@askalf/dario 6.14.0 → 6.14.2
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.
|
@@ -25,6 +25,12 @@ export declare function parseFamilyFallback(spec: string | Record<string, unknow
|
|
|
25
25
|
*
|
|
26
26
|
* A `[1m]` long-context tag on the request is carried onto the target when the
|
|
27
27
|
* target has none, so the switch does not shrink the context window asked for.
|
|
28
|
+
*
|
|
29
|
+
* A model name that is not printable ASCII (at most 256 characters, no spaces
|
|
30
|
+
* or control characters) is left alone: no real model is named so, and the
|
|
31
|
+
* name the client sent is echoed in the `x-dario-family-fallback` header and
|
|
32
|
+
* the log, where a line break would fail the header (setHeader throws, the
|
|
33
|
+
* request errors) or forge a log line.
|
|
28
34
|
*/
|
|
29
35
|
export declare function familyFallbackModel(map: FamilyFallbackMap, model: string, pool: {
|
|
30
36
|
parked: (family: string) => boolean;
|
package/dist/family-fallback.js
CHANGED
|
@@ -64,10 +64,18 @@ export function parseFamilyFallback(spec) {
|
|
|
64
64
|
*
|
|
65
65
|
* A `[1m]` long-context tag on the request is carried onto the target when the
|
|
66
66
|
* target has none, so the switch does not shrink the context window asked for.
|
|
67
|
+
*
|
|
68
|
+
* A model name that is not printable ASCII (at most 256 characters, no spaces
|
|
69
|
+
* or control characters) is left alone: no real model is named so, and the
|
|
70
|
+
* name the client sent is echoed in the `x-dario-family-fallback` header and
|
|
71
|
+
* the log, where a line break would fail the header (setHeader throws, the
|
|
72
|
+
* request errors) or forge a log line.
|
|
67
73
|
*/
|
|
68
74
|
export function familyFallbackModel(map, model, pool) {
|
|
69
75
|
if (map.size === 0)
|
|
70
76
|
return null;
|
|
77
|
+
if (!/^[\x21-\x7e]{1,256}$/.test(model))
|
|
78
|
+
return null;
|
|
71
79
|
const family = modelFamily(model);
|
|
72
80
|
if (!family)
|
|
73
81
|
return null;
|
|
@@ -518,7 +518,7 @@ export declare function detectDrift(t: TemplateData, installedOverride?: string
|
|
|
518
518
|
*/
|
|
519
519
|
export declare const SUPPORTED_CC_RANGE: {
|
|
520
520
|
readonly min: "1.0.0";
|
|
521
|
-
readonly maxTested: "2.1.
|
|
521
|
+
readonly maxTested: "2.1.310";
|
|
522
522
|
};
|
|
523
523
|
/**
|
|
524
524
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/dist/live-fingerprint.js
CHANGED
|
@@ -1238,7 +1238,7 @@ export function detectDrift(t, installedOverride) {
|
|
|
1238
1238
|
*/
|
|
1239
1239
|
export const SUPPORTED_CC_RANGE = {
|
|
1240
1240
|
min: '1.0.0',
|
|
1241
|
-
maxTested: '2.1.
|
|
1241
|
+
maxTested: '2.1.310',
|
|
1242
1242
|
};
|
|
1243
1243
|
/**
|
|
1244
1244
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/dist/pool.js
CHANGED
|
@@ -341,6 +341,14 @@ export function withParkedBuckets(prev, next, now = Date.now()) {
|
|
|
341
341
|
*/
|
|
342
342
|
export function isParkedInLiveWindow(account, now = Date.now(), family) {
|
|
343
343
|
const rl = account.rateLimit;
|
|
344
|
+
// A bucket the seat was parked on, carried past a reading that did not
|
|
345
|
+
// measure it (an Opus 200, or an Opus 429 that named no exhausted window,
|
|
346
|
+
// after a Fable credit 429; see withParkedBuckets): whatever the seat's
|
|
347
|
+
// status says now, the bucket's reset is still ahead and a probe for a
|
|
348
|
+
// family it binds can only 429 again. The bucket-scoped rejection itself is
|
|
349
|
+
// decided below, where a 429 with no stated reset stays probeable.
|
|
350
|
+
if (!isBucketScopedRejection(rl) && familyParkedOnBuckets(rl, family, now))
|
|
351
|
+
return true;
|
|
344
352
|
// A non-exhausted rejection is never "parked in a live window": its reset
|
|
345
353
|
// was not this seat's window, and once its cool-down passes asking is the
|
|
346
354
|
// way back (the all-exhausted branch may probe it even sooner).
|
|
@@ -1146,7 +1154,7 @@ export class AccountPool {
|
|
|
1146
1154
|
// reported, or cooled, as if they were.
|
|
1147
1155
|
const until = all.map((a) => {
|
|
1148
1156
|
if (isParkedInLiveWindow(a, now, family)) {
|
|
1149
|
-
return
|
|
1157
|
+
return familyParkedOnBuckets(a.rateLimit, family, now)
|
|
1150
1158
|
? (a.rateLimit.parkedBucketsUntil ?? a.rateLimit.reset * 1000)
|
|
1151
1159
|
: a.rateLimit.reset * 1000;
|
|
1152
1160
|
}
|
|
@@ -1348,7 +1356,9 @@ export class AccountPool {
|
|
|
1348
1356
|
: exhausted
|
|
1349
1357
|
? { ...merged, status: 'rejected', exhausted: true, parkedBuckets: undefined, parkedBucketsUntil: undefined }
|
|
1350
1358
|
: {
|
|
1351
|
-
|
|
1359
|
+
// Not a window, so not this seat's buckets either: a bucket parked
|
|
1360
|
+
// before it stays parked, as across any reading that did not measure it.
|
|
1361
|
+
...withParkedBuckets(account.rateLimit, merged, now),
|
|
1352
1362
|
status: 'rejected',
|
|
1353
1363
|
exhausted: false,
|
|
1354
1364
|
cooldownUntil: now + (snapshot.retryAfterMs ?? NON_WINDOW_REJECTION_COOLDOWN_MS),
|
|
@@ -124,6 +124,8 @@ curl http://localhost:3456/analytics # per-account / per-model stats, burn ra
|
|
|
124
124
|
|
|
125
125
|
**When every seat is parked.** A pool whose seats are all `rejected` inside live windows does not probe them again: dario answers the request itself with `429`, `retry-after` set to the earliest reset, `x-dario-upstream-rejection: pool_parked`, and nothing sent upstream. One log line marks the transition (`pool parked: all 6 seats are over their rate-limit windows, earliest resets in 21m`). Before 6.0.35 every such request re-probed the earliest-reset seat, so `rejectedCount` on that seat grew by one per request — a seat reading `rejected_count: 500` next to `request_count: 1` was that, not a seat that needed a re-login. With a `--pool-fallback` armed, the request goes to the fallback instead, as before.
|
|
126
126
|
|
|
127
|
+
**A seat parked on one family's bucket stays parked for it.** A seat parked on a per-model bucket counts for the families that bucket binds even after it has served another family since: an Opus `200` (or an Opus `429` that names no exhausted window) after a Fable credit `429` does not make it probeable for Fable again before the bucket resets.
|
|
128
|
+
|
|
127
129
|
**Spending extra usage while the pool is parked (dario#1282).** The parked answer is decided
|
|
128
130
|
from the seats' own rate-limit verdicts, before anything is sent. Disarming the overage-guard
|
|
129
131
|
does **not** change it: the guard is reactive — it reads the `representative-claim` on a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "6.14.
|
|
3
|
+
"version": "6.14.2",
|
|
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": {
|