@askalf/dario 5.4.16 → 5.4.19
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/cc-template.d.ts +11 -0
- package/dist/cc-template.js +68 -0
- package/dist/live-fingerprint.d.ts +0 -6
- package/dist/live-fingerprint.js +0 -8
- package/dist/proxy.js +26 -3
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -4
- package/docs/admin-api.md +154 -0
- package/docs/commands.md +77 -0
- package/docs/configuration.md +109 -0
- package/docs/docker.md +233 -0
- package/docs/drift-monitor.md +290 -0
- package/docs/faq.md +145 -0
- package/docs/integrations/agent-compat.md +269 -0
- package/docs/integrations/compat-matrix.md +51 -0
- package/docs/integrations/hands-walkthrough.md +295 -0
- package/docs/integrations/openclaw-walkthrough.md +248 -0
- package/docs/integrations/openhands-walkthrough.md +255 -0
- package/docs/mcp-server.md +22 -0
- package/docs/multi-account-pool.md +68 -0
- package/docs/research/system-prompt-classifier-study.md +288 -0
- package/docs/returning.md +94 -0
- package/docs/sub-agent.md +13 -0
- package/docs/system-prompt.md +107 -0
- package/docs/usage.md +123 -0
- package/docs/vpn-routing.md +108 -0
- package/docs/why-now-2026-06.md +93 -0
- package/docs/wire-fidelity.md +16 -0
- package/package.json +4 -2
package/dist/cc-template.d.ts
CHANGED
|
@@ -170,6 +170,17 @@ export declare const CC_AGENT_IDENTITY: string;
|
|
|
170
170
|
*/
|
|
171
171
|
export declare const CLIENT_SYSTEM_PREFACE: string;
|
|
172
172
|
export declare function resolveSystemPrompt(arg: string | undefined, model?: string): string;
|
|
173
|
+
/**
|
|
174
|
+
* Pick the CC-identity headers out of an inbound request so the passthrough
|
|
175
|
+
* path can forward them unchanged.
|
|
176
|
+
*
|
|
177
|
+
* Pure and exported so the allow/deny behaviour is unit-testable without
|
|
178
|
+
* standing up the proxy, matching `orderHeadersForOutbound` and
|
|
179
|
+
* `overlayTemplateHeaderValues`. Array-valued headers (Node allows repeats)
|
|
180
|
+
* take the first value; empty strings are skipped so a client sending a blank
|
|
181
|
+
* header cannot blank out a value dario would otherwise supply.
|
|
182
|
+
*/
|
|
183
|
+
export declare function forwardClientCCIdentityHeaders(reqHeaders: Record<string, string | string[] | undefined>): Record<string, string>;
|
|
173
184
|
/**
|
|
174
185
|
* Overlay a captured template's `header_values` onto the outbound header record,
|
|
175
186
|
* skipping the keys that must never be replayed.
|
package/dist/cc-template.js
CHANGED
|
@@ -283,6 +283,74 @@ function stripBehavioralConstraints(input, level) {
|
|
|
283
283
|
* so new captures are clean. This skip list is what makes every ALREADY-baked
|
|
284
284
|
* template and warm cache self-heal without waiting for a re-bake.
|
|
285
285
|
*/
|
|
286
|
+
/**
|
|
287
|
+
* Headers a genuine Claude Code client sends to identify itself, which the
|
|
288
|
+
* passthrough path forwards verbatim instead of substituting template values.
|
|
289
|
+
*
|
|
290
|
+
* The template exists to SYNTHESISE CC's shape for clients that are not CC. On
|
|
291
|
+
* the passthrough path `isGenuineCCClient` has already established that the
|
|
292
|
+
* caller really is Claude Code, so its own headers are the authentic article and
|
|
293
|
+
* a capture is at best a good imitation of them. Measured before this changed:
|
|
294
|
+
* of 13 CC-identity headers a real client sent, 12 were replaced with template
|
|
295
|
+
* values and 1 was dropped — 0 forwarded (dario#885).
|
|
296
|
+
*
|
|
297
|
+
* Deliberately NOT in this list, because dario must own them:
|
|
298
|
+
*
|
|
299
|
+
* authorization / x-api-key must become the pool account's credential
|
|
300
|
+
* x-claude-code-session-id session rotation is a feature, not an accident
|
|
301
|
+
* anthropic-beta merged with operator pins + the per-account
|
|
302
|
+
* rejection cache; the client's set is not final
|
|
303
|
+
* anthropic-version already read from the client at the call site
|
|
304
|
+
* accept / content-type body framing, owned by the proxy
|
|
305
|
+
* host / connection / transport, owned by the HTTP stack; forwarding
|
|
306
|
+
* content-length / them corrupts the request
|
|
307
|
+
* transfer-encoding /
|
|
308
|
+
* accept-encoding / keep-alive
|
|
309
|
+
*
|
|
310
|
+
* Anything a future CC adds under the `x-stainless-*` or `x-claude-code-*`
|
|
311
|
+
* prefixes is forwarded by the prefix rules in
|
|
312
|
+
* `forwardClientCCIdentityHeaders` rather than needing to be enumerated here —
|
|
313
|
+
* the capture cannot see first-party-conditional headers at all (dario#885), so
|
|
314
|
+
* an allowlist of exact names would silently miss them.
|
|
315
|
+
*/
|
|
316
|
+
const CC_IDENTITY_HEADERS_TO_FORWARD = new Set([
|
|
317
|
+
'user-agent',
|
|
318
|
+
'x-app',
|
|
319
|
+
'anthropic-dangerous-direct-browser-access',
|
|
320
|
+
]);
|
|
321
|
+
/** Prefixes whose every member is CC self-identification, forwarded wholesale. */
|
|
322
|
+
const CC_IDENTITY_HEADER_PREFIXES = ['x-stainless-', 'x-claude-code-', 'x-client-'];
|
|
323
|
+
/** Never forwarded from the client even when it matches a prefix above. */
|
|
324
|
+
const NEVER_FORWARD_FROM_CLIENT = new Set([
|
|
325
|
+
'x-claude-code-session-id', // dario rotates sessions deliberately
|
|
326
|
+
]);
|
|
327
|
+
/**
|
|
328
|
+
* Pick the CC-identity headers out of an inbound request so the passthrough
|
|
329
|
+
* path can forward them unchanged.
|
|
330
|
+
*
|
|
331
|
+
* Pure and exported so the allow/deny behaviour is unit-testable without
|
|
332
|
+
* standing up the proxy, matching `orderHeadersForOutbound` and
|
|
333
|
+
* `overlayTemplateHeaderValues`. Array-valued headers (Node allows repeats)
|
|
334
|
+
* take the first value; empty strings are skipped so a client sending a blank
|
|
335
|
+
* header cannot blank out a value dario would otherwise supply.
|
|
336
|
+
*/
|
|
337
|
+
export function forwardClientCCIdentityHeaders(reqHeaders) {
|
|
338
|
+
const out = {};
|
|
339
|
+
for (const [rawName, rawValue] of Object.entries(reqHeaders)) {
|
|
340
|
+
const name = rawName.toLowerCase();
|
|
341
|
+
if (NEVER_FORWARD_FROM_CLIENT.has(name))
|
|
342
|
+
continue;
|
|
343
|
+
const allowed = CC_IDENTITY_HEADERS_TO_FORWARD.has(name)
|
|
344
|
+
|| CC_IDENTITY_HEADER_PREFIXES.some((p) => name.startsWith(p));
|
|
345
|
+
if (!allowed)
|
|
346
|
+
continue;
|
|
347
|
+
const value = Array.isArray(rawValue) ? rawValue[0] : rawValue;
|
|
348
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
349
|
+
continue;
|
|
350
|
+
out[name] = value;
|
|
351
|
+
}
|
|
352
|
+
return out;
|
|
353
|
+
}
|
|
286
354
|
const NEVER_REPLAY_HEADER_VALUES = new Set([
|
|
287
355
|
'x-api-key',
|
|
288
356
|
'x-stainless-os',
|
|
@@ -336,12 +336,6 @@ export interface DriftResult {
|
|
|
336
336
|
* callers pass nothing and the real binary probe runs.
|
|
337
337
|
*/
|
|
338
338
|
export declare function detectDrift(t: TemplateData, installedOverride?: string | null): DriftResult;
|
|
339
|
-
/**
|
|
340
|
-
* Reset the memoized `claude --version` probe. Test-only — production
|
|
341
|
-
* code should never need to clear the cache since the installed binary
|
|
342
|
-
* doesn't change mid-process.
|
|
343
|
-
*/
|
|
344
|
-
export declare function _resetInstalledVersionProbeForTest(): void;
|
|
345
339
|
/**
|
|
346
340
|
* The CC version range the current dario release has been exercised
|
|
347
341
|
* against. Update `maxTested` every time we validate against a new CC
|
package/dist/live-fingerprint.js
CHANGED
|
@@ -919,14 +919,6 @@ export function detectDrift(t, installedOverride) {
|
|
|
919
919
|
message: `cache is from CC v${cachedVersion} but installed CC is v${installed} — background refresh will re-capture`,
|
|
920
920
|
};
|
|
921
921
|
}
|
|
922
|
-
/**
|
|
923
|
-
* Reset the memoized `claude --version` probe. Test-only — production
|
|
924
|
-
* code should never need to clear the cache since the installed binary
|
|
925
|
-
* doesn't change mid-process.
|
|
926
|
-
*/
|
|
927
|
-
export function _resetInstalledVersionProbeForTest() {
|
|
928
|
-
_installedVersionProbe = { value: null, cached: false };
|
|
929
|
-
}
|
|
930
922
|
// ============================================================
|
|
931
923
|
// CC version compat matrix (v3.17)
|
|
932
924
|
// ============================================================
|
package/dist/proxy.js
CHANGED
|
@@ -9,7 +9,7 @@ import { arch, platform } from 'node:process';
|
|
|
9
9
|
import { getAccessToken, getStatus } from './oauth.js';
|
|
10
10
|
import { buildHealthResponse, derivePoolStatus, shouldDiscloseHealthInternals } from './health-response.js';
|
|
11
11
|
import { darioVersion } from './version.js';
|
|
12
|
-
import { buildCCRequest, applyCcPromptCaching, parseEffortSuffix, reverseMapResponse, createStreamingReverseMapper, orderHeadersForOutbound, overlayTemplateHeaderValues, isMcpToolName, CC_TEMPLATE, effectiveCacheControl, withForced1hBeta } from './cc-template.js';
|
|
12
|
+
import { buildCCRequest, applyCcPromptCaching, parseEffortSuffix, reverseMapResponse, createStreamingReverseMapper, orderHeadersForOutbound, overlayTemplateHeaderValues, forwardClientCCIdentityHeaders, isMcpToolName, CC_TEMPLATE, effectiveCacheControl, withForced1hBeta } from './cc-template.js';
|
|
13
13
|
import { stampCch, hasCchSeed } from './cch.js';
|
|
14
14
|
import { describeTemplate, detectDrift, checkCCCompat } from './live-fingerprint.js';
|
|
15
15
|
import { AccountPool, computeStickyKey, parseRateLimits, modelFamily, isInAuthCooldown, authCooldownMs, reconcilePoolAccounts, resolvePoolStrategy } from './pool.js';
|
|
@@ -2064,6 +2064,12 @@ export async function startProxy(opts = {}) {
|
|
|
2064
2064
|
let requestModel = '';
|
|
2065
2065
|
let detectedClientForLog;
|
|
2066
2066
|
let preserveToolsEffective = Boolean(opts.preserveTools);
|
|
2067
|
+
// Per-request: did isGenuineCCClient recognise the caller as real Claude
|
|
2068
|
+
// Code? Hoisted because the header build below needs it and `genuineCC` is
|
|
2069
|
+
// block-scoped where buildCCRequest destructures it. NOT the same thing as
|
|
2070
|
+
// `passthrough`, which is a startup CLI flag — conflating the two is why
|
|
2071
|
+
// the first version of this forwarded nothing (dario#885).
|
|
2072
|
+
let genuineCCRequest = false;
|
|
2067
2073
|
try {
|
|
2068
2074
|
// Select an account by headroom (v5.0: the pool is the one credential
|
|
2069
2075
|
// model, so every OAuth request selects from it — a plain `dario login`
|
|
@@ -2442,6 +2448,7 @@ export async function startProxy(opts = {}) {
|
|
|
2442
2448
|
preserveToolsEffective = Boolean(opts.preserveTools)
|
|
2443
2449
|
|| Boolean(genuineCC)
|
|
2444
2450
|
|| (Boolean(detectedClient) && !opts.hybridTools && !opts.mergeTools);
|
|
2451
|
+
genuineCCRequest = Boolean(genuineCC);
|
|
2445
2452
|
if (genuineCC && !ccPassthroughLogged) {
|
|
2446
2453
|
ccPassthroughLogged = true;
|
|
2447
2454
|
console.log('[dario] genuine Claude Code client — system + tools forwarded verbatim (byte-faithful passthrough)');
|
|
@@ -2688,15 +2695,31 @@ export async function startProxy(opts = {}) {
|
|
|
2688
2695
|
console.log(`[dario] #${requestCount} session: rotate (${assigned.reason})${poolAccount ? ` [${poolAccount.alias}]` : ''}`);
|
|
2689
2696
|
}
|
|
2690
2697
|
}
|
|
2698
|
+
// On the passthrough path `isGenuineCCClient` has already established the
|
|
2699
|
+
// caller IS Claude Code, so its own identity headers are the authentic
|
|
2700
|
+
// article — forward them instead of substituting template values. The
|
|
2701
|
+
// template is for synthesising CC's shape when the client is not CC; here it
|
|
2702
|
+
// would only be an imitation of headers we already hold. Measured before
|
|
2703
|
+
// this: 12 of 13 client CC-identity headers were replaced and 1 dropped,
|
|
2704
|
+
// 0 forwarded (dario#885). Spread AFTER staticHeaders so the client wins
|
|
2705
|
+
// over template values, and BEFORE the dario-owned block below so auth,
|
|
2706
|
+
// session rotation and the merged beta set still win over the client.
|
|
2707
|
+
const forwardedIdentity = (passthrough || genuineCCRequest)
|
|
2708
|
+
? forwardClientCCIdentityHeaders(req.headers)
|
|
2709
|
+
: {};
|
|
2691
2710
|
const headers = {
|
|
2692
2711
|
...staticHeaders,
|
|
2712
|
+
...forwardedIdentity,
|
|
2693
2713
|
...upstreamAuthHeaders(upstreamApiKey, accessToken),
|
|
2694
2714
|
'x-claude-code-session-id': outboundSessionId,
|
|
2695
2715
|
'anthropic-version': passthrough ? (req.headers['anthropic-version'] || '2023-06-01') : '2023-06-01',
|
|
2696
2716
|
'anthropic-beta': beta,
|
|
2697
|
-
|
|
2717
|
+
// Prefer the client's own when passthrough forwarded one: a genuine CC
|
|
2718
|
+
// request already carries a real request id, and synthesising over it
|
|
2719
|
+
// discards information for no gain. Falls back to a fresh uuid otherwise.
|
|
2720
|
+
'x-client-request-id': forwardedIdentity['x-client-request-id'] ?? randomUUID(),
|
|
2698
2721
|
// CC sends 600 on first request per session. With rotation, every request is "first"
|
|
2699
|
-
'x-stainless-timeout': '600',
|
|
2722
|
+
'x-stainless-timeout': forwardedIdentity['x-stainless-timeout'] ?? '600',
|
|
2700
2723
|
};
|
|
2701
2724
|
// Client-disconnect abort: if the client drops the connection before
|
|
2702
2725
|
// we've finished sending the response, we default to aborting the
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Headless admin API
|
|
2
|
+
|
|
3
|
+
An opt-in HTTP control plane for managing dario's account pool without console
|
|
4
|
+
access: provision the first account on an empty proxy, add or remove accounts
|
|
5
|
+
later, and read live per-account status — all over HTTP, with no `dario login`,
|
|
6
|
+
no TTY, and no restart. Built for the deployments where a console is the
|
|
7
|
+
awkward part: Docker, Kubernetes, a Raspberry Pi in a closet, a VPS you'd
|
|
8
|
+
rather not SSH into.
|
|
9
|
+
|
|
10
|
+
Requires dario **v4.8.111+** (the `/status` / `/health` behavior described
|
|
11
|
+
below is accurate as of **v4.8.117**).
|
|
12
|
+
|
|
13
|
+
## Enabling it
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
DARIO_ADMIN=1 DARIO_ADMIN_TOKEN=<long-random-string> dario proxy
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Variable | Purpose |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `DARIO_ADMIN=1` | Mounts the API at `/admin/*`. Off by default — the endpoints don't exist otherwise. |
|
|
22
|
+
| `DARIO_ADMIN_TOKEN` | Bearer token for every admin call. Falls back to `DARIO_API_KEY` if unset. |
|
|
23
|
+
| `DARIO_ADMIN_RATE_LIMIT=off` | Disables the built-in rate limiting (see below). Leave on. |
|
|
24
|
+
|
|
25
|
+
Two deliberate security properties:
|
|
26
|
+
|
|
27
|
+
- **Auth is always required, even on loopback.** These endpoints add and remove
|
|
28
|
+
OAuth credentials; the localhost trust shortcut the proxy key allows for LLM
|
|
29
|
+
routes does not apply here.
|
|
30
|
+
- **Enabled-but-tokenless fails closed.** `DARIO_ADMIN=1` with neither
|
|
31
|
+
`DARIO_ADMIN_TOKEN` nor `DARIO_API_KEY` set returns `403` with a message
|
|
32
|
+
telling you to set the token — account control is never left open.
|
|
33
|
+
|
|
34
|
+
Admin mode also changes one startup behavior: the proxy **starts with zero
|
|
35
|
+
accounts** instead of exiting `Not authenticated`. Until an account exists,
|
|
36
|
+
LLM requests return a truthful `503 { "error": "No account configured" }` with
|
|
37
|
+
a hint pointing at `POST /admin/login/start`.
|
|
38
|
+
|
|
39
|
+
## Zero to serving, over HTTP only
|
|
40
|
+
|
|
41
|
+
The login flow mirrors `dario accounts add --manual` (PKCE + manual code
|
|
42
|
+
paste), split into two calls:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
ADMIN='authorization: Bearer <your DARIO_ADMIN_TOKEN>'
|
|
46
|
+
BASE=http://127.0.0.1:3456
|
|
47
|
+
|
|
48
|
+
# 1. Start a login. Alias is optional — omit it and a non-colliding
|
|
49
|
+
# default (account-1, account-2, …) is generated and returned.
|
|
50
|
+
curl -s -X POST -H "$ADMIN" "$BASE/admin/login/start" -d '{"alias":"main"}'
|
|
51
|
+
# -> { "alias": "main",
|
|
52
|
+
# "authorize_url": "https://claude.ai/oauth/authorize?...",
|
|
53
|
+
# "expires_at": "...",
|
|
54
|
+
# "instructions": "Open authorize_url, approve, then POST ... to /admin/login/complete." }
|
|
55
|
+
|
|
56
|
+
# 2. Open authorize_url in any browser on any machine, approve, and copy the
|
|
57
|
+
# code Anthropic displays. Paste it back ("code#state" or bare code both work):
|
|
58
|
+
curl -s -X POST -H "$ADMIN" "$BASE/admin/login/complete" \
|
|
59
|
+
-d '{"alias":"main","code":"<pasted code>"}'
|
|
60
|
+
# -> { "alias": "main", "status": "added", "expires_at": "..." }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**The account is routable the moment the `200` lands.** `login/complete` (and
|
|
64
|
+
account removal) hot-reload the live pool from disk before responding — no
|
|
65
|
+
proxy restart, superseding the "takes effect on next restart" behavior of
|
|
66
|
+
early builds. The model catalog also refetches immediately with the new
|
|
67
|
+
account's credentials, so `/v1/models` upgrades from the baked list without
|
|
68
|
+
waiting out a retry window.
|
|
69
|
+
|
|
70
|
+
Pending-login mechanics, for scripting against it:
|
|
71
|
+
|
|
72
|
+
- A pending login lives **10 minutes** and is **single-use** — `/complete`
|
|
73
|
+
consumes it whether or not the token exchange succeeds.
|
|
74
|
+
- **One pending login per alias**; a second `/start` for the same alias
|
|
75
|
+
replaces the first.
|
|
76
|
+
- If the pasted blob carries a `state` and it doesn't match the pending
|
|
77
|
+
login's, `/complete` refuses (`400 state mismatch`) — the code came from a
|
|
78
|
+
different login attempt.
|
|
79
|
+
- An expired or unknown alias gets `410` — start a new login.
|
|
80
|
+
- The PKCE verifier and state never touch disk and are never returned to the
|
|
81
|
+
client.
|
|
82
|
+
|
|
83
|
+
## Endpoint reference
|
|
84
|
+
|
|
85
|
+
All endpoints accept the token as `authorization: Bearer <token>` or
|
|
86
|
+
`x-api-key: <token>`.
|
|
87
|
+
|
|
88
|
+
| Method + path | Body | Returns |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `POST /admin/login/start` | `{ "alias"?: string }` | `{ alias, authorize_url, expires_at, instructions }` |
|
|
91
|
+
| `POST /admin/login/complete` | `{ "alias": string, "code": string }` | `{ alias, status: "added", expires_at }` |
|
|
92
|
+
| `GET /admin/accounts` | — | `{ accounts: [...], count }` |
|
|
93
|
+
| `DELETE /admin/accounts/<alias>` | — | `{ alias, removed }` (`404` if no such alias) |
|
|
94
|
+
|
|
95
|
+
`GET /admin/accounts` is the monitoring surface: each entry carries the
|
|
96
|
+
persisted metadata (`alias`, `scopes`, `expires_in_ms`) **plus live pool
|
|
97
|
+
status whenever pool mode is active** — `util5h` / `util7d` utilization,
|
|
98
|
+
representative `claim` (e.g. `five_hour`), routing `status`, and
|
|
99
|
+
`request_count`. It's the admin-token-gated equivalent of the proxy-key-gated
|
|
100
|
+
`GET /accounts` pool view; a headless operator needs only the admin token to
|
|
101
|
+
watch headroom.
|
|
102
|
+
|
|
103
|
+
## What the generic surfaces report (v4.8.117+)
|
|
104
|
+
|
|
105
|
+
`/status` and `/health` derive from the live pool whenever pool mode is
|
|
106
|
+
active, so they track the admin lifecycle truthfully:
|
|
107
|
+
|
|
108
|
+
| Stage | `/status` | `/health` |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| Started empty (`DARIO_ADMIN=1`, no accounts) | `authenticated:false`, `status:"none"`, hint: add one via `POST /admin/login/start` | **503** `degraded` — correct: every LLM call 503s until an account exists |
|
|
111
|
+
| ≥1 account added | `authenticated:true`, `status:"healthy"`, `mode:"pool"`, `accounts:N`, earliest token expiry | **200** `ok` — docker healthchecks and `depends_on: service_healthy` pass |
|
|
112
|
+
| All accounts in auth-cooldown (upstream 401s) | `status:"broken"`, `authenticated:false` | **503** `degraded` — the next request would fail |
|
|
113
|
+
|
|
114
|
+
If you're wiring a container healthcheck against a proxy that starts empty,
|
|
115
|
+
expect it to report unhealthy until the first account is provisioned — that's
|
|
116
|
+
the API telling you the truth, not a bug. Gate your bootstrap job on the
|
|
117
|
+
container being *up* (TCP/HTTP response), not *healthy*.
|
|
118
|
+
|
|
119
|
+
## Audit trail
|
|
120
|
+
|
|
121
|
+
Every mutation (`login_start`, `login_complete`, `account_remove`) and every
|
|
122
|
+
auth reject or throttle is logged with the action, target alias, outcome, HTTP
|
|
123
|
+
status, and client address — to the console always (so `docker logs` /
|
|
124
|
+
journald has the trail with zero setup), and as a structured
|
|
125
|
+
`event: "admin.<action>"` line when `--log-file` / `DARIO_LOG_FILE` is set.
|
|
126
|
+
Secrets never reach the audit sink.
|
|
127
|
+
|
|
128
|
+
## Rate limiting
|
|
129
|
+
|
|
130
|
+
Two global token buckets (per proxy, not per-IP — the surface is
|
|
131
|
+
loopback-default, so per-IP keying buys nothing), applied **after** auth for
|
|
132
|
+
mutations and **to failed auth attempts** separately:
|
|
133
|
+
|
|
134
|
+
- **Failed auth**: 10 burst, then 1 per 2s — a wrong-token flood is slowed,
|
|
135
|
+
not answered at full speed.
|
|
136
|
+
- **Mutations** (`login/start`, `login/complete`, account removal): 30 burst,
|
|
137
|
+
then 1 per 1s.
|
|
138
|
+
|
|
139
|
+
Over the limit returns `429` with a `Retry-After` header, and the throttle
|
|
140
|
+
itself is audited (`rate_limited`). Reads (`GET /admin/accounts`) and
|
|
141
|
+
successful auth are never throttled. `DARIO_ADMIN_RATE_LIMIT=off` disables
|
|
142
|
+
both buckets; the defaults are generous for a human plus scripts and only
|
|
143
|
+
bite runaway callers.
|
|
144
|
+
|
|
145
|
+
## Relationship to the CLI
|
|
146
|
+
|
|
147
|
+
The admin API and `dario accounts add/remove/list` manage the same on-disk
|
|
148
|
+
store (`~/.dario/accounts/`) and can be mixed freely. Pool mode activates at
|
|
149
|
+
**one** account, so a single `login/start`/`complete` round-trip on a fresh
|
|
150
|
+
box yields a serving proxy — `dario login` remains the single-default-account
|
|
151
|
+
one-liner for interactive setups and is never required on the admin path. See
|
|
152
|
+
[`docs/multi-account-pool.md`](./multi-account-pool.md) for how the pool
|
|
153
|
+
routes, and [`docs/docker.md`](./docker.md) for the container deployment this
|
|
154
|
+
API was built for.
|
package/docs/commands.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Commands and proxy options
|
|
2
|
+
|
|
3
|
+
This page is the per-flag reference. For environment variables grouped by task — overage guard, request queue, template fidelity, pacing — see [`configuration.md`](./configuration.md), which also covers the precedence order and the boolean-parsing rules.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
| Command | Description |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `dario login [--manual]` | Log in to the Claude backend. Detects CC credentials or runs its own OAuth flow. `--manual` (v3.20) mirrors CC's code-paste flow for SSH / container setups without a browser. |
|
|
10
|
+
| `dario proxy` | Start the local API proxy on port 3456 |
|
|
11
|
+
| `dario doctor [--probe] [--auth-check] [--json] [--bun-bootstrap]` | Aggregated health report — dario / Node / runtime-TLS / CC binary + compat / template + drift / per-request overhead / OAuth / pool + pool routing (next account in rotation when 2+ loaded) / backends / sub-agent. `--probe` (v3.31.7) hits the live `claude.ai/oauth/authorize` endpoint and surfaces the verdict, so scope-policy drift is catchable from a user's machine (not just CI). `--auth-check` (v3.31.9) opens a one-shot `x-api-key` listener and classifies whatever a client actually sends (match / mismatch / no-auth / timeout), with only redacted previews in output. `--json` (v3.31.8) emits structured output for deepdive's health probes and CI scrapers. `--bun-bootstrap` runs the canonical bun.sh installer when the runtime/TLS check is warning that Bun isn't on PATH. |
|
|
12
|
+
| `dario usage [--port=N] [--json]` | Burn-rate summary of the running proxy's traffic over the last 60 minutes: requests, input/output tokens, avg latency, error rate, subscription % vs. extra-usage, estimated API-equivalent cost, plus per-account breakdown when pool mode is active. Hits `/analytics` on the local proxy. When the proxy isn't reachable, prints a hint pointing at `dario doctor --usage` (the one-off rate-limit probe). `--json` emits the raw `/analytics` payload for status bars / CI dashboards. Also exposed as the `usage` tool in `dario mcp`. |
|
|
13
|
+
| `dario config [--json]` | Prints the effective dario configuration with credentials redacted. Complementary to `doctor` — doctor answers *is it working?*, config answers *what IS it?* (v3.31.10) |
|
|
14
|
+
| `dario upgrade` | Safe wrapper over `npm install -g @askalf/dario@latest` — probes npm for the `@latest` version first (3s timeout, 60s cache), refuses to run if already on latest, fails with a clear hint if npm is missing. (v3.31.10) |
|
|
15
|
+
| `dario status` | Show Claude backend OAuth token health and expiry |
|
|
16
|
+
| `dario refresh` | Force an immediate Claude token refresh |
|
|
17
|
+
| `dario logout` | Delete stored Claude credentials |
|
|
18
|
+
| `dario accounts list` / `add <alias>` / `remove <alias>` | Multi-account pool management. `add <alias>` on a fresh pool auto back-fills your existing `dario login` credentials as `login`, so your first `add` trips the 2+ pool threshold on its own — see [Multi-account pool mode](./multi-account-pool.md). |
|
|
19
|
+
| `dario backend list` / `add <name> --key=<key> [--base-url=<url>]` / `remove <name>` | OpenAI-compat backend management |
|
|
20
|
+
| `dario subagent install` / `remove` / `status` | CC sub-agent lifecycle. See [sub-agent hook](./sub-agent.md). |
|
|
21
|
+
| `dario mcp` | Run dario as an MCP server over stdio. See [MCP server](./mcp-server.md). |
|
|
22
|
+
| `dario help` | Full command reference |
|
|
23
|
+
|
|
24
|
+
## Proxy options
|
|
25
|
+
|
|
26
|
+
| Flag / env | Description | Default |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `--passthrough` / `--thin` | Thin proxy for the Claude backend — OAuth swap only, no template injection | off |
|
|
29
|
+
| `--preserve-tools` / `--keep-tools` | Keep client tool schemas instead of remapping to CC's. Required for clients whose tools have fields CC doesn't — see [Custom tool schemas](./integrations/agent-compat.md#custom-tool-schemas). Auto-enabled for Cline / Kilo Code / Roo Code and forks (detected via system-prompt identity markers). | off (auto for text-tool clients) |
|
|
30
|
+
| `--no-auto-detect` / `--no-auto-preserve` | Disable the text-tool-client detector so the CC wire shape stays intact on Cline/Kilo/Roo prompts (v3.20.1, dario#40). Explicit `--preserve-tools` still wins. | off |
|
|
31
|
+
| `--hybrid-tools` / `--context-inject` | Remap to CC tools **and** inject request-context values (`sessionId`, `requestId`, `channelId`, `userId`, `timestamp`) into client-declared fields CC's schema doesn't carry. See [Hybrid tool mode](./integrations/agent-compat.md#hybrid-tool-mode). | off |
|
|
32
|
+
| `--merge-tools` / `--append-tools` | **EXPERIMENTAL.** Send CC's canonical tools first, append the client's custom tools after (deduped by name, case-insensitive). Model can call either side; tool calls flow back unchanged. Mutually exclusive with `--preserve-tools` and `--hybrid-tools`. Anthropic's billing classifier may flip routing on the appended suffix — validate with `--verbose` and watch the `billing: <bucket>` line on the first 1-2 requests before relying on it. | off |
|
|
33
|
+
| `--model=<name>` | Force a model. Shortcuts (`fable`, `opus`, `sonnet`, `haiku`, and their `1m` long-context forms) always resolve to the newest model of that family in the live catalog; version pins (`opus48`, `opus47`, `opus46`, `sonnet46`) never float. Also full IDs (`claude-fable-5`, `claude-opus-5`), or a **provider prefix** (`openai:gpt-4o`, `groq:llama-3.3-70b`, `claude:fable`, `claude:opus`, `local:qwen-coder`) to force the backend server-wide. | passthrough |
|
|
34
|
+
| `--model-alias=<name=target>` / `DARIO_MODEL_ALIASES` / config `modelAliases` | User-defined model alias, repeatable. Applied to the client's model name before provider-prefix parsing, so a target may carry a prefix and retarget the backend (`--model-alias=my-fast=openai:gpt-4o-mini`). Advertised on `/v1/models` so client pickers offer it. Names match case-insensitively; targets forward verbatim; one step, never recursive. An alias may shadow a real id or built-in shortcut — that's how you remap every `opus` call from a client whose picker you don't control. Merge order per-key: config < env < flags. `--model` still wins downstream (it overrides the resolved model server-wide). | none |
|
|
35
|
+
| `--port=<n>` | Port to listen on | `3456` |
|
|
36
|
+
| `--host=<addr>` / `DARIO_HOST` | Bind address. Use `0.0.0.0` for LAN, or a specific IP (e.g. a Tailscale interface). When non-loopback, also set `DARIO_API_KEY`. | `127.0.0.1` |
|
|
37
|
+
| `--verbose` / `-v` | Log every request (one line per request — method + path + billing bucket) | off |
|
|
38
|
+
| `--verbose=2` / `-vv` / `DARIO_LOG_BODIES=1` | Also dump the outbound request body (redacted: bearer tokens, `sk-ant-*` keys, JWTs stripped; capped at 8KB). For wire-level client-compat debugging. | off |
|
|
39
|
+
| `--log-file=<path>` / `DARIO_LOG_FILE` | Append one JSON-ND record per completed request to PATH. Useful for backgrounded proxies where stdout is unobserved (where `--verbose` can't help). Field set: `ts`, `req`, `method`, `path`, `model`, `status`, `latency_ms`, `in_tokens`, `out_tokens`, `cache_read`, `cache_create`, `claim`, `bucket`, `account`, `client`, `preserve_tools`, `stream`, plus `reject` / `error` on failure paths. Secrets scrubbed via the same redactor that `--verbose-bodies` uses; no request bodies. | off |
|
|
40
|
+
| `--pool-fallback=<model>` / `DARIO_POOL_FALLBACK` / config `poolFallback.model` | Strictly opt-in. When every pool seat is drained or in auth cool-down, forward OpenAI-shape requests (`/v1/chat/completions`) to the configured openai-compat backend as `<model>` instead of surfacing the 429/503. Every fallback response carries `x-dario-pool-fallback: <model>` — never silent. Anthropic-shape requests keep the error (no reverse response translation). Requires an openai-compat backend (`dario backend add …`); inert without one. Empty pool still 503s (setup error, not traffic to re-bill). Empty flag value disables, overriding env + config. See [Pool-exhausted fallback](./multi-account-pool.md#pool-exhausted-fallback). | off |
|
|
41
|
+
| `--passthrough-betas=<csv>` / `DARIO_PASSTHROUGH_BETAS` | Beta flags ALWAYS forwarded upstream regardless of CC's captured set or the client's `anthropic-beta` header. Bypasses the billable-beta filter (so `extended-cache-ttl-*` survives if you opt in). Per-account rejection cache still applies — a pinned flag the upstream 400's gets dropped on retry rather than re-sent forever. Use when you know a beta works on your account but isn't in the captured template, or when client traffic should be force-augmented. Empty flag value (`--passthrough-betas=`) clears the env-default. | off |
|
|
42
|
+
| `--strict-tls` / `DARIO_STRICT_TLS=1` | Refuse to start proxy mode unless runtime classifies as `bun-match` — i.e. the TLS ClientHello matches CC's. See [Wire-fidelity axes](./wire-fidelity.md). (v3.23) | off |
|
|
43
|
+
| `--pace-min=<ms>` / `DARIO_PACE_MIN_MS` | Minimum inter-request gap in ms. Replaces the legacy hardcoded 500 ms. (v3.24) | `500` |
|
|
44
|
+
| `--pace-jitter=<ms>` / `DARIO_PACE_JITTER_MS` | Uniform random jitter added to each gap. Dissolves the minimum-inter-arrival observable edge. (v3.24) | `0` |
|
|
45
|
+
| `--drain-on-close` / `DARIO_DRAIN_ON_CLOSE=1` | When a downstream client disconnects mid-stream, keep reading upstream SSE to completion (match CC's consumption shape). Bounded by the 5-min upstream timeout. (v3.25) | off |
|
|
46
|
+
| `--session-idle-rotate=<ms>` / `DARIO_SESSION_IDLE_ROTATE_MS` | Idle threshold before a session-id rotates. (v3.28) | `900000` (15 min) |
|
|
47
|
+
| `--session-rotate-jitter=<ms>` / `DARIO_SESSION_JITTER_MS` | Jitter sampled once per session at creation — hides the exact idle floor. (v3.28) | `0` |
|
|
48
|
+
| `--session-max-age=<ms>` / `DARIO_SESSION_MAX_AGE_MS` | Hard ceiling on a session-id's lifetime regardless of activity. (v3.28) | off |
|
|
49
|
+
| `--session-per-client` / `DARIO_SESSION_PER_CLIENT=1` | Split session-id registry by a per-client header so multi-UI fan-out doesn't collapse onto one id. (v3.28) | off |
|
|
50
|
+
| `--pool-strategy=<headroom\|fill-first>` / `DARIO_POOL_STRATEGY` | Where new conversations land in a multi-account pool. `headroom` spreads them to the seat with the most slack; `fill-first` concentrates them on the alphabetically-first eligible seat until it drains to the 2% floor, then spills to the next — primary/backup semantics, alias naming (`1-main`, `2-overflow`) picks the fill order. Sticky bindings behave identically under both. See [Multi-account pool](./multi-account-pool.md#routing-strategy). | `headroom` |
|
|
51
|
+
| `--pool-fallback=<model>` / `DARIO_POOL_FALLBACK` / config `poolFallback.model` | When every pool seat is drained or in auth cool-down (at selection, or mid-flight on a 429 with no peer left), forward **OpenAI-shape** requests (`/v1/chat/completions`) to the configured openai-compat backend as `<model>` instead of surfacing the 429/503. Every substituted response carries `x-dario-pool-fallback: <model>` — a swapped model is never silent. Anthropic-shape requests (`/v1/messages`) keep the error: dario has no OpenAI→Anthropic response translation. Requires `dario backend add …`; inert otherwise. Empty flag value (`--pool-fallback=`) disables, overriding env + config. See [Multi-account pool](./multi-account-pool.md#pool-exhausted-fallback). | off |
|
|
52
|
+
| `--system-prompt=<verbatim\|partial\|aggressive\|filepath>` / `DARIO_SYSTEM_PROMPT` | System-prompt mode for outbound CC-shaped requests. `partial` strips behavioral constraints (Tone-and-style, Text-output, scope/verbosity/comment bullets) for ~1.2–2.8× output capability on open-ended work. `aggressive` adds prompt-level RLHF restatement removal (<3% over partial — alignment is RLHF-trained). `<filepath>` fully replaces the slot with file contents. Empirically validated as unfingerprinted by the billing classifier — see [`system-prompt.md`](./system-prompt.md) and [`research/system-prompt-classifier-study.md`](./research/system-prompt-classifier-study.md). (v3.34) | `verbatim` |
|
|
53
|
+
| `--upstream-proxy=<url>` / `--via=<url>` / `DARIO_UPSTREAM_PROXY` | Route dario's outbound fetches (api.anthropic.com, OpenAI-compat backends, OAuth) through an HTTP/HTTPS proxy. Pair with the HTTP proxy mode of a VPN provider (Mullvad, AirVPN), a corporate proxy, privoxy/Tor, etc. Localhost calls bypass. Requires Bun runtime; SOCKS5 not supported. Full provider matrix + setup in [`vpn-routing.md`](./vpn-routing.md). (v3.35) | unset |
|
|
54
|
+
| `DARIO_API_KEY` | If set, all endpoints (except `/health`) require a matching `x-api-key` or `Authorization: Bearer` header. Required when `--host` binds non-loopback. | unset (open) |
|
|
55
|
+
| `DARIO_CORS_ORIGIN` | Override browser CORS origin | `http://localhost:${port}` |
|
|
56
|
+
| `DARIO_QUIET_TLS` | Suppress the runtime/TLS mismatch startup banner | unset |
|
|
57
|
+
| `DARIO_NO_BUN` | Disable automatic Bun relaunch | unset |
|
|
58
|
+
| `DARIO_MIN_INTERVAL_MS` | Legacy name for `DARIO_PACE_MIN_MS`. Still honored; new name wins when both are set. | — |
|
|
59
|
+
| `DARIO_CC_PATH` | Override path to the Claude Code binary for OAuth detection | auto-detect |
|
|
60
|
+
| `DARIO_OAUTH_CLIENT_ID` | Override the detected Claude OAuth client id as an emergency escape hatch | unset |
|
|
61
|
+
| `DARIO_OAUTH_AUTHORIZE_URL` | Override the detected Claude OAuth authorize URL | unset |
|
|
62
|
+
| `DARIO_OAUTH_TOKEN_URL` | Override the detected Claude OAuth token URL | unset |
|
|
63
|
+
| `DARIO_OAUTH_SCOPES` | Override the detected Claude OAuth scopes | unset |
|
|
64
|
+
| `DARIO_OAUTH_OVERRIDE_PATH` | Override file path for JSON OAuth overrides | `~/.dario/oauth-config.override.json` |
|
|
65
|
+
| `DARIO_OAUTH_DISABLE_OVERRIDE=1` | Ignore env/file OAuth overrides entirely | unset |
|
|
66
|
+
|
|
67
|
+
## Endpoints
|
|
68
|
+
|
|
69
|
+
| Path | Description |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `POST /v1/messages` | Anthropic Messages API (Claude backend) |
|
|
72
|
+
| `POST /v1/chat/completions` | OpenAI-compatible Chat API (routes by model name) |
|
|
73
|
+
| `GET /v1/models` | Model list (Claude models — OpenAI models come from the OpenAI backend directly) |
|
|
74
|
+
| `GET /health` | Proxy health + OAuth status + request count |
|
|
75
|
+
| `GET /status` | Detailed Claude OAuth token status |
|
|
76
|
+
| `GET /accounts` | Pool snapshot including sticky binding count (pool mode only) |
|
|
77
|
+
| `GET /analytics` | Per-account / per-model stats, burn rate, exhaustion predictions, `billingBucket` + `subscriptionPercent` per request |
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Every knob below is settable three ways. Precedence, highest first:
|
|
4
|
+
|
|
5
|
+
1. a CLI flag
|
|
6
|
+
2. an environment variable
|
|
7
|
+
3. `~/.dario/config.json`
|
|
8
|
+
4. the built-in default
|
|
9
|
+
|
|
10
|
+
`dario --help` is the complete list and always matches the binary you have installed. [`commands.md`](./commands.md) documents the proxy options flag-by-flag, including the OAuth overrides, session-rotation and TLS vars not repeated here.
|
|
11
|
+
|
|
12
|
+
This page is the other view: grouped by what you are trying to do, covering the vars that matter when you cannot pass a flag — Docker, Compose, k8s, systemd — plus the ones whose behaviour has a sharp edge worth stating in prose. Anything documented in `commands.md` is deliberately not restated here; two copies of a default is one that goes stale.
|
|
13
|
+
|
|
14
|
+
## Booleans
|
|
15
|
+
|
|
16
|
+
Two shapes, and the difference is not cosmetic.
|
|
17
|
+
|
|
18
|
+
**Off-switches** (`DARIO_OVERAGE_GUARD`, `DARIO_OVERAGE_NOTIFY`) accept `on|1|true|yes` and `off|0|false|no`. They guard features that default **on**, so they have to be able to say no.
|
|
19
|
+
|
|
20
|
+
**On-switches** (everything else) accept only `1|true|yes|on`. They guard features that default **off**, so an unset var and a falsy var mean the same thing and there is nothing to express.
|
|
21
|
+
|
|
22
|
+
An unrecognised value is ignored in both cases and the next source down wins. A typo leaves you on the default rather than silently flipping the knob.
|
|
23
|
+
|
|
24
|
+
> `DARIO_OVERAGE_GUARD=off` and `DARIO_OVERAGE_NOTIFY=off` were documented in `cli.ts` from v4.1 but did nothing until v5.4.14 — the shared parser could only return `true` or `undefined`, so `off` fell through the `?? … ?? true` chain and the guard stayed on. Container deployments were the only ones affected, because a flag was the sole working way to turn it off.
|
|
25
|
+
|
|
26
|
+
## Overage guard
|
|
27
|
+
|
|
28
|
+
Halts the proxy when an upstream response reports `representative-claim: overage`, so a subscription never silently starts billing per token. Defaults on. See [`#288`](https://github.com/askalf/dario/issues/288).
|
|
29
|
+
|
|
30
|
+
| Variable | Flag | Default | Values |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| `DARIO_OVERAGE_GUARD` | `--no-overage-guard` | on | off-switch |
|
|
33
|
+
| `DARIO_OVERAGE_BEHAVIOR` | `--overage-behavior=` | `halt` | `halt` returns 503 until cooldown or `dario resume`; `warn` logs and keeps serving |
|
|
34
|
+
| `DARIO_OVERAGE_COOLDOWN` | `--overage-cooldown=MS` | `1800000` (30 min) | ms |
|
|
35
|
+
| `DARIO_OVERAGE_NOTIFY` | `--no-overage-notify` | on | off-switch; suppresses the desktop notification only |
|
|
36
|
+
|
|
37
|
+
## Request queue
|
|
38
|
+
|
|
39
|
+
| Variable | Flag | Default | Notes |
|
|
40
|
+
|---|---|---|---|
|
|
41
|
+
| `DARIO_MAX_CONCURRENT` | `--max-concurrent=N` | `10` | in-flight ceiling |
|
|
42
|
+
| `DARIO_MAX_QUEUED` | `--max-queued=N` | `128` | buffered waiting for a slot; over this, dario returns 429 `queue-full` |
|
|
43
|
+
| `DARIO_QUEUE_TIMEOUT_MS` | `--queue-timeout=MS` | `60000` | a queued request waiting longer gets 504 `queue-timeout` |
|
|
44
|
+
|
|
45
|
+
## Template fidelity
|
|
46
|
+
|
|
47
|
+
dario replays Claude Code's wire shape from a template it captures from your installed `claude` binary, falling back to a baked snapshot. These two make the unsafe states require intent ([`#77`](https://github.com/askalf/dario/issues/77)).
|
|
48
|
+
|
|
49
|
+
| Variable | Flag | Default | Notes |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `DARIO_NO_LIVE_CAPTURE` | `--no-live-capture` | off | Never spawn the installed CC; use the baked snapshot only. For air-gapped and reproducible-build runs. |
|
|
52
|
+
| `DARIO_STRICT_TEMPLATE` | `--strict-template` | off | Refuse to start if the live capture never succeeded or drifts from the installed CC version. |
|
|
53
|
+
|
|
54
|
+
## Client shape
|
|
55
|
+
|
|
56
|
+
Off by default, each one a deliberate divergence from what real CC sends.
|
|
57
|
+
|
|
58
|
+
| Variable | Flag | Notes |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `DARIO_STEALTH` | `--stealth` | Behavioural-stealth preset. Per-knob pacing vars below still win, so you can flip this on and tune one axis. |
|
|
61
|
+
| `DARIO_HONOR_CLIENT_THINKING` | `--honor-client-thinking` | Pass a client's own `thinking` block through unchanged. |
|
|
62
|
+
| `DARIO_PRESERVE_OUTPUT_FORMAT` | `--preserve-output-format` | Carry a client's `output_config.format` schema through, for structured-output SDKs. |
|
|
63
|
+
| `DARIO_PRESERVE_ORCHESTRATION_TAGS` | `--preserve-orchestration-tags` | Keep orchestration tags instead of stripping them ([`#78`](https://github.com/askalf/dario/issues/78)). |
|
|
64
|
+
| `DARIO_EFFORT` | `--effort=` | Forces a reasoning-effort level. Can flip requests to overage billing — watch `-v` logs for representative-claim changes ([`#87`](https://github.com/askalf/dario/issues/87)). |
|
|
65
|
+
| `DARIO_MAX_TOKENS` | `--max-tokens=` | Anthropic enforces the per-model ceiling server-side, so too-high values return a clean 400 ([`#88`](https://github.com/askalf/dario/issues/88)). |
|
|
66
|
+
|
|
67
|
+
## Pacing
|
|
68
|
+
|
|
69
|
+
Only meaningful with stealth, and all default to 0 (off) except the cap. See [`wire-fidelity.md`](./wire-fidelity.md).
|
|
70
|
+
|
|
71
|
+
| Variable | Flag | Default |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `DARIO_THINK_TIME_BASE_MS` | `--think-time-base=MS` | `0` |
|
|
74
|
+
| `DARIO_THINK_TIME_PER_TOKEN_MS` | `--think-time-per-token=MS` | `0` |
|
|
75
|
+
| `DARIO_THINK_TIME_JITTER_MS` | `--think-time-jitter=MS` | `0` |
|
|
76
|
+
| `DARIO_THINK_TIME_MAX_MS` | `--think-time-max=MS` | `30000` |
|
|
77
|
+
| `DARIO_SESSION_START_MIN_MS` | `--session-start-min=MS` | `0` |
|
|
78
|
+
| `DARIO_SESSION_START_JITTER_MS` | `--session-start-jitter=MS` | `0` |
|
|
79
|
+
|
|
80
|
+
## Pool and routing
|
|
81
|
+
|
|
82
|
+
The pool-strategy, fallback-model, alias and upstream-proxy vars live in [`commands.md`](./commands.md).
|
|
83
|
+
|
|
84
|
+
| Variable | Flag | Notes |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `DARIO_SUSPENDED_MODELS` | — | Filters families from `/v1/models` so it never advertises a model that 404s. |
|
|
87
|
+
| `DARIO_SKIP_FIELDS` | `--skip-fields=CSV` | Drop named fields from the outbound body. |
|
|
88
|
+
|
|
89
|
+
## Networking and caches
|
|
90
|
+
|
|
91
|
+
| Variable | Flag | Default | Notes |
|
|
92
|
+
|---|---|---|---|
|
|
93
|
+
| `DARIO_DNS_RESULT_ORDER` | — | `ipv4first` | `verbatim` uses the resolver's own order. IPv4-first because an IPv6 answer is not universally routable. |
|
|
94
|
+
| `DARIO_MODEL_CATALOG_TTL_MS` | — | `3600000` (1h) | How long `/v1/models` caches Anthropic's live catalog. Model launches are rare; shorten it if you are chasing one. |
|
|
95
|
+
| `DARIO_USAGE_PORT` | `--port=N` | `3456` | Which proxy the `dario usage` subcommand queries. |
|
|
96
|
+
|
|
97
|
+
## Escape hatches
|
|
98
|
+
|
|
99
|
+
Reversible switches for behaviour that is normally correct. You should not need them; they exist so a bad guess on our side is not fatal.
|
|
100
|
+
|
|
101
|
+
| Variable | Values | Notes |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `DARIO_CCH` | `random` | Stops replaying a calibrated `cch` token in the billing tag and randomises it per request instead. Only affects CC versions we hold a seed for — current CC sends no `cch` at all, so dario omits it and this does nothing. |
|
|
104
|
+
|
|
105
|
+
## Not part of the supported surface
|
|
106
|
+
|
|
107
|
+
`DARIO_LIVE_TEMPLATE_CACHE` and `DARIO_TEST_URL` exist for the test suite. They are not configuration, are not covered by semver, and can change or vanish in a patch release.
|
|
108
|
+
|
|
109
|
+
If an unsupported var is the only way to do something you need, that is a missing flag. Open an issue.
|