@bman654/clodex 2.8.4 → 2.9.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 +59 -16
- package/dist/cli.js +361 -122
- package/dist/cli.js.map +1 -1
- package/docs/background-agents.md +4 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -382,7 +382,7 @@ import { join } from "path";
|
|
|
382
382
|
// package.json
|
|
383
383
|
var package_default = {
|
|
384
384
|
name: "@bman654/clodex",
|
|
385
|
-
version: "2.
|
|
385
|
+
version: "2.9.0",
|
|
386
386
|
publishConfig: {
|
|
387
387
|
access: "public"
|
|
388
388
|
},
|
|
@@ -3423,7 +3423,7 @@ function savedStopsAfter(current, assignments) {
|
|
|
3423
3423
|
}
|
|
3424
3424
|
|
|
3425
3425
|
// src/patch-transforms.ts
|
|
3426
|
-
var PATCH_TRANSFORMS_VERSION =
|
|
3426
|
+
var PATCH_TRANSFORMS_VERSION = 12;
|
|
3427
3427
|
var NATIVE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
3428
3428
|
var BASE_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
3429
3429
|
function projectNativeEffort(effort) {
|
|
@@ -3812,7 +3812,7 @@ function applyClodexPatches(source, config) {
|
|
|
3812
3812
|
}
|
|
3813
3813
|
applyOnce(
|
|
3814
3814
|
patchName,
|
|
3815
|
-
/(function [\w$]+\(\)\{)(let (?:[^;{}]|\{[^;{}]*\})*?[\w$]+\(process\.env\.CLAUDE_CODE_REMOTE\)\?(?:(?!\}\s*function )[\s\S])*?\)return process\.env;let ([\w$]+)=\{(?:(?!\}\s*function )[\s\S])*?return \3)(\})/,
|
|
3815
|
+
/(function [\w$]+\(\)\{)(let[ {[](?:[^;{}]|\{[^;{}]*\})*?(?:\{[^;{}]*)?(?:getAgentProxyEnv|[\w$]+\(process\.env\.CLAUDE_CODE_REMOTE\)\?)(?:(?!\}\s*function )[\s\S])*?\)return process\.env;let ([\w$]+)=\{(?:(?!\}\s*function )[\s\S])*?return \3)(\})/,
|
|
3816
3816
|
(match, head, body, _copyVar, tail) => {
|
|
3817
3817
|
const at = js.indexOf(match);
|
|
3818
3818
|
const closingBrace = at < 0 ? -1 : blockEndIndex(js, at + head.length - 1);
|
|
@@ -3820,7 +3820,7 @@ function applyClodexPatches(source, config) {
|
|
|
3820
3820
|
const bound = braceScanFailed ? 0 : closingBrace - at - (match.length - 1);
|
|
3821
3821
|
const missingLiteral = requiredBodyLiterals.find((literal) => !body.includes(literal));
|
|
3822
3822
|
const scrubbedSeen = scrubbedEnvNames.filter((name) => body.includes(name));
|
|
3823
|
-
const why = missingLiteral !== void 0 ? "body does not contain " + missingLiteral : scrubbedSeen.length < MIN_SCRUBBED_ENV_NAMES ? "body
|
|
3823
|
+
const why = missingLiteral !== void 0 ? "body does not contain " + missingLiteral : scrubbedSeen.length < MIN_SCRUBBED_ENV_NAMES ? "body spells only " + scrubbedSeen.length + " of the " + scrubbedEnvNames.length + " known child-env names (expected at least " + MIN_SCRUBBED_ENV_NAMES + ")" : /\bfunction\s*[\w$]*\(/.test(body) ? "body declares a nested function" : braceScanFailed ? "the brace walk never reached the function's closing brace" : bound !== 0 ? "match ends " + Math.abs(bound) + " characters " + (bound > 0 ? "before" : "after") + " the end of the function it started in" : void 0;
|
|
3824
3824
|
if (why !== void 0) {
|
|
3825
3825
|
log12("FAIL", patchName, "target validation failed: " + why);
|
|
3826
3826
|
fail("clodex patch: child network environment target validation failed: " + why);
|
|
@@ -7066,7 +7066,7 @@ function resignMachOBinary(path) {
|
|
|
7066
7066
|
}
|
|
7067
7067
|
|
|
7068
7068
|
// src/bun-compiled-pointer.ts
|
|
7069
|
-
import { closeSync as closeSync3, openSync as openSync3, readSync as readSync2, writeSync as writeSync3 } from "fs";
|
|
7069
|
+
import { closeSync as closeSync3, fstatSync, openSync as openSync3, readSync as readSync2, writeSync as writeSync3 } from "fs";
|
|
7070
7070
|
var TWEAKCC_SCAN_STRIDE = 16384n;
|
|
7071
7071
|
var SCAN_CHUNK = 1 << 20;
|
|
7072
7072
|
var ELF_MAGIC = 1179403647;
|
|
@@ -7098,6 +7098,9 @@ function readElfLayout(fd) {
|
|
|
7098
7098
|
const shstrndx = ident.readUInt16LE(62);
|
|
7099
7099
|
if (shnum === 0 || phnum === 65535) return null;
|
|
7100
7100
|
if (shstrndx >= shnum || shentsize < 64 || phentsize < 56) return null;
|
|
7101
|
+
const fileSize = fstatSync(fd).size;
|
|
7102
|
+
const fits = (offset, length) => Number.isSafeInteger(offset) && offset >= 0 && length >= 0 && offset + length <= fileSize;
|
|
7103
|
+
if (!fits(Number(shoff), shnum * shentsize)) return null;
|
|
7101
7104
|
const shTable = readAt2(fd, shnum * shentsize, Number(shoff));
|
|
7102
7105
|
if (shTable.length !== shnum * shentsize) return null;
|
|
7103
7106
|
const raw = [];
|
|
@@ -7111,6 +7114,7 @@ function readElfLayout(fd) {
|
|
|
7111
7114
|
});
|
|
7112
7115
|
}
|
|
7113
7116
|
const strtab = raw[shstrndx];
|
|
7117
|
+
if (!fits(Number(strtab.offset), Number(strtab.size))) return null;
|
|
7114
7118
|
const names = readAt2(fd, Number(strtab.size), Number(strtab.offset));
|
|
7115
7119
|
const sections = raw.map((section) => {
|
|
7116
7120
|
const start = section.nameOffset;
|
|
@@ -7123,6 +7127,7 @@ function readElfLayout(fd) {
|
|
|
7123
7127
|
size: section.size
|
|
7124
7128
|
};
|
|
7125
7129
|
});
|
|
7130
|
+
if (!fits(Number(phoff), phnum * phentsize)) return null;
|
|
7126
7131
|
const phTable = readAt2(fd, phnum * phentsize, Number(phoff));
|
|
7127
7132
|
if (phTable.length !== phnum * phentsize) return null;
|
|
7128
7133
|
const segments = [];
|
|
@@ -7192,7 +7197,6 @@ function shimBunCompiledPointer(path) {
|
|
|
7192
7197
|
if (!segment) return null;
|
|
7193
7198
|
const needle = Buffer.alloc(8);
|
|
7194
7199
|
needle.writeBigUInt64LE(bun.addr);
|
|
7195
|
-
if (tweakccWouldFind(fd, segment, needle) !== null) return null;
|
|
7196
7200
|
const segmentStart = Number(segment.offset);
|
|
7197
7201
|
const segmentEnd = Number(segment.offset + segment.filesz);
|
|
7198
7202
|
const bunStart = Number(bun.offset);
|
|
@@ -7205,6 +7209,15 @@ function shimBunCompiledPointer(path) {
|
|
|
7205
7209
|
}
|
|
7206
7210
|
const pointerOffset = candidates[0];
|
|
7207
7211
|
const pointerVaddr = segment.vaddr + BigInt(pointerOffset) - segment.offset;
|
|
7212
|
+
const wouldFind = tweakccWouldFind(fd, segment, needle);
|
|
7213
|
+
if (wouldFind !== null) {
|
|
7214
|
+
if (wouldFind !== pointerVaddr) {
|
|
7215
|
+
throw new Error(
|
|
7216
|
+
`tweakcc's ELF repack would rewrite 0x${wouldFind.toString(16)}, which is not Bun's blob pointer at 0x${pointerVaddr.toString(16)}. Refusing to repack a binary whose Bun global would be left stale.`
|
|
7217
|
+
);
|
|
7218
|
+
}
|
|
7219
|
+
return null;
|
|
7220
|
+
}
|
|
7208
7221
|
const first = alignUp(segment.vaddr, TWEAKCC_SCAN_STRIDE);
|
|
7209
7222
|
const last = segment.vaddr + segment.filesz - 8n;
|
|
7210
7223
|
let standInVaddr = null;
|
|
@@ -7241,7 +7254,11 @@ function restoreBunCompiledPointer(path, shim) {
|
|
|
7241
7254
|
"the repack left Bun's blob pointer outside the loaded image, or in more than one segment of it"
|
|
7242
7255
|
);
|
|
7243
7256
|
}
|
|
7244
|
-
const
|
|
7257
|
+
const standIn = readAt2(fd, 8, standInOffset);
|
|
7258
|
+
if (standIn.length !== 8) {
|
|
7259
|
+
throw new Error("the repacked binary ends before the stand-in for Bun's blob pointer");
|
|
7260
|
+
}
|
|
7261
|
+
const written = standIn.readBigUInt64LE(0);
|
|
7245
7262
|
if (written === shim.bunVaddr) {
|
|
7246
7263
|
throw new Error("the repack did not rewrite Bun's blob pointer \u2014 the stand-in was not used");
|
|
7247
7264
|
}
|
|
@@ -10911,43 +10928,152 @@ function resolveUpstreamTools(tools, messages) {
|
|
|
10911
10928
|
|
|
10912
10929
|
// src/upstream-retry.ts
|
|
10913
10930
|
var UPSTREAM_MAX_RETRIES_ENV = "CLODEX_UPSTREAM_MAX_RETRIES";
|
|
10914
|
-
var
|
|
10931
|
+
var UPSTREAM_IDLE_TIMEOUT_ENV = "CLODEX_UPSTREAM_IDLE_TIMEOUT_MS";
|
|
10932
|
+
var UPSTREAM_TOTAL_TIMEOUT_ENV = "CLODEX_UPSTREAM_TOTAL_TIMEOUT_MS";
|
|
10933
|
+
var DEFAULT_UPSTREAM_IDLE_TIMEOUT_MS = 12e4;
|
|
10934
|
+
var DEFAULT_UPSTREAM_TOTAL_TIMEOUT_MS = 10 * 6e4;
|
|
10935
|
+
var MIN_UPSTREAM_IDLE_TIMEOUT_MS = 1e4;
|
|
10936
|
+
var MAX_UPSTREAM_IDLE_TIMEOUT_MS = 60 * 6e4;
|
|
10937
|
+
var MIN_UPSTREAM_TOTAL_TIMEOUT_MS = 6e4;
|
|
10938
|
+
var MAX_UPSTREAM_TOTAL_TIMEOUT_MS = 6 * 60 * 6e4;
|
|
10939
|
+
var SDK_INITIAL_RETRY_DELAY_MS = 2e3;
|
|
10915
10940
|
var reportedValues = /* @__PURE__ */ new Set();
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
reportedValues.
|
|
10941
|
+
var defaultWarn = (message) => emitParentNotice(`clodex: ${message}`);
|
|
10942
|
+
function reportOnce(key, message, warn) {
|
|
10943
|
+
if (reportedValues.has(key)) return;
|
|
10944
|
+
reportedValues.add(key);
|
|
10919
10945
|
try {
|
|
10920
10946
|
warn(message);
|
|
10921
10947
|
} catch {
|
|
10922
10948
|
}
|
|
10923
10949
|
}
|
|
10924
|
-
function
|
|
10950
|
+
function timeoutSetting(env, envName, fallback, min, max, warn) {
|
|
10951
|
+
const raw = env[envName]?.trim();
|
|
10952
|
+
if (raw === void 0 || raw === "") return { value: fallback, explicit: false };
|
|
10953
|
+
const value = Number(raw);
|
|
10954
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
10955
|
+
reportOnce(
|
|
10956
|
+
`${envName}=${raw}`,
|
|
10957
|
+
`ignoring ${envName}=${raw} (expected a positive integer number of milliseconds)`,
|
|
10958
|
+
warn
|
|
10959
|
+
);
|
|
10960
|
+
return { value: fallback, explicit: false };
|
|
10961
|
+
}
|
|
10962
|
+
if (value < min || value > max) {
|
|
10963
|
+
const clamped = Math.min(max, Math.max(min, value));
|
|
10964
|
+
reportOnce(
|
|
10965
|
+
`${envName}=${raw}`,
|
|
10966
|
+
`clamping ${envName}=${raw} to ${clamped}ms (supported range is ${min}-${max}ms)`,
|
|
10967
|
+
warn
|
|
10968
|
+
);
|
|
10969
|
+
return { value: clamped, explicit: true };
|
|
10970
|
+
}
|
|
10971
|
+
return { value, explicit: true };
|
|
10972
|
+
}
|
|
10973
|
+
function maxRetriesForIdleTimeout(idleTimeoutMs) {
|
|
10974
|
+
let retries = 0;
|
|
10975
|
+
let elapsedMs = 0;
|
|
10976
|
+
let delayMs = SDK_INITIAL_RETRY_DELAY_MS;
|
|
10977
|
+
while (elapsedMs + delayMs < idleTimeoutMs) {
|
|
10978
|
+
elapsedMs += delayMs;
|
|
10979
|
+
delayMs *= 2;
|
|
10980
|
+
retries += 1;
|
|
10981
|
+
}
|
|
10982
|
+
return retries;
|
|
10983
|
+
}
|
|
10984
|
+
var MAX_UPSTREAM_MAX_RETRIES = maxRetriesForIdleTimeout(
|
|
10985
|
+
DEFAULT_UPSTREAM_IDLE_TIMEOUT_MS
|
|
10986
|
+
);
|
|
10987
|
+
var DEFAULT_UPSTREAM_MAX_RETRIES = MAX_UPSTREAM_MAX_RETRIES;
|
|
10988
|
+
function configuredUpstreamMaxRetries(env, warn) {
|
|
10925
10989
|
const raw = env[UPSTREAM_MAX_RETRIES_ENV]?.trim();
|
|
10926
10990
|
if (raw === void 0 || raw === "") return void 0;
|
|
10927
10991
|
const value = Number(raw);
|
|
10928
10992
|
if (!Number.isInteger(value) || value < 0) {
|
|
10929
10993
|
reportOnce(
|
|
10930
|
-
raw
|
|
10994
|
+
`${UPSTREAM_MAX_RETRIES_ENV}=${raw}`,
|
|
10931
10995
|
`ignoring ${UPSTREAM_MAX_RETRIES_ENV}=${raw} (expected a non-negative integer)`,
|
|
10932
10996
|
warn
|
|
10933
10997
|
);
|
|
10934
10998
|
return void 0;
|
|
10935
10999
|
}
|
|
10936
|
-
|
|
11000
|
+
return value;
|
|
11001
|
+
}
|
|
11002
|
+
function resolveUpstreamMaxRetries(env, warn, idleTimeoutMs) {
|
|
11003
|
+
const ceiling = maxRetriesForIdleTimeout(idleTimeoutMs);
|
|
11004
|
+
const defaultRetries = Math.min(DEFAULT_UPSTREAM_MAX_RETRIES, ceiling);
|
|
11005
|
+
const value = configuredUpstreamMaxRetries(env, warn);
|
|
11006
|
+
if (value === void 0) return defaultRetries;
|
|
11007
|
+
if (value > ceiling) {
|
|
10937
11008
|
reportOnce(
|
|
10938
|
-
|
|
10939
|
-
`clamping ${UPSTREAM_MAX_RETRIES_ENV}=${
|
|
11009
|
+
`${UPSTREAM_MAX_RETRIES_ENV}=${value}:idle=${idleTimeoutMs}`,
|
|
11010
|
+
`clamping ${UPSTREAM_MAX_RETRIES_ENV}=${value} to ${ceiling} (estimated from the SDK fallback backoff and resolved ${idleTimeoutMs}ms idle timeout; provider delays may allow fewer retries)`,
|
|
10940
11011
|
warn
|
|
10941
11012
|
);
|
|
10942
|
-
return
|
|
11013
|
+
return ceiling;
|
|
10943
11014
|
}
|
|
10944
11015
|
return value;
|
|
10945
11016
|
}
|
|
11017
|
+
function upstreamRequestBudget(options = {}) {
|
|
11018
|
+
const env = options.env ?? process.env;
|
|
11019
|
+
const warn = options.warn ?? defaultWarn;
|
|
11020
|
+
const hasIdleOverride = options.idleTimeoutMs !== void 0;
|
|
11021
|
+
const configuredIdle = options.idleTimeoutMs !== void 0 ? { value: options.idleTimeoutMs, explicit: false } : timeoutSetting(
|
|
11022
|
+
env,
|
|
11023
|
+
UPSTREAM_IDLE_TIMEOUT_ENV,
|
|
11024
|
+
DEFAULT_UPSTREAM_IDLE_TIMEOUT_MS,
|
|
11025
|
+
MIN_UPSTREAM_IDLE_TIMEOUT_MS,
|
|
11026
|
+
MAX_UPSTREAM_IDLE_TIMEOUT_MS,
|
|
11027
|
+
warn
|
|
11028
|
+
);
|
|
11029
|
+
const configuredTotal = timeoutSetting(
|
|
11030
|
+
env,
|
|
11031
|
+
UPSTREAM_TOTAL_TIMEOUT_ENV,
|
|
11032
|
+
DEFAULT_UPSTREAM_TOTAL_TIMEOUT_MS,
|
|
11033
|
+
MIN_UPSTREAM_TOTAL_TIMEOUT_MS,
|
|
11034
|
+
MAX_UPSTREAM_TOTAL_TIMEOUT_MS,
|
|
11035
|
+
warn
|
|
11036
|
+
);
|
|
11037
|
+
let idleTimeoutMs = configuredIdle.value;
|
|
11038
|
+
let totalTimeoutMs = configuredTotal.value;
|
|
11039
|
+
if (totalTimeoutMs < idleTimeoutMs) {
|
|
11040
|
+
if (hasIdleOverride) {
|
|
11041
|
+
idleTimeoutMs = totalTimeoutMs;
|
|
11042
|
+
} else if (configuredIdle.explicit && !configuredTotal.explicit) {
|
|
11043
|
+
reportOnce(
|
|
11044
|
+
`timeout-pair:raise-total:${idleTimeoutMs}:${totalTimeoutMs}`,
|
|
11045
|
+
`raising the resolved total timeout from ${totalTimeoutMs}ms to ${idleTimeoutMs}ms so it is not shorter than ${UPSTREAM_IDLE_TIMEOUT_ENV}`,
|
|
11046
|
+
warn
|
|
11047
|
+
);
|
|
11048
|
+
totalTimeoutMs = idleTimeoutMs;
|
|
11049
|
+
} else {
|
|
11050
|
+
reportOnce(
|
|
11051
|
+
`timeout-pair:lower-idle:${idleTimeoutMs}:${totalTimeoutMs}`,
|
|
11052
|
+
`lowering the resolved idle timeout from ${idleTimeoutMs}ms to ${totalTimeoutMs}ms because it cannot exceed ${UPSTREAM_TOTAL_TIMEOUT_ENV}`,
|
|
11053
|
+
warn
|
|
11054
|
+
);
|
|
11055
|
+
idleTimeoutMs = totalTimeoutMs;
|
|
11056
|
+
}
|
|
11057
|
+
}
|
|
11058
|
+
return {
|
|
11059
|
+
idleTimeoutMs,
|
|
11060
|
+
totalTimeoutMs,
|
|
11061
|
+
maxRetries: resolveUpstreamMaxRetries(env, warn, idleTimeoutMs)
|
|
11062
|
+
};
|
|
11063
|
+
}
|
|
10946
11064
|
var CLIENT_MAX_RETRIES_ENV = "CLAUDE_CODE_MAX_RETRIES";
|
|
10947
11065
|
var DEFAULT_PASSTHROUGH_RETRIES = 1;
|
|
10948
|
-
function passthroughUpstreamRetries(env = process.env) {
|
|
10949
|
-
const explicit =
|
|
10950
|
-
if (explicit !== void 0)
|
|
11066
|
+
function passthroughUpstreamRetries(env = process.env, warn = defaultWarn) {
|
|
11067
|
+
const explicit = configuredUpstreamMaxRetries(env, warn);
|
|
11068
|
+
if (explicit !== void 0) {
|
|
11069
|
+
if (explicit <= MAX_UPSTREAM_MAX_RETRIES) return explicit;
|
|
11070
|
+
reportOnce(
|
|
11071
|
+
`${UPSTREAM_MAX_RETRIES_ENV}=${explicit}:passthrough`,
|
|
11072
|
+
`clamping ${UPSTREAM_MAX_RETRIES_ENV}=${explicit} to ${MAX_UPSTREAM_MAX_RETRIES} (the raw HTTP MITM path supports at most this many replays)`,
|
|
11073
|
+
warn
|
|
11074
|
+
);
|
|
11075
|
+
return MAX_UPSTREAM_MAX_RETRIES;
|
|
11076
|
+
}
|
|
10951
11077
|
const raw = env[CLIENT_MAX_RETRIES_ENV]?.trim();
|
|
10952
11078
|
if (raw !== void 0 && raw !== "") {
|
|
10953
11079
|
const clientRetries = Number(raw);
|
|
@@ -10956,6 +11082,49 @@ function passthroughUpstreamRetries(env = process.env) {
|
|
|
10956
11082
|
return DEFAULT_PASSTHROUGH_RETRIES;
|
|
10957
11083
|
}
|
|
10958
11084
|
|
|
11085
|
+
// src/upstream-attempts.ts
|
|
11086
|
+
import { RetryError as RetryError2, wrapLanguageModel as wrapLanguageModel2 } from "ai";
|
|
11087
|
+
function trackUpstreamAttempts(model) {
|
|
11088
|
+
if (typeof model === "string") {
|
|
11089
|
+
return { model, deadlineError: (timeoutError) => timeoutError };
|
|
11090
|
+
}
|
|
11091
|
+
const failedAttempts = [];
|
|
11092
|
+
let waitingToRetry = false;
|
|
11093
|
+
const track = async (call) => {
|
|
11094
|
+
waitingToRetry = false;
|
|
11095
|
+
try {
|
|
11096
|
+
const result = await call();
|
|
11097
|
+
failedAttempts.length = 0;
|
|
11098
|
+
return result;
|
|
11099
|
+
} catch (error) {
|
|
11100
|
+
failedAttempts.push(error);
|
|
11101
|
+
waitingToRetry = true;
|
|
11102
|
+
throw error;
|
|
11103
|
+
}
|
|
11104
|
+
};
|
|
11105
|
+
const middleware = {
|
|
11106
|
+
specificationVersion: "v4",
|
|
11107
|
+
wrapGenerate: ({ doGenerate }) => track(doGenerate),
|
|
11108
|
+
wrapStream: ({ doStream }) => track(doStream)
|
|
11109
|
+
};
|
|
11110
|
+
return {
|
|
11111
|
+
model: wrapLanguageModel2({ model, middleware }),
|
|
11112
|
+
deadlineError: (timeoutError) => {
|
|
11113
|
+
if (!waitingToRetry || failedAttempts.length === 0) return timeoutError;
|
|
11114
|
+
const count = failedAttempts.length;
|
|
11115
|
+
return new RetryError2({
|
|
11116
|
+
message: [
|
|
11117
|
+
"Provider retry interrupted by a request deadline after",
|
|
11118
|
+
count,
|
|
11119
|
+
`failed ${count === 1 ? "attempt" : "attempts"}`
|
|
11120
|
+
].join(" "),
|
|
11121
|
+
reason: "abort",
|
|
11122
|
+
errors: [...failedAttempts]
|
|
11123
|
+
});
|
|
11124
|
+
}
|
|
11125
|
+
};
|
|
11126
|
+
}
|
|
11127
|
+
|
|
10959
11128
|
// src/sdk-adapter.ts
|
|
10960
11129
|
function sdkTranslationErrorSignature(error) {
|
|
10961
11130
|
const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
|
|
@@ -11330,8 +11499,6 @@ function toAnthropicUsage(u) {
|
|
|
11330
11499
|
cache_read_input_tokens: cacheRead
|
|
11331
11500
|
};
|
|
11332
11501
|
}
|
|
11333
|
-
var SDK_STREAM_IDLE_TIMEOUT_MS = 12e4;
|
|
11334
|
-
var SDK_TOTAL_TIMEOUT_MS = 10 * 6e4;
|
|
11335
11502
|
function streamAbortError(signal) {
|
|
11336
11503
|
if (signal?.reason instanceof Error) return signal.reason;
|
|
11337
11504
|
const error = new Error(
|
|
@@ -11552,42 +11719,44 @@ async function writeAnthropicStream(stream, modelId, write, log12, observer, too
|
|
|
11552
11719
|
emit("message_stop", { type: "message_stop" });
|
|
11553
11720
|
}
|
|
11554
11721
|
async function streamAnthropicResponse(model, params, modelId, write, log12, observer) {
|
|
11555
|
-
const idleTimeoutMs
|
|
11722
|
+
const { idleTimeoutMs, totalTimeoutMs, maxRetries } = upstreamRequestBudget({
|
|
11723
|
+
idleTimeoutMs: observer?.idleTimeoutMs
|
|
11724
|
+
});
|
|
11725
|
+
const attempts = trackUpstreamAttempts(model);
|
|
11556
11726
|
const idleAbort = new AbortController();
|
|
11557
11727
|
const stopForwardingAbort = forwardAbortSignal(observer?.abortSignal, idleAbort);
|
|
11558
11728
|
const abortSignal = idleAbort.signal;
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
idleTimeoutMs
|
|
11729
|
+
const idleError = () => attempts.deadlineError(
|
|
11730
|
+
new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)
|
|
11562
11731
|
);
|
|
11732
|
+
let idleTimer = setTimeout(() => idleAbort.abort(idleError()), idleTimeoutMs);
|
|
11563
11733
|
const totalTimer = setTimeout(
|
|
11564
|
-
() => idleAbort.abort(
|
|
11565
|
-
|
|
11734
|
+
() => idleAbort.abort(attempts.deadlineError(
|
|
11735
|
+
new Error(`provider stream exceeded ${Math.round(totalTimeoutMs / 1e3)}s`)
|
|
11736
|
+
)),
|
|
11737
|
+
totalTimeoutMs
|
|
11566
11738
|
);
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11739
|
+
try {
|
|
11740
|
+
const result = streamText({
|
|
11741
|
+
model: attempts.model,
|
|
11742
|
+
...params,
|
|
11743
|
+
maxRetries,
|
|
11744
|
+
abortSignal,
|
|
11745
|
+
onError: () => {
|
|
11746
|
+
},
|
|
11747
|
+
onStepFinish: (step) => reportUnsupportedServiceTier(params, step.warnings)
|
|
11748
|
+
});
|
|
11749
|
+
const watchedStream = (async function* () {
|
|
11750
|
+
try {
|
|
11751
|
+
for await (const part of result.stream) {
|
|
11752
|
+
clearTimeout(idleTimer);
|
|
11753
|
+
idleTimer = setTimeout(() => idleAbort.abort(idleError()), idleTimeoutMs);
|
|
11754
|
+
yield part;
|
|
11755
|
+
}
|
|
11756
|
+
} finally {
|
|
11579
11757
|
clearTimeout(idleTimer);
|
|
11580
|
-
idleTimer = setTimeout(
|
|
11581
|
-
() => idleAbort.abort(new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)),
|
|
11582
|
-
idleTimeoutMs
|
|
11583
|
-
);
|
|
11584
|
-
yield part;
|
|
11585
11758
|
}
|
|
11586
|
-
}
|
|
11587
|
-
clearTimeout(idleTimer);
|
|
11588
|
-
}
|
|
11589
|
-
})();
|
|
11590
|
-
try {
|
|
11759
|
+
})();
|
|
11591
11760
|
await writeAnthropicStream(watchedStream, modelId, write, log12, { ...observer, abortSignal }, params.tools);
|
|
11592
11761
|
} finally {
|
|
11593
11762
|
stopForwardingAbort();
|
|
@@ -11602,39 +11771,41 @@ async function generateAnthropicResponse(model, params, modelId, options) {
|
|
|
11602
11771
|
let finishReason;
|
|
11603
11772
|
let usage;
|
|
11604
11773
|
let warnings;
|
|
11774
|
+
const { idleTimeoutMs, totalTimeoutMs, maxRetries } = upstreamRequestBudget({
|
|
11775
|
+
idleTimeoutMs: options?.forceStream ? options.idleTimeoutMs : void 0
|
|
11776
|
+
});
|
|
11777
|
+
const attempts = trackUpstreamAttempts(model);
|
|
11605
11778
|
if (options?.forceStream) {
|
|
11606
11779
|
const forceAbort = new AbortController();
|
|
11607
11780
|
const stopForwardingAbort = forwardAbortSignal(options.abortSignal, forceAbort);
|
|
11608
11781
|
const abortSignal = forceAbort.signal;
|
|
11609
|
-
const
|
|
11610
|
-
|
|
11611
|
-
() => forceAbort.abort(new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)),
|
|
11612
|
-
idleTimeoutMs
|
|
11782
|
+
const idleError = () => attempts.deadlineError(
|
|
11783
|
+
new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)
|
|
11613
11784
|
);
|
|
11785
|
+
let idleTimer = setTimeout(() => forceAbort.abort(idleError()), idleTimeoutMs);
|
|
11614
11786
|
const totalTimer = setTimeout(
|
|
11615
|
-
() => forceAbort.abort(
|
|
11616
|
-
|
|
11787
|
+
() => forceAbort.abort(attempts.deadlineError(
|
|
11788
|
+
new Error(`provider stream exceeded ${Math.round(totalTimeoutMs / 1e3)}s`)
|
|
11789
|
+
)),
|
|
11790
|
+
totalTimeoutMs
|
|
11617
11791
|
);
|
|
11618
|
-
const r = streamText({
|
|
11619
|
-
model,
|
|
11620
|
-
...params,
|
|
11621
|
-
maxRetries: upstreamMaxRetries(),
|
|
11622
|
-
abortSignal,
|
|
11623
|
-
onError: () => {
|
|
11624
|
-
},
|
|
11625
|
-
onStepFinish: (step) => reportUnsupportedServiceTier(params, step.warnings)
|
|
11626
|
-
});
|
|
11627
11792
|
const streamedText = [];
|
|
11628
11793
|
const streamedToolCalls = [];
|
|
11629
11794
|
let streamedFinishReason = "stop";
|
|
11630
11795
|
let streamedUsage;
|
|
11631
11796
|
try {
|
|
11797
|
+
const r = streamText({
|
|
11798
|
+
model: attempts.model,
|
|
11799
|
+
...params,
|
|
11800
|
+
maxRetries,
|
|
11801
|
+
abortSignal,
|
|
11802
|
+
onError: () => {
|
|
11803
|
+
},
|
|
11804
|
+
onStepFinish: (step) => reportUnsupportedServiceTier(params, step.warnings)
|
|
11805
|
+
});
|
|
11632
11806
|
for await (const part of r.stream) {
|
|
11633
11807
|
clearTimeout(idleTimer);
|
|
11634
|
-
idleTimer = setTimeout(
|
|
11635
|
-
() => forceAbort.abort(new Error(`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`)),
|
|
11636
|
-
idleTimeoutMs
|
|
11637
|
-
);
|
|
11808
|
+
idleTimer = setTimeout(() => forceAbort.abort(idleError()), idleTimeoutMs);
|
|
11638
11809
|
options.onPart?.(part.type);
|
|
11639
11810
|
if (abortSignal.aborted || part.type === "abort") {
|
|
11640
11811
|
throw streamAbortError(abortSignal);
|
|
@@ -11669,17 +11840,22 @@ async function generateAnthropicResponse(model, params, modelId, options) {
|
|
|
11669
11840
|
const generateAbort = new AbortController();
|
|
11670
11841
|
const stopForwardingAbort = forwardAbortSignal(options?.abortSignal, generateAbort);
|
|
11671
11842
|
const totalTimer = setTimeout(
|
|
11672
|
-
() => generateAbort.abort(
|
|
11673
|
-
|
|
11843
|
+
() => generateAbort.abort(attempts.deadlineError(
|
|
11844
|
+
new Error(`provider request exceeded ${Math.round(totalTimeoutMs / 1e3)}s`)
|
|
11845
|
+
)),
|
|
11846
|
+
totalTimeoutMs
|
|
11674
11847
|
);
|
|
11675
11848
|
try {
|
|
11676
11849
|
const r = await generateText({
|
|
11677
|
-
model,
|
|
11850
|
+
model: attempts.model,
|
|
11678
11851
|
...params,
|
|
11679
|
-
maxRetries
|
|
11852
|
+
maxRetries,
|
|
11680
11853
|
abortSignal: generateAbort.signal
|
|
11681
11854
|
});
|
|
11682
11855
|
({ text: text5, toolCalls, finishReason, usage, warnings } = r);
|
|
11856
|
+
} catch (error) {
|
|
11857
|
+
if (generateAbort.signal.aborted) throw streamAbortError(generateAbort.signal);
|
|
11858
|
+
throw error;
|
|
11683
11859
|
} finally {
|
|
11684
11860
|
stopForwardingAbort();
|
|
11685
11861
|
clearTimeout(totalTimer);
|
|
@@ -13516,7 +13692,7 @@ import { randomUUID as randomUUID4 } from "crypto";
|
|
|
13516
13692
|
import {
|
|
13517
13693
|
closeSync as closeSync7,
|
|
13518
13694
|
existsSync as existsSync6,
|
|
13519
|
-
fstatSync,
|
|
13695
|
+
fstatSync as fstatSync2,
|
|
13520
13696
|
fsyncSync as fsyncSync2,
|
|
13521
13697
|
lstatSync,
|
|
13522
13698
|
mkdirSync as mkdirSync6,
|
|
@@ -13613,7 +13789,7 @@ function readJournalUnlocked(path) {
|
|
|
13613
13789
|
throw new Error("Credential cleanup journal must be a regular file.");
|
|
13614
13790
|
}
|
|
13615
13791
|
fd = openSync7(path, "r");
|
|
13616
|
-
const opened =
|
|
13792
|
+
const opened = fstatSync2(fd);
|
|
13617
13793
|
if (before.dev !== opened.dev || before.ino !== opened.ino) {
|
|
13618
13794
|
throw new Error("Credential cleanup journal changed while opening.");
|
|
13619
13795
|
}
|
|
@@ -16653,24 +16829,81 @@ async function collectOpenAiStream(stream) {
|
|
|
16653
16829
|
}
|
|
16654
16830
|
return collected;
|
|
16655
16831
|
}
|
|
16832
|
+
function startUpstreamBudget(model, streaming) {
|
|
16833
|
+
const { idleTimeoutMs, totalTimeoutMs, maxRetries } = upstreamRequestBudget();
|
|
16834
|
+
const attempts = trackUpstreamAttempts(model);
|
|
16835
|
+
const abort = new AbortController();
|
|
16836
|
+
const idleError = () => attempts.deadlineError(new Error(
|
|
16837
|
+
`no data received from provider for ${Math.round(idleTimeoutMs / 1e3)}s`
|
|
16838
|
+
));
|
|
16839
|
+
let idleTimer = streaming ? setTimeout(() => abort.abort(idleError()), idleTimeoutMs) : void 0;
|
|
16840
|
+
const totalTimer = setTimeout(
|
|
16841
|
+
() => abort.abort(attempts.deadlineError(new Error(
|
|
16842
|
+
`provider ${streaming ? "stream" : "request"} exceeded ${Math.round(totalTimeoutMs / 1e3)}s`
|
|
16843
|
+
))),
|
|
16844
|
+
totalTimeoutMs
|
|
16845
|
+
);
|
|
16846
|
+
return {
|
|
16847
|
+
model: attempts.model,
|
|
16848
|
+
maxRetries,
|
|
16849
|
+
abortSignal: abort.signal,
|
|
16850
|
+
onStreamPart: () => {
|
|
16851
|
+
if (idleTimer === void 0) return;
|
|
16852
|
+
clearTimeout(idleTimer);
|
|
16853
|
+
idleTimer = setTimeout(() => abort.abort(idleError()), idleTimeoutMs);
|
|
16854
|
+
},
|
|
16855
|
+
close: () => {
|
|
16856
|
+
if (idleTimer !== void 0) clearTimeout(idleTimer);
|
|
16857
|
+
clearTimeout(totalTimer);
|
|
16858
|
+
if (!abort.signal.aborted) abort.abort();
|
|
16859
|
+
}
|
|
16860
|
+
};
|
|
16861
|
+
}
|
|
16862
|
+
async function* watchOpenAiStream(stream, budget) {
|
|
16863
|
+
for await (const part of stream) {
|
|
16864
|
+
if (budget.abortSignal.aborted || part.type === "abort") {
|
|
16865
|
+
throw budget.abortSignal.reason instanceof Error ? budget.abortSignal.reason : new Error("SDK stream aborted");
|
|
16866
|
+
}
|
|
16867
|
+
budget.onStreamPart();
|
|
16868
|
+
yield part;
|
|
16869
|
+
}
|
|
16870
|
+
if (budget.abortSignal.aborted) {
|
|
16871
|
+
throw budget.abortSignal.reason instanceof Error ? budget.abortSignal.reason : new Error("SDK stream aborted");
|
|
16872
|
+
}
|
|
16873
|
+
}
|
|
16656
16874
|
async function generateOpenAiResponse(model, params, responseModelId, options) {
|
|
16657
16875
|
let result;
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
16661
|
-
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16665
|
-
|
|
16666
|
-
|
|
16667
|
-
|
|
16668
|
-
|
|
16669
|
-
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16876
|
+
const streaming = options?.forceStream === true;
|
|
16877
|
+
const budget = startUpstreamBudget(model, streaming);
|
|
16878
|
+
try {
|
|
16879
|
+
if (streaming) {
|
|
16880
|
+
const { stream } = streamText2({
|
|
16881
|
+
model: budget.model,
|
|
16882
|
+
...params,
|
|
16883
|
+
maxRetries: budget.maxRetries,
|
|
16884
|
+
abortSignal: budget.abortSignal,
|
|
16885
|
+
onError: () => {
|
|
16886
|
+
},
|
|
16887
|
+
onStepFinish: (step) => reportUnsupportedServiceTier(params, step.warnings)
|
|
16888
|
+
});
|
|
16889
|
+
result = await collectOpenAiStream(watchOpenAiStream(stream, budget));
|
|
16890
|
+
} else {
|
|
16891
|
+
try {
|
|
16892
|
+
result = await generateText2({
|
|
16893
|
+
model: budget.model,
|
|
16894
|
+
...params,
|
|
16895
|
+
maxRetries: budget.maxRetries,
|
|
16896
|
+
abortSignal: budget.abortSignal
|
|
16897
|
+
});
|
|
16898
|
+
} catch (error) {
|
|
16899
|
+
if (budget.abortSignal.aborted && budget.abortSignal.reason instanceof Error) {
|
|
16900
|
+
throw budget.abortSignal.reason;
|
|
16901
|
+
}
|
|
16902
|
+
throw error;
|
|
16903
|
+
}
|
|
16904
|
+
}
|
|
16905
|
+
} finally {
|
|
16906
|
+
budget.close();
|
|
16674
16907
|
}
|
|
16675
16908
|
reportUnsupportedServiceTier(params, result.warnings);
|
|
16676
16909
|
const message = { role: "assistant", content: result.text || null };
|
|
@@ -16695,41 +16928,47 @@ async function generateOpenAiResponse(model, params, responseModelId, options) {
|
|
|
16695
16928
|
};
|
|
16696
16929
|
}
|
|
16697
16930
|
async function streamOpenAiResponse(model, params, responseModelId, onChunk) {
|
|
16698
|
-
const
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16931
|
+
const budget = startUpstreamBudget(model, true);
|
|
16932
|
+
try {
|
|
16933
|
+
const { stream } = streamText2({
|
|
16934
|
+
model: budget.model,
|
|
16935
|
+
...params,
|
|
16936
|
+
maxRetries: budget.maxRetries,
|
|
16937
|
+
abortSignal: budget.abortSignal,
|
|
16938
|
+
onStepFinish: (step) => reportUnsupportedServiceTier(params, step.warnings)
|
|
16939
|
+
});
|
|
16940
|
+
const baseData = {
|
|
16941
|
+
id: `chatcmpl-${Date.now()}`,
|
|
16942
|
+
object: "chat.completion.chunk",
|
|
16943
|
+
created: Math.floor(Date.now() / 1e3),
|
|
16944
|
+
model: responseModelId
|
|
16945
|
+
};
|
|
16946
|
+
const send = (delta, finish_reason = null) => onChunk(`data: ${JSON.stringify({ ...baseData, choices: [{ index: 0, delta, finish_reason }] })}
|
|
16711
16947
|
|
|
16712
16948
|
`);
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16949
|
+
for await (const part of watchOpenAiStream(stream, budget)) {
|
|
16950
|
+
const p13 = part;
|
|
16951
|
+
switch (p13.type) {
|
|
16952
|
+
case "text-delta":
|
|
16953
|
+
send({ role: "assistant", content: p13.textDelta ?? p13.text ?? "" });
|
|
16954
|
+
break;
|
|
16955
|
+
case "tool-input-start":
|
|
16956
|
+
send({ role: "assistant", tool_calls: [{ index: 0, id: p13.id ?? p13.toolCallId, type: "function", function: { name: p13.toolName, arguments: "" } }] });
|
|
16957
|
+
break;
|
|
16958
|
+
case "tool-input-delta":
|
|
16959
|
+
send({ tool_calls: [{ index: 0, function: { arguments: p13.delta ?? p13.text ?? p13.argsTextDelta ?? "" } }] });
|
|
16960
|
+
break;
|
|
16961
|
+
case "finish":
|
|
16962
|
+
send({}, p13.finishReason || "stop");
|
|
16963
|
+
break;
|
|
16964
|
+
case "error":
|
|
16965
|
+
throw p13.error instanceof Error || p13.error && typeof p13.error === "object" ? p13.error : new Error(typeof p13.error === "string" ? p13.error : "Upstream stream failed");
|
|
16966
|
+
}
|
|
16730
16967
|
}
|
|
16968
|
+
onChunk("data: [DONE]\n\n");
|
|
16969
|
+
} finally {
|
|
16970
|
+
budget.close();
|
|
16731
16971
|
}
|
|
16732
|
-
onChunk("data: [DONE]\n\n");
|
|
16733
16972
|
}
|
|
16734
16973
|
|
|
16735
16974
|
// src/server/router.ts
|