@bman654/clodex 2.15.0 → 2.16.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 +11 -1
- package/dist/cli.js +154 -27
- package/dist/cli.js.map +1 -1
- package/docs/opencode-go.md +3 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -276,6 +276,16 @@ Two things worth knowing about the numbers:
|
|
|
276
276
|
number first only costs usable context. A provider that declares a share of its own
|
|
277
277
|
is still honoured; clodex just never invents one. Use `--context` if you want a
|
|
278
278
|
smaller window than the provider offers.
|
|
279
|
+
- **A window nobody published is not a ceiling.** Some servers list their models
|
|
280
|
+
without saying how much context each one takes. Clodex reports the 200,000 Claude
|
|
281
|
+
Code assumes anyway, but that number is a guess, not a measurement — so
|
|
282
|
+
`clodex models --context <model>=1m --save` raises it instead of being clamped back
|
|
283
|
+
down to the guess. Clamping still applies in full wherever a window *is* published,
|
|
284
|
+
by the provider or by clodex's own catalog. If the model is already baked into a
|
|
285
|
+
patched binary, re-run `clodex patch` so it picks the new window up. Set this model up
|
|
286
|
+
before this version? Run `clodex providers refresh-models <provider>` once — an older
|
|
287
|
+
clodex stored the guess as if the server had published it, and until you refresh it is
|
|
288
|
+
indistinguishable from a real limit and still clamps.
|
|
279
289
|
- **The account ceiling moves.** It is server-side and per-account, and it has
|
|
280
290
|
changed by more than 2x within a single day in the past. `max` reads whatever the
|
|
281
291
|
catalog reports now and clamps to it, so a stale ceiling shrinks the stop rather
|
|
@@ -292,7 +302,7 @@ Two things worth knowing about the numbers:
|
|
|
292
302
|
| `remove <id>` | Remove a provider by id |
|
|
293
303
|
| `refresh-models [id]` | Update cached model lists |
|
|
294
304
|
|
|
295
|
-
Providers supported: `openai` (API key, platform.openai.com), `openai-oauth` (ChatGPT/Codex plan), and `opencode-go` (OpenCode Go API key). OpenCode Go exposes its Anthropic Messages
|
|
305
|
+
Providers supported: `openai` (API key, platform.openai.com), `openai-oauth` (ChatGPT/Codex plan), and `opencode-go` (OpenCode Go API key). OpenCode Go exposes its Anthropic Messages, Chat Completions, and Responses models; entries whose transport has not been verified against the live endpoint are left out. See [OpenCode Go provider](docs/opencode-go.md).
|
|
296
306
|
|
|
297
307
|
A **custom OpenAI-compatible server** is any OpenAI-style API, given by its base URL (the part before `/chat/completions`), such as `https://openrouter.ai/api/v1`. `providers add` asks for a name, the base URL and an API key (leave it empty for a local server without auth), lists the server's models to check the connection, and saves the provider as `custom-<name>`. Its models then appear in `clodex models`; once saved as favorites they are addressed as `clodex:custom-<name>:<model>` and can be given a short alias with `clodex models --alias`. The base URL is checked before anything is saved: plain `http://` is accepted only after you confirm it, and only for loopback or private-network addresses, and an `https://` URL whose host is, or resolves to, a loopback (`127.0.0.0/8`, `::1`), private, link-local, unique-local, carrier-grade-NAT or well-known cloud-metadata address is refused. A model's id and name are stored with surrounding whitespace trimmed, and a model whose trimmed id or name still contains a control character is skipped, whether the list is fetched by `providers add` or by `providers refresh-models`, and error text from the server is shown with control characters replaced by spaces. Only the OpenAI-compatible kind is offered in the menu.
|
|
298
308
|
|
package/dist/cli.js
CHANGED
|
@@ -346,7 +346,7 @@ import { join } from "path";
|
|
|
346
346
|
// package.json
|
|
347
347
|
var package_default = {
|
|
348
348
|
name: "@bman654/clodex",
|
|
349
|
-
version: "2.
|
|
349
|
+
version: "2.16.0",
|
|
350
350
|
publishConfig: {
|
|
351
351
|
access: "public"
|
|
352
352
|
},
|
|
@@ -694,20 +694,22 @@ function getCacheIndex() {
|
|
|
694
694
|
}
|
|
695
695
|
return cacheIndex;
|
|
696
696
|
}
|
|
697
|
-
function
|
|
698
|
-
|
|
699
|
-
if (cached !== void 0) return cached;
|
|
697
|
+
function matchHeuristicWindow(modelId) {
|
|
698
|
+
if (heuristicCache.has(modelId)) return heuristicCache.get(modelId);
|
|
700
699
|
for (const [pattern, size] of HEURISTIC_RULES) {
|
|
701
700
|
if (pattern.test(modelId)) {
|
|
702
701
|
heuristicCache.set(modelId, size);
|
|
703
702
|
return size;
|
|
704
703
|
}
|
|
705
704
|
}
|
|
706
|
-
heuristicCache.set(modelId,
|
|
707
|
-
return
|
|
705
|
+
heuristicCache.set(modelId, void 0);
|
|
706
|
+
return void 0;
|
|
707
|
+
}
|
|
708
|
+
function lookupKnownContextWindow(modelId) {
|
|
709
|
+
return getCacheIndex().get(modelId) ?? matchHeuristicWindow(modelId);
|
|
708
710
|
}
|
|
709
711
|
function lookupContextWindow(modelId) {
|
|
710
|
-
return
|
|
712
|
+
return lookupKnownContextWindow(modelId) ?? DEFAULT_CONTEXT_WINDOW;
|
|
711
713
|
}
|
|
712
714
|
function resolveContextWindow(modelId, explicit) {
|
|
713
715
|
if (typeof explicit === "number" && explicit > 0) return explicit;
|
|
@@ -3160,17 +3162,19 @@ function parseContextStop(value) {
|
|
|
3160
3162
|
return parsed;
|
|
3161
3163
|
}
|
|
3162
3164
|
function resolveContextStop(limits, stop = "standard") {
|
|
3163
|
-
const
|
|
3164
|
-
const
|
|
3165
|
-
const
|
|
3166
|
-
const
|
|
3165
|
+
const declaredWindow = positiveInteger(limits.contextWindow);
|
|
3166
|
+
const declaredCeiling = positiveInteger(limits.maxContextWindow);
|
|
3167
|
+
const standardRaw = declaredWindow ?? DEFAULT_CONTEXT_WINDOW;
|
|
3168
|
+
const ceiling = declaredCeiling ?? declaredWindow;
|
|
3169
|
+
const requested = stop === "standard" ? standardRaw : stop === "max" ? declaredCeiling ?? standardRaw : positiveInteger(stop) ?? standardRaw;
|
|
3170
|
+
const raw = ceiling === void 0 ? requested : Math.min(requested, ceiling);
|
|
3167
3171
|
const effective = effectiveContextWindow(raw, limits.effectiveContextPercent);
|
|
3168
3172
|
const boundary = positiveInteger(limits.pricingBoundary);
|
|
3169
3173
|
return {
|
|
3170
3174
|
stop,
|
|
3171
3175
|
raw,
|
|
3172
3176
|
effective,
|
|
3173
|
-
...requested > ceiling ? { clampedFrom: requested } : {},
|
|
3177
|
+
...ceiling !== void 0 && requested > ceiling ? { clampedFrom: requested } : {},
|
|
3174
3178
|
crossesPricingBoundary: boundary !== void 0 && effective > boundary
|
|
3175
3179
|
};
|
|
3176
3180
|
}
|
|
@@ -5208,6 +5212,52 @@ var opencode_go_models_default = [
|
|
|
5208
5212
|
upstreamModelId: "minimax-m3",
|
|
5209
5213
|
family: "minimax"
|
|
5210
5214
|
},
|
|
5215
|
+
{
|
|
5216
|
+
id: "muse-spark-1.2-contributor",
|
|
5217
|
+
name: "Muse Spark 1.2 Contributor",
|
|
5218
|
+
contextWindow: 1048576,
|
|
5219
|
+
cost: {
|
|
5220
|
+
input: 0.1,
|
|
5221
|
+
output: 0.2,
|
|
5222
|
+
cache_read: 2e-3
|
|
5223
|
+
},
|
|
5224
|
+
modelFormat: "openai",
|
|
5225
|
+
npm: "@ai-sdk/openai",
|
|
5226
|
+
apiUrl: "https://opencode.ai/zen/go/v1",
|
|
5227
|
+
reasoning: true,
|
|
5228
|
+
modalities: [
|
|
5229
|
+
"text",
|
|
5230
|
+
"image"
|
|
5231
|
+
],
|
|
5232
|
+
compatibility: {
|
|
5233
|
+
supportsReasoningEffort: false
|
|
5234
|
+
},
|
|
5235
|
+
upstreamModelId: "muse-spark-1.2-contributor",
|
|
5236
|
+
family: "muse"
|
|
5237
|
+
},
|
|
5238
|
+
{
|
|
5239
|
+
id: "muse-spark-1.3-contributor",
|
|
5240
|
+
name: "Muse Spark 1.3 Contributor",
|
|
5241
|
+
contextWindow: 1048576,
|
|
5242
|
+
cost: {
|
|
5243
|
+
input: 0.1,
|
|
5244
|
+
output: 0.2,
|
|
5245
|
+
cache_read: 2e-3
|
|
5246
|
+
},
|
|
5247
|
+
modelFormat: "openai",
|
|
5248
|
+
npm: "@ai-sdk/openai",
|
|
5249
|
+
apiUrl: "https://opencode.ai/zen/go/v1",
|
|
5250
|
+
reasoning: true,
|
|
5251
|
+
modalities: [
|
|
5252
|
+
"text",
|
|
5253
|
+
"image"
|
|
5254
|
+
],
|
|
5255
|
+
compatibility: {
|
|
5256
|
+
supportsReasoningEffort: false
|
|
5257
|
+
},
|
|
5258
|
+
upstreamModelId: "muse-spark-1.3-contributor",
|
|
5259
|
+
family: "muse"
|
|
5260
|
+
},
|
|
5211
5261
|
{
|
|
5212
5262
|
id: "qwen3.6-plus",
|
|
5213
5263
|
name: "Qwen3.6 Plus",
|
|
@@ -5471,6 +5521,10 @@ function openCodeGoPinnedApiUrl(npm) {
|
|
|
5471
5521
|
if (npm === "@ai-sdk/anthropic") return OPENCODE_GO_ANTHROPIC_BASE_URL;
|
|
5472
5522
|
return null;
|
|
5473
5523
|
}
|
|
5524
|
+
function openCodeGoPinnedModelApiUrl(npm) {
|
|
5525
|
+
if (npm === "@ai-sdk/openai") return OPENCODE_GO_COMPLETIONS_BASE_URL;
|
|
5526
|
+
return openCodeGoPinnedApiUrl(npm);
|
|
5527
|
+
}
|
|
5474
5528
|
function isProviderConfiguredForTemplate(provider, templateId) {
|
|
5475
5529
|
if (provider.id === templateId) return true;
|
|
5476
5530
|
return templateId === OPENCODE_GO_PROVIDER_ID && isRetainedOpenCodeGoProvider(provider);
|
|
@@ -5957,10 +6011,10 @@ var OPENAI_OAUTH_MODEL_SEEDS = [
|
|
|
5957
6011
|
{ id: "gpt-5", name: "GPT-5", contextWindow: 272e3, reasoning: true },
|
|
5958
6012
|
// o-series reasoning (Plus+)
|
|
5959
6013
|
{ id: "o4-mini", name: "o4 Mini", reasoning: true },
|
|
5960
|
-
{ id: "o3", name: "o3", reasoning: true },
|
|
6014
|
+
{ id: "o3", name: "o3", contextWindow: 2e5, reasoning: true },
|
|
5961
6015
|
{ id: "o3-mini", name: "o3 Mini", reasoning: true },
|
|
5962
|
-
{ id: "o1", name: "o1", reasoning: true },
|
|
5963
|
-
{ id: "o1-mini", name: "o1 Mini", reasoning: true }
|
|
6016
|
+
{ id: "o1", name: "o1", contextWindow: 2e5, reasoning: true },
|
|
6017
|
+
{ id: "o1-mini", name: "o1 Mini", contextWindow: 128e3, reasoning: true }
|
|
5964
6018
|
];
|
|
5965
6019
|
function hasPricingBoundary(id) {
|
|
5966
6020
|
const version = /^gpt-(\d+)(?:\.(\d+))?(?:-|$)/i.exec(id);
|
|
@@ -6008,7 +6062,7 @@ function buildOpenAiOAuthModels() {
|
|
|
6008
6062
|
upstreamModelId: seed.id,
|
|
6009
6063
|
family: prefix,
|
|
6010
6064
|
brand: deriveBrand(prefix),
|
|
6011
|
-
contextWindow:
|
|
6065
|
+
contextWindow: seed.contextWindow ?? lookupKnownContextWindow(seed.id),
|
|
6012
6066
|
maxContextWindow: seed.maxContextWindow,
|
|
6013
6067
|
effectiveContextPercent: seed.effectiveContextPercent,
|
|
6014
6068
|
pricingBoundary: seed.pricingBoundary ?? pricing.pricingBoundary,
|
|
@@ -6524,7 +6578,9 @@ function parseModelList(body, npm, allowBareArray) {
|
|
|
6524
6578
|
const freeStatus = classifyFreeStatus({
|
|
6525
6579
|
model: { cost, isFree: row.isFree }
|
|
6526
6580
|
});
|
|
6527
|
-
const contextWindow = row.context_length ?? row.contextWindow ?? row.context_window ?? row.max_model_len ??
|
|
6581
|
+
const contextWindow = row.context_length ?? row.contextWindow ?? row.context_window ?? row.max_model_len ?? // Left undefined when nothing is known: persisting the invented 200,000
|
|
6582
|
+
// would make it this model's permanent ceiling.
|
|
6583
|
+
lookupKnownContextWindow(id);
|
|
6528
6584
|
models.push({
|
|
6529
6585
|
id,
|
|
6530
6586
|
name: normalizeGoogleDisplayName(row.name, id),
|
|
@@ -6556,7 +6612,7 @@ function materializeTemplateModel(template, model, baseUrl) {
|
|
|
6556
6612
|
upstreamModelId: model.upstreamModelId ?? normalizedUpstream,
|
|
6557
6613
|
family,
|
|
6558
6614
|
brand: model.brand ?? deriveBrand(family),
|
|
6559
|
-
contextWindow: model.contextWindow ??
|
|
6615
|
+
contextWindow: model.contextWindow ?? lookupKnownContextWindow(id),
|
|
6560
6616
|
isFree: model.isFree ?? isFreeStatus(freeStatus),
|
|
6561
6617
|
freeStatus,
|
|
6562
6618
|
modelFormat: model.modelFormat ?? modelFormatForNpm(npm),
|
|
@@ -6758,10 +6814,10 @@ function resolveMaterializedApiUrl(cached, provider, npm) {
|
|
|
6758
6814
|
if (!isRetainedOpenCodeGoProvider(provider)) {
|
|
6759
6815
|
return cached.apiUrl ?? provider.api.url ?? "";
|
|
6760
6816
|
}
|
|
6761
|
-
return
|
|
6817
|
+
return openCodeGoPinnedModelApiUrl(npm);
|
|
6762
6818
|
}
|
|
6763
6819
|
function projectContextStop(cached, providerId, modelId) {
|
|
6764
|
-
const limits = contextLimitsFrom(cached,
|
|
6820
|
+
const limits = contextLimitsFrom(cached, lookupKnownContextWindow(modelId));
|
|
6765
6821
|
const stop = selectContextStop(providerId, modelId);
|
|
6766
6822
|
const resolved = resolveContextStop(limits, stop);
|
|
6767
6823
|
return {
|
|
@@ -7893,7 +7949,7 @@ function outboundHttpProxyAgent(targetUrl, env = process.env) {
|
|
|
7893
7949
|
}
|
|
7894
7950
|
return new HttpsProxyAgent(parsedProxy, { keepAlive: true });
|
|
7895
7951
|
} catch (err) {
|
|
7896
|
-
|
|
7952
|
+
emitParentNotice(
|
|
7897
7953
|
`clodex: HTTP(S)_PROXY cannot be used for a CONNECT tunnel; using a direct connection (${err instanceof Error ? err.message : String(err)})`
|
|
7898
7954
|
);
|
|
7899
7955
|
return void 0;
|
|
@@ -10777,7 +10833,7 @@ async function createLanguageModel(spec) {
|
|
|
10777
10833
|
apiKey: "",
|
|
10778
10834
|
...spec.headers ? { headers: spec.headers } : {},
|
|
10779
10835
|
fetch: fetchWithoutCredentialHeaders
|
|
10780
|
-
} : { apiKey, ...spec.headers ? { headers: spec.headers } : {} };
|
|
10836
|
+
} : { apiKey, ...baseURL ? { baseURL } : {}, ...spec.headers ? { headers: spec.headers } : {} };
|
|
10781
10837
|
const openai = createOpenAI(oauthOptions);
|
|
10782
10838
|
return useResponsesEndpoint ? openai.responses(modelId) : openai.chat(modelId);
|
|
10783
10839
|
}
|
|
@@ -14109,7 +14165,7 @@ function buildDesiredPatchConfig(options = {}) {
|
|
|
14109
14165
|
compatibility: model.compatibility,
|
|
14110
14166
|
upstreamModelId: upstreamModelId2
|
|
14111
14167
|
});
|
|
14112
|
-
const limits = contextLimitsFrom(model,
|
|
14168
|
+
const limits = contextLimitsFrom(model, lookupKnownContextWindow(model.id));
|
|
14113
14169
|
const stop = resolveContextStop(
|
|
14114
14170
|
limits,
|
|
14115
14171
|
options.sessionStops ? selectContextStop(provider.id, model.id, prefs.modelContextModes) : readContextStop(prefs.modelContextModes, provider.id, model.id) ?? "standard"
|
|
@@ -14678,7 +14734,9 @@ async function runPatchCommand(opts = {}) {
|
|
|
14678
14734
|
return 1;
|
|
14679
14735
|
}
|
|
14680
14736
|
for (const id of desired.unknownWindows) {
|
|
14681
|
-
p2.log.warn(
|
|
14737
|
+
p2.log.warn(
|
|
14738
|
+
`No context window metadata for ${id} \u2014 Claude Code will assume the 200k default. Refresh the provider's models, then set a window with \`clodex models --context <model=stop> --save\`, then re-run \`clodex patch\`.`
|
|
14739
|
+
);
|
|
14682
14740
|
}
|
|
14683
14741
|
reportRejectedModelAliases(desired.rejectedAliasRejections);
|
|
14684
14742
|
const localPatches = inspectLocalPatchSource(
|
|
@@ -15781,7 +15839,7 @@ async function fetchAnthropicModels(baseUrl, apiKey, extraHeaders) {
|
|
|
15781
15839
|
upstreamModelId: id,
|
|
15782
15840
|
family: id.split("-")[0] ?? id,
|
|
15783
15841
|
brand: deriveBrand(id),
|
|
15784
|
-
contextWindow:
|
|
15842
|
+
contextWindow: lookupKnownContextWindow(id),
|
|
15785
15843
|
modelFormat: "anthropic",
|
|
15786
15844
|
npm: "@ai-sdk/anthropic",
|
|
15787
15845
|
apiUrl: root
|
|
@@ -16328,7 +16386,7 @@ function buildDynamicOAuthModel(entry, seedById, codexCatalog) {
|
|
|
16328
16386
|
upstreamModelId: id,
|
|
16329
16387
|
family: prefix,
|
|
16330
16388
|
brand: deriveBrand(prefix),
|
|
16331
|
-
contextWindow: entry.context_window ??
|
|
16389
|
+
contextWindow: entry.context_window ?? lookupKnownContextWindow(id),
|
|
16332
16390
|
maxContextWindow: entry.max_context_window,
|
|
16333
16391
|
// Absent means no reduction. clodex reports the window the provider actually
|
|
16334
16392
|
// gives; deciding how much of it to leave free is the client's job, and Claude
|
|
@@ -20433,6 +20491,14 @@ async function startHttpProxy(options) {
|
|
|
20433
20491
|
);
|
|
20434
20492
|
});
|
|
20435
20493
|
const sockets = /* @__PURE__ */ new Set();
|
|
20494
|
+
let warnedConnectSelfProxy = false;
|
|
20495
|
+
const connectTunnelAgents = /* @__PURE__ */ new Map();
|
|
20496
|
+
const connectTunnelAgent = (proxyUrl, targetUrl) => {
|
|
20497
|
+
if (!connectTunnelAgents.has(proxyUrl)) {
|
|
20498
|
+
connectTunnelAgents.set(proxyUrl, outboundHttpProxyAgent(targetUrl));
|
|
20499
|
+
}
|
|
20500
|
+
return connectTunnelAgents.get(proxyUrl);
|
|
20501
|
+
};
|
|
20436
20502
|
mitmServer.on("upgrade", (req, socket, head) => {
|
|
20437
20503
|
forwardAnthropicUpgrade(
|
|
20438
20504
|
req,
|
|
@@ -20462,6 +20528,65 @@ async function startHttpProxy(options) {
|
|
|
20462
20528
|
clientSocket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
20463
20529
|
return;
|
|
20464
20530
|
}
|
|
20531
|
+
const targetUrl = `https://${req.url}`;
|
|
20532
|
+
const outboundProxyUrl = outboundProxyUrlForTarget(targetUrl);
|
|
20533
|
+
const bound = proxyServer.address();
|
|
20534
|
+
const selfTargeting = outboundProxyUrl !== void 0 && bound !== null && typeof bound !== "string" && proxyUrlTargetsListener(outboundProxyUrl, bound.address, bound.port);
|
|
20535
|
+
if (selfTargeting && !warnedConnectSelfProxy) {
|
|
20536
|
+
warnedConnectSelfProxy = true;
|
|
20537
|
+
emitParentNotice(
|
|
20538
|
+
"clodex: HTTP(S)_PROXY points at this proxy; tunneling CONNECT direct"
|
|
20539
|
+
);
|
|
20540
|
+
}
|
|
20541
|
+
const outboundAgent = outboundProxyUrl !== void 0 && !selfTargeting ? connectTunnelAgent(outboundProxyUrl, targetUrl) : void 0;
|
|
20542
|
+
if (outboundAgent) {
|
|
20543
|
+
let upstream2;
|
|
20544
|
+
let proxyConnectStatus;
|
|
20545
|
+
req.once("proxyConnect", (response) => {
|
|
20546
|
+
proxyConnectStatus = response.statusCode;
|
|
20547
|
+
});
|
|
20548
|
+
clientSocket.once("close", () => {
|
|
20549
|
+
if (upstream2 && !upstream2.destroyed) upstream2.destroy();
|
|
20550
|
+
});
|
|
20551
|
+
void outboundAgent.connect(req, {
|
|
20552
|
+
host: target.host,
|
|
20553
|
+
port: target.port,
|
|
20554
|
+
secureEndpoint: false
|
|
20555
|
+
}).then((connected) => {
|
|
20556
|
+
upstream2 = connected;
|
|
20557
|
+
if (proxyConnectStatus !== 200 || clientSocket.destroyed) {
|
|
20558
|
+
connected.destroy();
|
|
20559
|
+
if (!clientSocket.destroyed) {
|
|
20560
|
+
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n", () => clientSocket.destroy());
|
|
20561
|
+
}
|
|
20562
|
+
return;
|
|
20563
|
+
}
|
|
20564
|
+
let tunnelEstablished2 = false;
|
|
20565
|
+
sockets.add(connected);
|
|
20566
|
+
connected.once("close", () => {
|
|
20567
|
+
sockets.delete(connected);
|
|
20568
|
+
if (tunnelEstablished2 && !clientSocket.destroyed) clientSocket.destroy();
|
|
20569
|
+
});
|
|
20570
|
+
connected.once("error", () => {
|
|
20571
|
+
if (clientSocket.destroyed) return;
|
|
20572
|
+
if (tunnelEstablished2) {
|
|
20573
|
+
clientSocket.destroy();
|
|
20574
|
+
return;
|
|
20575
|
+
}
|
|
20576
|
+
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n", () => clientSocket.destroy());
|
|
20577
|
+
});
|
|
20578
|
+
tunnelEstablished2 = true;
|
|
20579
|
+
clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
20580
|
+
if (head.length > 0) connected.write(head);
|
|
20581
|
+
clientSocket.pipe(connected);
|
|
20582
|
+
connected.pipe(clientSocket);
|
|
20583
|
+
}).catch(() => {
|
|
20584
|
+
if (!clientSocket.destroyed) {
|
|
20585
|
+
clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n", () => clientSocket.destroy());
|
|
20586
|
+
}
|
|
20587
|
+
});
|
|
20588
|
+
return;
|
|
20589
|
+
}
|
|
20465
20590
|
const upstream = net.connect(target.port, target.host);
|
|
20466
20591
|
let tunnelEstablished = false;
|
|
20467
20592
|
sockets.add(upstream);
|
|
@@ -20527,6 +20652,8 @@ async function startHttpProxy(options) {
|
|
|
20527
20652
|
for (const socket of sockets) socket.destroy();
|
|
20528
20653
|
await new Promise((resolve4) => proxyServer.close(() => resolve4()));
|
|
20529
20654
|
mitmServer.close();
|
|
20655
|
+
for (const agent of connectTunnelAgents.values()) agent?.destroy();
|
|
20656
|
+
connectTunnelAgents.clear();
|
|
20530
20657
|
anthropicAgent?.destroy();
|
|
20531
20658
|
adapter?.close();
|
|
20532
20659
|
}
|
|
@@ -22242,7 +22369,7 @@ function applyContextStopAssignments(assignments, save, report, saveHint = "Add
|
|
|
22242
22369
|
);
|
|
22243
22370
|
return 1;
|
|
22244
22371
|
}
|
|
22245
|
-
const limits = contextLimitsFrom(cached,
|
|
22372
|
+
const limits = contextLimitsFrom(cached, lookupKnownContextWindow(assignment.modelId));
|
|
22246
22373
|
const resolved = resolveContextStop(limits, assignment.stop ?? "standard");
|
|
22247
22374
|
const target = modelAliasTarget(assignment);
|
|
22248
22375
|
const label = assignment.label === target ? target : `${assignment.label} (${target})`;
|