@askalf/dario 6.10.2 → 6.10.3
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/dist/live-fingerprint.d.ts +1 -1
- package/dist/live-fingerprint.js +1 -1
- package/dist/proxy.d.ts +32 -0
- package/dist/proxy.js +67 -0
- package/package.json +1 -1
|
@@ -510,7 +510,7 @@ export declare function detectDrift(t: TemplateData, installedOverride?: string
|
|
|
510
510
|
*/
|
|
511
511
|
export declare const SUPPORTED_CC_RANGE: {
|
|
512
512
|
readonly min: "1.0.0";
|
|
513
|
-
readonly maxTested: "2.1.
|
|
513
|
+
readonly maxTested: "2.1.280";
|
|
514
514
|
};
|
|
515
515
|
/**
|
|
516
516
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/dist/live-fingerprint.js
CHANGED
|
@@ -1211,7 +1211,7 @@ export function detectDrift(t, installedOverride) {
|
|
|
1211
1211
|
*/
|
|
1212
1212
|
export const SUPPORTED_CC_RANGE = {
|
|
1213
1213
|
min: '1.0.0',
|
|
1214
|
-
maxTested: '2.1.
|
|
1214
|
+
maxTested: '2.1.280',
|
|
1215
1215
|
};
|
|
1216
1216
|
/**
|
|
1217
1217
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/dist/proxy.d.ts
CHANGED
|
@@ -181,6 +181,38 @@ export declare function parseEffortRejection(body: string): {
|
|
|
181
181
|
* an EMPTY supported set in effortSupportByModel. Exported for tests.
|
|
182
182
|
*/
|
|
183
183
|
export declare function isEffortParamUnsupported(body: string): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Parse upstream's CLIENT-VERSION gate:
|
|
186
|
+
*
|
|
187
|
+
* 400 {"type":"invalid_request_error","message":"Claude Code 2.1.278 does
|
|
188
|
+
* not support this model; version 2.1.280 or newer is required. Run
|
|
189
|
+
* 'claude update', or update the Claude Code SDK."}
|
|
190
|
+
*
|
|
191
|
+
* Observed live 2026-09-22 the day `claude-opus-5-5` shipped: Anthropic gates a
|
|
192
|
+
* new model on the CLIENT version it reads off the request, which for dario is
|
|
193
|
+
* the bundled template's `user-agent: claude-cli/<_version>`. The bundle claimed
|
|
194
|
+
* 2.1.278 and the model wanted 2.1.280, so every request for it 400'd with a
|
|
195
|
+
* message naming Claude Code -- which the caller usually is not (Cursor, Cline,
|
|
196
|
+
* the Agent SDK). Nothing in the pool, the seat or the model is wrong, and the
|
|
197
|
+
* daily sdk-drift watch can be up to a day behind the npm publish, so the first
|
|
198
|
+
* symptom is this 400 and it reads like a model problem.
|
|
199
|
+
*
|
|
200
|
+
* Returns the version the bundle claimed and the version upstream wants, or
|
|
201
|
+
* null for any other 400. Exported for tests.
|
|
202
|
+
*/
|
|
203
|
+
export declare function parseClientVersionGate(body: string): {
|
|
204
|
+
claimed: string;
|
|
205
|
+
required: string;
|
|
206
|
+
} | null;
|
|
207
|
+
/**
|
|
208
|
+
* The operator-facing sentence for a client-version gate. One line, names the
|
|
209
|
+
* cause and the fix, and says it in terms of dario rather than of Claude Code:
|
|
210
|
+
* the caller is usually a different client entirely.
|
|
211
|
+
*/
|
|
212
|
+
export declare function describeClientVersionGate(g: {
|
|
213
|
+
claimed: string;
|
|
214
|
+
required: string;
|
|
215
|
+
}, model: string): string;
|
|
184
216
|
/**
|
|
185
217
|
* Pick the strongest effort level a model says it supports. Preference is
|
|
186
218
|
* descending capability — the caller asked for more than the model can do,
|
package/dist/proxy.js
CHANGED
|
@@ -602,6 +602,40 @@ export function parseEffortRejection(body) {
|
|
|
602
602
|
export function isEffortParamUnsupported(body) {
|
|
603
603
|
return /does not support the effort parameter/i.test(body);
|
|
604
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Parse upstream's CLIENT-VERSION gate:
|
|
607
|
+
*
|
|
608
|
+
* 400 {"type":"invalid_request_error","message":"Claude Code 2.1.278 does
|
|
609
|
+
* not support this model; version 2.1.280 or newer is required. Run
|
|
610
|
+
* 'claude update', or update the Claude Code SDK."}
|
|
611
|
+
*
|
|
612
|
+
* Observed live 2026-09-22 the day `claude-opus-5-5` shipped: Anthropic gates a
|
|
613
|
+
* new model on the CLIENT version it reads off the request, which for dario is
|
|
614
|
+
* the bundled template's `user-agent: claude-cli/<_version>`. The bundle claimed
|
|
615
|
+
* 2.1.278 and the model wanted 2.1.280, so every request for it 400'd with a
|
|
616
|
+
* message naming Claude Code -- which the caller usually is not (Cursor, Cline,
|
|
617
|
+
* the Agent SDK). Nothing in the pool, the seat or the model is wrong, and the
|
|
618
|
+
* daily sdk-drift watch can be up to a day behind the npm publish, so the first
|
|
619
|
+
* symptom is this 400 and it reads like a model problem.
|
|
620
|
+
*
|
|
621
|
+
* Returns the version the bundle claimed and the version upstream wants, or
|
|
622
|
+
* null for any other 400. Exported for tests.
|
|
623
|
+
*/
|
|
624
|
+
export function parseClientVersionGate(body) {
|
|
625
|
+
const m = body.match(/Claude Code ([\d.]+) does not support this model;\s*version ([\d.]+) or newer is required/i);
|
|
626
|
+
return m ? { claimed: m[1], required: m[2] } : null;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* The operator-facing sentence for a client-version gate. One line, names the
|
|
630
|
+
* cause and the fix, and says it in terms of dario rather than of Claude Code:
|
|
631
|
+
* the caller is usually a different client entirely.
|
|
632
|
+
*/
|
|
633
|
+
export function describeClientVersionGate(g, model) {
|
|
634
|
+
return `${model} requires Claude Code >= ${g.required}, and dario's bundled template claims ${g.claimed}. `
|
|
635
|
+
+ `This is the template's version label, not your client and not the seat: upgrade Claude Code on the dario host `
|
|
636
|
+
+ `(npm i -g @anthropic-ai/claude-code@latest) and run the cc-drift-template-watch workflow, which re-labels the `
|
|
637
|
+
+ `bundle (a label refresh when the wire shape is unchanged). Until then this model cannot be served.`;
|
|
638
|
+
}
|
|
605
639
|
/**
|
|
606
640
|
* Pick the strongest effort level a model says it supports. Preference is
|
|
607
641
|
* descending capability — the caller asked for more than the model can do,
|
|
@@ -1899,6 +1933,11 @@ export async function startProxy(opts = {}) {
|
|
|
1899
1933
|
// front so older models capped below dario's DEFAULT_MAX_TOKENS pin never
|
|
1900
1934
|
// re-pay the rejection.
|
|
1901
1935
|
const maxTokensCapByModel = new Map();
|
|
1936
|
+
// Client-version gates already announced this process, keyed `model@required`.
|
|
1937
|
+
// The gate is a property of (model, installed CC), so it repeats on every
|
|
1938
|
+
// request for that model until the template is re-labelled; saying it once is
|
|
1939
|
+
// the difference between a diagnosis and a log flood.
|
|
1940
|
+
const announcedVersionGates = new Set();
|
|
1902
1941
|
// Beta flag set — sourced from the live template when the capture recorded
|
|
1903
1942
|
// one (schema v2+), else falls back to the v2.1.104 bundled default.
|
|
1904
1943
|
// Computed once per proxy because it's a function of the loaded template,
|
|
@@ -4989,6 +5028,34 @@ export async function startProxy(opts = {}) {
|
|
|
4989
5028
|
return;
|
|
4990
5029
|
}
|
|
4991
5030
|
}
|
|
5031
|
+
else if (upstream.status === 400 && parseClientVersionGate(peekedBody)) {
|
|
5032
|
+
// Client-version gate. There is nothing to retry -- no body edit makes a
|
|
5033
|
+
// stale version label acceptable -- so this only has to be SAID well:
|
|
5034
|
+
// once per (model, required) at error level, and in the response the
|
|
5035
|
+
// caller actually reads. Without this the client gets a 400 blaming a
|
|
5036
|
+
// Claude Code version it is not running.
|
|
5037
|
+
const gate = parseClientVersionGate(peekedBody);
|
|
5038
|
+
const gateKey = `${requestModel}@${gate.required}`;
|
|
5039
|
+
if (!announcedVersionGates.has(gateKey)) {
|
|
5040
|
+
announcedVersionGates.add(gateKey);
|
|
5041
|
+
console.error(`[dario] #${requestCount} ${describeClientVersionGate(gate, requestModel || 'this model')}`);
|
|
5042
|
+
}
|
|
5043
|
+
const responseHeaders = {
|
|
5044
|
+
'Content-Type': 'application/json',
|
|
5045
|
+
'Access-Control-Allow-Origin': corsOrigin,
|
|
5046
|
+
...SECURITY_HEADERS,
|
|
5047
|
+
};
|
|
5048
|
+
for (const [key, value] of upstream.headers.entries()) {
|
|
5049
|
+
if (key === 'request-id')
|
|
5050
|
+
responseHeaders[key] = value;
|
|
5051
|
+
}
|
|
5052
|
+
requestCount++;
|
|
5053
|
+
res.writeHead(400, responseHeaders);
|
|
5054
|
+
res.end(JSON.stringify(isOpenAI
|
|
5055
|
+
? { error: { message: describeClientVersionGate(gate, requestModel || 'this model'), type: 'invalid_request_error', param: 'model', code: 'client_version_too_old' } }
|
|
5056
|
+
: { type: 'error', error: { type: 'invalid_request_error', message: describeClientVersionGate(gate, requestModel || 'this model') } }));
|
|
5057
|
+
return;
|
|
5058
|
+
}
|
|
4992
5059
|
else if (upstream.status === 400 && parseMaxTokensRejection(peekedBody) !== null && finalBody && recoveryPasses < MAX_RECOVERY_PASSES) {
|
|
4993
5060
|
// max_tokens-cap rejection — dario's DEFAULT_MAX_TOKENS pin exceeds
|
|
4994
5061
|
// this (older) model's per-model output cap (e.g. opus-4-1 caps at
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "6.10.
|
|
3
|
+
"version": "6.10.3",
|
|
4
4
|
"description": "Use your Claude and ChatGPT subscriptions in Cursor, Cline, Aider, Claude Code and the Agent SDK — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint: either plan answers either wire shape, with automatic failover when one hits its limit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|