@askalf/dario 4.8.154 → 5.0.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 +1 -2
- package/dist/cc-template.d.ts +0 -2
- package/dist/cc-template.js +0 -2
- package/dist/cli.js +50 -124
- package/dist/config-report.js +16 -1
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.js +17 -7
- package/dist/live-fingerprint.d.ts +8 -8
- package/dist/live-fingerprint.js +6 -6
- package/dist/proxy.d.ts +2 -11
- package/dist/proxy.js +247 -256
- package/dist/runtime-fingerprint.d.ts +5 -11
- package/dist/runtime-fingerprint.js +7 -13
- package/dist/session-rotation.d.ts +22 -10
- package/dist/session-rotation.js +30 -13
- package/package.json +3 -3
- package/dist/shim/host.d.ts +0 -86
- package/dist/shim/host.js +0 -196
- package/dist/shim/runtime.cjs +0 -327
package/README.md
CHANGED
|
@@ -265,7 +265,6 @@ Tune via `~/.dario/config.json` → `overageGuard`, or CLI flags: `--overage-beh
|
|
|
265
265
|
- **Honor client thinking (`--honor-client-thinking`).** By default dario rebuilds the outbound request with CC's interactive thinking shape regardless of what the client sent. Pass this flag (or `DARIO_HONOR_CLIENT_THINKING=1`) to pass a non-CC client's own `thinking` block through unchanged. Off by default; the rebuild-to-CC path is what keeps the subscription pool routing.
|
|
266
266
|
- **Preserve structured output (`--preserve-output-format`).** By default dario rebuilds `output_config` from CC's template (effort only), dropping a client's `output_config.format` JSON schema, so structured-output clients get unconstrained prose their strict parser rejects. Pass this flag (or `DARIO_PRESERVE_OUTPUT_FORMAT=1`) to carry the client's schema through unchanged — SDK clients like the Vercel AI SDK's `generateObject` then get schema-constrained output. Off by default; empirically without flipping billing (verified `five_hour` on `claude-sonnet-4-6`).
|
|
267
267
|
- **Reachable from inside CC / any MCP client.** `dario subagent install` registers a CC sub-agent for in-session diagnostics; `dario mcp` exposes dario as a read-only MCP server. → [`docs/sub-agent.md`](./docs/sub-agent.md) · [`docs/mcp-server.md`](./docs/mcp-server.md)
|
|
268
|
-
- **Shim mode** *(deprecated v4.2, removal scheduled v5.x)*. The original "no HTTP hop" path empirically matched only 3 of the 8 classifier axes and fell back to passthrough for the 1-block system prompts `claude -p` and the Agent SDK both send. Use **proxy mode** for any non-CC client — it's the only mode that rebuilds every request to CC's full canonical shape.
|
|
269
268
|
|
|
270
269
|
---
|
|
271
270
|
|
|
@@ -311,7 +310,7 @@ New *product* work happens in [askalf](https://askalf.org), the AI operation tha
|
|
|
311
310
|
|
|
312
311
|
## Commands
|
|
313
312
|
|
|
314
|
-
`dario` (TUI) · `login` · `proxy` · `doctor` · `accounts {list,add,remove}` · `backend {list,add,remove}` · `
|
|
313
|
+
`dario` (TUI) · `login` · `proxy` · `doctor` · `accounts {list,add,remove}` · `backend {list,add,remove}` · `mcp` · `subagent {install,status,remove}` · `usage` · `config` · `upgrade` · `status` · `refresh` · `resume` · `logout` · `help`
|
|
315
314
|
|
|
316
315
|
Full flag/env reference: [`docs/commands.md`](./docs/commands.md) · SDK examples + per-tool setup: [`docs/usage.md`](./docs/usage.md)
|
|
317
316
|
|
package/dist/cc-template.d.ts
CHANGED
|
@@ -178,8 +178,6 @@ export declare function resolveSystemPrompt(arg: string | undefined, model?: str
|
|
|
178
178
|
* in the captured order are emitted in the template's exact case; names
|
|
179
179
|
* only in the caller's map keep the caller's case.
|
|
180
180
|
*
|
|
181
|
-
* Matches `rewriteHeaders` in `src/shim/runtime.cjs` — the shim and the
|
|
182
|
-
* proxy are two transports that need to produce the same wire shape.
|
|
183
181
|
*
|
|
184
182
|
* @param headers outbound headers the proxy built
|
|
185
183
|
* @param overrideHeaderOrder test-only override; production callers pass nothing
|
package/dist/cc-template.js
CHANGED
|
@@ -268,8 +268,6 @@ function stripBehavioralConstraints(input, level) {
|
|
|
268
268
|
* in the captured order are emitted in the template's exact case; names
|
|
269
269
|
* only in the caller's map keep the caller's case.
|
|
270
270
|
*
|
|
271
|
-
* Matches `rewriteHeaders` in `src/shim/runtime.cjs` — the shim and the
|
|
272
|
-
* proxy are two transports that need to produce the same wire shape.
|
|
273
271
|
*
|
|
274
272
|
* @param headers outbound headers the proxy built
|
|
275
273
|
* @param overrideHeaderOrder test-only override; production callers pass nothing
|
package/dist/cli.js
CHANGED
|
@@ -53,6 +53,22 @@ const DEFAULT_COMMAND = args.includes('--no-tui') ? 'help' : 'tui';
|
|
|
53
53
|
// `dario --version` etc. still dispatch as expected.
|
|
54
54
|
const positionalArgs = args.filter((a) => a !== '--no-tui');
|
|
55
55
|
const command = positionalArgs[0] ?? DEFAULT_COMMAND;
|
|
56
|
+
// v5.0 pool-as-primitive: materialize the just-authenticated `dario login`
|
|
57
|
+
// credentials as a pool of one (accounts/login.json under the reserved `login`
|
|
58
|
+
// alias) so every surface — proxy, doctor, config-report, /accounts — reads a
|
|
59
|
+
// single credential model. Idempotent and copy-only: a no-op when an accounts/
|
|
60
|
+
// pool already exists or no credentials are reachable, and it never refreshes
|
|
61
|
+
// the token lineage (see ensureLoginCredentialsInPool). Best-effort — a failure
|
|
62
|
+
// here shouldn't fail an otherwise-successful login; the proxy back-fills again
|
|
63
|
+
// at startup.
|
|
64
|
+
async function materializeLoginPool() {
|
|
65
|
+
try {
|
|
66
|
+
const alias = await ensureLoginCredentialsInPool();
|
|
67
|
+
if (alias)
|
|
68
|
+
console.log(' Pool: materialized as a pool of one (alias `login`).');
|
|
69
|
+
}
|
|
70
|
+
catch { /* non-fatal; proxy startup back-fills again */ }
|
|
71
|
+
}
|
|
56
72
|
async function login() {
|
|
57
73
|
console.log('');
|
|
58
74
|
console.log(' dario — Claude Login');
|
|
@@ -74,6 +90,7 @@ async function login() {
|
|
|
74
90
|
if (creds?.claudeAiOauth?.accessToken && creds.claudeAiOauth.expiresAt > Date.now()) {
|
|
75
91
|
if (noProxy) {
|
|
76
92
|
console.log(' Found valid credentials. (--no-proxy / --manual: not starting proxy.)');
|
|
93
|
+
await materializeLoginPool();
|
|
77
94
|
console.log('');
|
|
78
95
|
return;
|
|
79
96
|
}
|
|
@@ -93,6 +110,7 @@ async function login() {
|
|
|
93
110
|
const tokens = await refreshTokens();
|
|
94
111
|
const expiresIn = Math.round((tokens.expiresAt - Date.now()) / 60000);
|
|
95
112
|
console.log(` Refresh successful! Token expires in ${expiresIn} minutes.`);
|
|
113
|
+
await materializeLoginPool();
|
|
96
114
|
console.log('');
|
|
97
115
|
console.log(' Run `dario proxy` to start the API proxy.');
|
|
98
116
|
console.log('');
|
|
@@ -129,6 +147,7 @@ async function login() {
|
|
|
129
147
|
const expiresIn = Math.round((tokens.expiresAt - Date.now()) / 60000);
|
|
130
148
|
console.log(' Login successful!');
|
|
131
149
|
console.log(` Token expires in ${expiresIn} minutes (auto-refreshes).`);
|
|
150
|
+
await materializeLoginPool();
|
|
132
151
|
console.log('');
|
|
133
152
|
if (noProxy) {
|
|
134
153
|
console.log(' (--no-proxy / --manual: credentials saved, proxy not started.)');
|
|
@@ -360,9 +379,10 @@ async function proxy() {
|
|
|
360
379
|
// read-to-completion pattern. Costs tokens (the response is fully
|
|
361
380
|
// generated even if nobody reads it), so it's opt-in.
|
|
362
381
|
const drainOnClose = args.includes('--drain-on-close') || fileCfg.drainOnClose || undefined;
|
|
363
|
-
// --session-* knobs (v3.28, direction #1). Control the
|
|
364
|
-
//
|
|
365
|
-
//
|
|
382
|
+
// --session-* knobs (v3.28, direction #1). Control the session-id lifecycle:
|
|
383
|
+
// idle threshold, jitter on that threshold, hard max-age, and whether to give
|
|
384
|
+
// each upstream client its own session. v5.0: this policy now applies
|
|
385
|
+
// per-account (a pool of one behaves exactly as the pre-v5 single account).
|
|
366
386
|
// All defaults preserve v3.27 behaviour exactly. Logic lives in
|
|
367
387
|
// src/session-rotation.ts; these flags just feed resolveSessionRotationConfig.
|
|
368
388
|
const sessionIdleRotateMs = parsePositiveIntFlag('--session-idle-rotate=');
|
|
@@ -777,23 +797,24 @@ async function accounts() {
|
|
|
777
797
|
console.log(' ────────────────');
|
|
778
798
|
console.log('');
|
|
779
799
|
if (aliases.length === 0) {
|
|
780
|
-
console.log(' No
|
|
800
|
+
console.log(' No accounts in the pool yet.');
|
|
781
801
|
console.log('');
|
|
782
|
-
console.log('
|
|
783
|
-
console.log('
|
|
802
|
+
console.log(' The pool is the one credential model (v5.0): `dario login`');
|
|
803
|
+
console.log(' is a pool of one, materialized as the `login` account. Add');
|
|
804
|
+
console.log(' more to load-balance across subscriptions:');
|
|
784
805
|
console.log(' dario accounts add <alias>');
|
|
785
806
|
console.log('');
|
|
786
|
-
console.log('
|
|
787
|
-
console.log('
|
|
788
|
-
console.log('
|
|
807
|
+
console.log(' If you have run `dario login` but see this, its credentials');
|
|
808
|
+
console.log(' materialize into the pool on the next `dario login` or');
|
|
809
|
+
console.log(' `dario proxy`.');
|
|
789
810
|
console.log('');
|
|
790
811
|
return;
|
|
791
812
|
}
|
|
792
813
|
const loaded = await loadAllAccounts();
|
|
793
814
|
const now = Date.now();
|
|
794
|
-
console.log(` ${aliases.length}
|
|
815
|
+
console.log(` Pool of ${aliases.length} (${aliases.length === 1 ? '1 account' : aliases.length + ' accounts'})`);
|
|
795
816
|
if (aliases.length === 1) {
|
|
796
|
-
console.log(' (
|
|
817
|
+
console.log(' (A pool of one — add another with `dario accounts add <alias>` to load-balance.)');
|
|
797
818
|
}
|
|
798
819
|
console.log('');
|
|
799
820
|
for (const a of loaded) {
|
|
@@ -1094,13 +1115,6 @@ async function help() {
|
|
|
1094
1115
|
dario backend add NAME --key=sk-... [--base-url=...]
|
|
1095
1116
|
Add an OpenAI-compat backend (OpenAI, OpenRouter, Groq, etc.)
|
|
1096
1117
|
dario backend remove N Remove an OpenAI-compat backend
|
|
1097
|
-
dario shim -- CMD ARGS [DEPRECATED — removal scheduled for v5.x]
|
|
1098
|
-
Run CMD with dario's fetch-patch in-process.
|
|
1099
|
-
Only replaces 3 of 8 billing-classifier axes
|
|
1100
|
-
(system blocks, agent identity, header order).
|
|
1101
|
-
Falls back to passthrough on 1-block system
|
|
1102
|
-
requests (\`claude -p\`, Agent SDK). Use proxy
|
|
1103
|
-
mode for non-CC clients. See CHANGELOG v4.2.0.
|
|
1104
1118
|
dario subagent install Register ~/.claude/agents/dario.md so Claude Code
|
|
1105
1119
|
can delegate dario diagnostics / template-refresh
|
|
1106
1120
|
operations to a named sub-agent (v3.26)
|
|
@@ -1208,7 +1222,7 @@ async function help() {
|
|
|
1208
1222
|
proxy's JA3/JA4 ClientHello indistinguishable
|
|
1209
1223
|
from a stock CC request. Install Bun
|
|
1210
1224
|
(https://bun.sh) so dario auto-relaunches
|
|
1211
|
-
under it
|
|
1225
|
+
under it. (v3.23)
|
|
1212
1226
|
--stealth Single-flag behavioral-stealth preset.
|
|
1213
1227
|
Flips pace-jitter, think-time, and
|
|
1214
1228
|
session-start defaults from 0 to non-zero
|
|
@@ -1268,11 +1282,12 @@ async function help() {
|
|
|
1268
1282
|
is fully generated even if nobody reads
|
|
1269
1283
|
it) for fingerprint fidelity. Bounded by
|
|
1270
1284
|
the 5-minute upstream timeout. (v3.25)
|
|
1271
|
-
--session-idle-rotate=MS Idle ms before
|
|
1272
|
-
|
|
1285
|
+
--session-idle-rotate=MS Idle ms before an account's session id
|
|
1286
|
+
rotates (default: 900000 = 15 min).
|
|
1273
1287
|
Real CC rotates once per conversation, not
|
|
1274
1288
|
per call; the default matches its observed
|
|
1275
|
-
cadence.
|
|
1289
|
+
cadence. Applies per account — a pool of one
|
|
1290
|
+
rotates as the pre-v5 single account did. (v3.28)
|
|
1276
1291
|
--session-rotate-jitter=MS
|
|
1277
1292
|
Max additional uniform-random jitter (ms)
|
|
1278
1293
|
added to the idle threshold, sampled once
|
|
@@ -1489,109 +1504,20 @@ async function help() {
|
|
|
1489
1504
|
Tokens auto-refresh in the background — set it and forget it.
|
|
1490
1505
|
`);
|
|
1491
1506
|
}
|
|
1507
|
+
// `dario shim` was removed in v5.0 (deprecated since v4.2 — it matched only
|
|
1508
|
+
// 3 of the 8 billing-classifier axes and fell back to passthrough on 1-block
|
|
1509
|
+
// system requests). This stub keeps the failure mode a one-line pointer
|
|
1510
|
+
// instead of an "unknown command" for users upgrading across the boundary.
|
|
1492
1511
|
async function shim() {
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
if (sepIdx >= 0) {
|
|
1503
|
-
head = rest.slice(0, sepIdx);
|
|
1504
|
-
childArgs = rest.slice(sepIdx + 1);
|
|
1505
|
-
}
|
|
1506
|
-
else {
|
|
1507
|
-
head = [];
|
|
1508
|
-
childArgs = rest;
|
|
1509
|
-
}
|
|
1510
|
-
for (const flag of head) {
|
|
1511
|
-
if (flag === '-v' || flag === '--verbose')
|
|
1512
|
-
verbose = true;
|
|
1513
|
-
else if (flag.startsWith('--priority=')) {
|
|
1514
|
-
const v = flag.slice('--priority='.length);
|
|
1515
|
-
if (v !== 'normal' && v !== 'below-normal' && v !== 'low') {
|
|
1516
|
-
console.error(`--priority: invalid value ${JSON.stringify(v)}. Expected one of: normal, below-normal, low.`);
|
|
1517
|
-
process.exit(1);
|
|
1518
|
-
}
|
|
1519
|
-
priority = v;
|
|
1520
|
-
}
|
|
1521
|
-
else {
|
|
1522
|
-
console.error(`Unknown shim flag: ${flag}`);
|
|
1523
|
-
process.exit(1);
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
if (childArgs.length === 0) {
|
|
1527
|
-
console.error('Usage: dario shim [-v] [--priority=normal|below-normal|low] -- <command> [args...]');
|
|
1528
|
-
console.error('Example: dario shim -- claude --print -p "hi"');
|
|
1529
|
-
console.error(' dario shim --priority=below-normal -- claude (recommended on Windows when RDP\'d into the host)');
|
|
1530
|
-
process.exit(1);
|
|
1531
|
-
}
|
|
1532
|
-
// v4.2.0+: shim mode is DEPRECATED — set for removal in v5.x.
|
|
1533
|
-
//
|
|
1534
|
-
// The empirical reason (verified by side-by-side fingerprint diff of
|
|
1535
|
-
// shim's `_rewriteBody` against the proxy's `buildCCRequest` — see
|
|
1536
|
-
// CHANGELOG v4.2.0 entry): shim mode only replaces 3 of the 8 axes
|
|
1537
|
-
// Anthropic's billing classifier actually inspects (system blocks,
|
|
1538
|
-
// agent identity, header order). It leaves the client's JSON key
|
|
1539
|
-
// order, max_tokens value, metadata billing tag, and any non-CC
|
|
1540
|
-
// fields (temperature, top_p, service_tier) unchanged on the wire.
|
|
1541
|
-
// And on the most-common claude -p / Agent-SDK request shape (which
|
|
1542
|
-
// sends a 1-block system, not the 3-block shape shim's shape-check
|
|
1543
|
-
// hardcodes), shim silently falls back to total passthrough — sending
|
|
1544
|
-
// the client's raw body to api.anthropic.com with zero replay.
|
|
1545
|
-
//
|
|
1546
|
-
// For interactive CC (`dario shim -- claude`), this is mostly a no-op
|
|
1547
|
-
// because CC's own outbound already matches every axis dario would
|
|
1548
|
-
// synthesize. But for any non-CC client (`dario shim -- aider`,
|
|
1549
|
-
// `dario shim -- cline`, your own scripts), shim mode does not deliver
|
|
1550
|
-
// the wire fidelity the README claims.
|
|
1551
|
-
//
|
|
1552
|
-
// We warn loudly here instead of silently breaking, and point users
|
|
1553
|
-
// at proxy mode. Set DARIO_SHIM_NO_DEPRECATION_WARNING=1 to suppress
|
|
1554
|
-
// the banner for scripts that need the exit-code semantics but have
|
|
1555
|
-
// already migrated their understanding.
|
|
1556
|
-
if (process.env['DARIO_SHIM_NO_DEPRECATION_WARNING'] !== '1') {
|
|
1557
|
-
console.error('');
|
|
1558
|
-
console.error('[dario] ⚠ DEPRECATION: `dario shim` is deprecated in v4.2 and scheduled for removal in v5.x.');
|
|
1559
|
-
console.error('[dario]');
|
|
1560
|
-
console.error('[dario] Shim mode only matches a subset of the wire-shape axes Anthropic\'s billing classifier');
|
|
1561
|
-
console.error('[dario] inspects. Specifically, it does not normalize JSON key order, max_tokens, metadata');
|
|
1562
|
-
console.error('[dario] billing-tag, or non-CC body fields. On `claude -p` / Agent-SDK style requests (1-block');
|
|
1563
|
-
console.error('[dario] system), shim falls back to total passthrough — the client\'s raw body reaches the');
|
|
1564
|
-
console.error('[dario] upstream unchanged.');
|
|
1565
|
-
console.error('[dario]');
|
|
1566
|
-
console.error('[dario] Use proxy mode instead, which rebuilds every request to CC\'s exact wire shape:');
|
|
1567
|
-
console.error('[dario]');
|
|
1568
|
-
console.error('[dario] Terminal 1: dario proxy');
|
|
1569
|
-
console.error('[dario] Terminal 2: ANTHROPIC_BASE_URL=http://localhost:3456 \\');
|
|
1570
|
-
console.error('[dario] ANTHROPIC_API_KEY=dario \\');
|
|
1571
|
-
console.error('[dario] ' + childArgs.join(' '));
|
|
1572
|
-
console.error('[dario]');
|
|
1573
|
-
console.error('[dario] To suppress this banner: DARIO_SHIM_NO_DEPRECATION_WARNING=1');
|
|
1574
|
-
console.error('');
|
|
1575
|
-
}
|
|
1576
|
-
const { runShim } = await import('./shim/host.js');
|
|
1577
|
-
try {
|
|
1578
|
-
const result = await runShim({
|
|
1579
|
-
command: childArgs[0],
|
|
1580
|
-
args: childArgs.slice(1),
|
|
1581
|
-
verbose,
|
|
1582
|
-
priority,
|
|
1583
|
-
});
|
|
1584
|
-
if (verbose) {
|
|
1585
|
-
const summary = result.analytics.summary(60);
|
|
1586
|
-
console.error(`[dario shim] ${result.events.length} relay events, ` +
|
|
1587
|
-
`subscriptionPercent=${summary.window.subscriptionPercent}%`);
|
|
1588
|
-
}
|
|
1589
|
-
process.exit(result.exitCode);
|
|
1590
|
-
}
|
|
1591
|
-
catch (err) {
|
|
1592
|
-
console.error('shim failed:', sanitizeError(err));
|
|
1593
|
-
process.exit(1);
|
|
1594
|
-
}
|
|
1512
|
+
console.error('`dario shim` was removed in v5.0. Use proxy mode instead:');
|
|
1513
|
+
console.error('');
|
|
1514
|
+
console.error(' Terminal 1: dario proxy');
|
|
1515
|
+
console.error(' Terminal 2: ANTHROPIC_BASE_URL=http://localhost:3456 \\');
|
|
1516
|
+
console.error(' ANTHROPIC_API_KEY=dario \\');
|
|
1517
|
+
console.error(' <your command>');
|
|
1518
|
+
console.error('');
|
|
1519
|
+
console.error('See MIGRATION.md (v4 → v5) for details.');
|
|
1520
|
+
process.exit(1);
|
|
1595
1521
|
}
|
|
1596
1522
|
async function subagent() {
|
|
1597
1523
|
const sub = args[1] ?? 'status';
|
package/dist/config-report.js
CHANGED
|
@@ -82,10 +82,25 @@ export async function collectEffectiveConfig() {
|
|
|
82
82
|
try {
|
|
83
83
|
const { listAccountAliases } = await import('./accounts.js');
|
|
84
84
|
const aliases = await listAccountAliases();
|
|
85
|
+
// Pool-as-primitive (v5.0): the pool is the one credential model. An empty
|
|
86
|
+
// accounts/ dir means either not-logged-in or a `dario login` whose
|
|
87
|
+
// credentials.json hasn't been back-filled into the pool yet (that happens
|
|
88
|
+
// on the next `dario login` / `dario proxy`), so report the pending pool-of-one.
|
|
89
|
+
let mode;
|
|
90
|
+
if (aliases.length > 0) {
|
|
91
|
+
mode = `pool of ${aliases.length}`;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const { loadCredentials } = await import('./oauth.js');
|
|
95
|
+
const creds = await loadCredentials();
|
|
96
|
+
mode = creds?.claudeAiOauth?.accessToken
|
|
97
|
+
? 'pool of 1 (login, not yet materialized)'
|
|
98
|
+
: 'empty (run `dario login`)';
|
|
99
|
+
}
|
|
85
100
|
sections.push({
|
|
86
101
|
title: 'Account pool',
|
|
87
102
|
rows: [
|
|
88
|
-
{ label: 'mode', value:
|
|
103
|
+
{ label: 'mode', value: mode },
|
|
89
104
|
...(aliases.length > 0 ? [{ label: 'aliases', value: aliases.join(', ') }] : []),
|
|
90
105
|
],
|
|
91
106
|
});
|
package/dist/doctor.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export interface IdentityDriftInput {
|
|
|
70
70
|
deviceId: string;
|
|
71
71
|
accountUuid: string;
|
|
72
72
|
} | null;
|
|
73
|
-
/** Pool account snapshots — `[]`
|
|
73
|
+
/** Pool account snapshots — `[]` when no pool accounts are materialized yet. */
|
|
74
74
|
poolAccounts: Array<{
|
|
75
75
|
alias: string;
|
|
76
76
|
deviceId: string;
|
package/dist/doctor.js
CHANGED
|
@@ -104,7 +104,7 @@ export function checkIdentityDrift(input) {
|
|
|
104
104
|
return [{
|
|
105
105
|
status: 'info',
|
|
106
106
|
label: 'Identity',
|
|
107
|
-
detail: `~/.claude.json userID=${shortId(live.deviceId)} —
|
|
107
|
+
detail: `~/.claude.json userID=${shortId(live.deviceId)} — no pool accounts snapshotted yet, so identity drift can't be checked. It starts once the login pool-of-one is materialized (\`dario login\` / \`dario proxy\`) or you \`dario accounts add\` more; until then a mismatch only surfaces as a 401 from Anthropic on non-Haiku models.`,
|
|
108
108
|
}];
|
|
109
109
|
}
|
|
110
110
|
const aligned = [];
|
|
@@ -740,7 +740,17 @@ export async function runChecks(opts = {}) {
|
|
|
740
740
|
const { listAccountAliases, loadAllAccounts } = await import('./accounts.js');
|
|
741
741
|
const aliases = await listAccountAliases();
|
|
742
742
|
if (aliases.length === 0) {
|
|
743
|
-
|
|
743
|
+
// Pool-as-primitive (v5.0): no accounts/ entries. Either not logged in,
|
|
744
|
+
// or a pre-v5 `dario login` whose credentials.json hasn't been back-filled
|
|
745
|
+
// into the pool yet — that happens on the next `dario login` / `dario proxy`.
|
|
746
|
+
const { loadCredentials } = await import('./oauth.js');
|
|
747
|
+
const creds = await loadCredentials();
|
|
748
|
+
if (creds?.claudeAiOauth?.accessToken) {
|
|
749
|
+
checks.push({ status: 'info', label: 'Pool', detail: 'pool of 1 (login credentials present, not yet materialized — runs on next `dario login` or `dario proxy`); `dario accounts add <alias>` adds more for headroom routing' });
|
|
750
|
+
}
|
|
751
|
+
else {
|
|
752
|
+
checks.push({ status: 'info', label: 'Pool', detail: 'empty — run `dario login` (a pool of one) or `dario accounts add <alias>`' });
|
|
753
|
+
}
|
|
744
754
|
}
|
|
745
755
|
else {
|
|
746
756
|
const loaded = await loadAllAccounts();
|
|
@@ -749,9 +759,9 @@ export async function runChecks(opts = {}) {
|
|
|
749
759
|
checks.push({
|
|
750
760
|
status: expired > 0 ? 'warn' : 'ok',
|
|
751
761
|
label: 'Pool',
|
|
752
|
-
detail:
|
|
762
|
+
detail: `pool of ${aliases.length}` +
|
|
753
763
|
(expired > 0 ? `, ${expired} expired` : '') +
|
|
754
|
-
(aliases.length === 1 ? ' (pool
|
|
764
|
+
(aliases.length === 1 ? ' (a pool of one — `dario accounts add <alias>` to load-balance)' : ''),
|
|
755
765
|
});
|
|
756
766
|
// Next-account-in-rotation surfacing. The proxy's per-request
|
|
757
767
|
// selector picks by max headroom (with 7d_<family> per-model
|
|
@@ -761,9 +771,9 @@ export async function runChecks(opts = {}) {
|
|
|
761
771
|
// operators wondering "if I send a request right now, which
|
|
762
772
|
// account gets it?" — it matches `pool.select()` with no family
|
|
763
773
|
// hint, the same call the proxy uses when no model is parsed
|
|
764
|
-
// yet (e.g. on misshapen requests).
|
|
765
|
-
// account is
|
|
766
|
-
if (aliases.length >=
|
|
774
|
+
// yet (e.g. on misshapen requests). Shown for a pool of one too
|
|
775
|
+
// (v5.0): it confirms the sole account is eligible, not rejected.
|
|
776
|
+
if (aliases.length >= 1) {
|
|
767
777
|
try {
|
|
768
778
|
const { AccountPool } = await import('./pool.js');
|
|
769
779
|
const pool = new AccountPool();
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
* provided both run on the same Node major. A cross-runtime worry
|
|
42
42
|
* surfaces when Anthropic ships Bun- or bundled-binary CC: at that
|
|
43
43
|
* point Node-dario and Bun-CC would JA-differ.
|
|
44
|
-
* → Mitigation:
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* → Mitigation: dario auto-relaunches under Bun when it's on PATH so
|
|
45
|
+
* the proxy's ClientHello matches CC's Bun/BoringSSL shape;
|
|
46
|
+
* `--strict-tls` refuses to start otherwise.
|
|
47
47
|
*
|
|
48
48
|
* 3. HTTP/2 frame ordering + SETTINGS parameters. Similar to TLS, this
|
|
49
49
|
* is controlled by the HTTP library. Node and undici produce a
|
|
@@ -115,8 +115,8 @@ export interface TemplateData {
|
|
|
115
115
|
/**
|
|
116
116
|
* The `anthropic-beta` flag set CC sent on the captured request, verbatim.
|
|
117
117
|
* Schema v2 (v3.19). Previously the proxy path hardcoded this — bumping
|
|
118
|
-
* CC's beta list required a dario release. Now the
|
|
119
|
-
*
|
|
118
|
+
* CC's beta list required a dario release. Now the proxy replays
|
|
119
|
+
* whatever the live capture recorded. Falls back to
|
|
120
120
|
* `'claude-code-20250219'` when undefined (bundled snapshots, older caches).
|
|
121
121
|
*/
|
|
122
122
|
anthropic_beta?: string;
|
|
@@ -236,9 +236,9 @@ export declare function probeInstalledCCVersion(): string | null;
|
|
|
236
236
|
export declare function formatCaptureAge(capturedIso: string, now?: number): string;
|
|
237
237
|
/**
|
|
238
238
|
* One-line human summary of the active template — what source, which CC
|
|
239
|
-
* version captured it, and how old that capture is. Proxy
|
|
240
|
-
*
|
|
241
|
-
*
|
|
239
|
+
* version captured it, and how old that capture is. Proxy startup logs
|
|
240
|
+
* this so users can tell at a glance whether they're on a fresh live
|
|
241
|
+
* capture or a stale bundled fallback.
|
|
242
242
|
*/
|
|
243
243
|
export declare function describeTemplate(t: TemplateData): string;
|
|
244
244
|
export interface DriftResult {
|
package/dist/live-fingerprint.js
CHANGED
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
* provided both run on the same Node major. A cross-runtime worry
|
|
42
42
|
* surfaces when Anthropic ships Bun- or bundled-binary CC: at that
|
|
43
43
|
* point Node-dario and Bun-CC would JA-differ.
|
|
44
|
-
* → Mitigation:
|
|
45
|
-
*
|
|
46
|
-
*
|
|
44
|
+
* → Mitigation: dario auto-relaunches under Bun when it's on PATH so
|
|
45
|
+
* the proxy's ClientHello matches CC's Bun/BoringSSL shape;
|
|
46
|
+
* `--strict-tls` refuses to start otherwise.
|
|
47
47
|
*
|
|
48
48
|
* 3. HTTP/2 frame ordering + SETTINGS parameters. Similar to TLS, this
|
|
49
49
|
* is controlled by the HTTP library. Node and undici produce a
|
|
@@ -735,9 +735,9 @@ export function formatCaptureAge(capturedIso, now = Date.now()) {
|
|
|
735
735
|
}
|
|
736
736
|
/**
|
|
737
737
|
* One-line human summary of the active template — what source, which CC
|
|
738
|
-
* version captured it, and how old that capture is. Proxy
|
|
739
|
-
*
|
|
740
|
-
*
|
|
738
|
+
* version captured it, and how old that capture is. Proxy startup logs
|
|
739
|
+
* this so users can tell at a glance whether they're on a fresh live
|
|
740
|
+
* capture or a stale bundled fallback.
|
|
741
741
|
*/
|
|
742
742
|
export function describeTemplate(t) {
|
|
743
743
|
const source = t._source ?? 'bundled';
|
package/dist/proxy.d.ts
CHANGED
|
@@ -463,17 +463,8 @@ export declare function describeAuthReject(headers: IncomingMessage['headers']):
|
|
|
463
463
|
*/
|
|
464
464
|
export declare function upstreamAuthHeaders(upstreamApiKey: string, accessToken: string): Record<string, string>;
|
|
465
465
|
/**
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* `dario accounts add` bootstraps a servable proxy with no `dario login`
|
|
469
|
-
* step — and admin mode always does (#599), where the pool may start empty
|
|
470
|
-
* and be populated over HTTP. Login-only setups (no accounts/ entries) keep
|
|
471
|
-
* the single-account credentials.json path. Pure + exported for unit
|
|
472
|
-
* testing.
|
|
473
|
-
*/
|
|
474
|
-
export declare function shouldUsePool(accountCount: number, adminEnabled: boolean): boolean;
|
|
475
|
-
/**
|
|
476
|
-
* Resolve the single-account startup auth outcome, refreshing an expired-but-
|
|
466
|
+
* Resolve the startup auth outcome when the pool is empty and there's a
|
|
467
|
+
* `dario login` credentials.json to fall back on — refreshing an expired-but-
|
|
477
468
|
* refreshable access token before giving up.
|
|
478
469
|
*
|
|
479
470
|
* The classic single-account startup used to read getStatus() once and, on any
|