@askalf/dario 4.7.2 → 4.8.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 +0 -1
- package/dist/cc-template.d.ts +1 -0
- package/dist/cc-template.js +34 -13
- package/dist/cli.d.ts +7 -0
- package/dist/cli.js +39 -1
- package/dist/proxy.d.ts +12 -0
- package/dist/proxy.js +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -513,7 +513,6 @@ Ordered by relevance to a dario reader — projects that route through dario fir
|
|
|
513
513
|
| [hands](https://github.com/askalf/hands) | Cross-platform computer-use agent — your LLM on your mouse, keyboard, and screen. Windows + macOS + Linux. Routes through dario or any Anthropic-compat. |
|
|
514
514
|
| [deepdive](https://github.com/askalf/deepdive) | Local research agent. One command, cited answer. Plan → search → headless fetch → extract → synthesize. Every LLM call through your own router. |
|
|
515
515
|
| [claude-sync](https://github.com/askalf/claude-sync) | Sync Claude Code sessions across machines. Pack a CC session into a portable `.ccsync` file, ship it via Dropbox / iCloud / USB, unpack on the other side. |
|
|
516
|
-
| [claude-bridge](https://github.com/askalf/claude-bridge) | Bridge Claude Code sessions to Discord. Stay in sync with your CC instances from your phone. |
|
|
517
516
|
| [browser-bridge](https://github.com/askalf/browser-bridge) | Stealth headless Chromium in a container, CDP on 9222. Connect from Playwright, Puppeteer, MCP browser tools, any agent that wants a remote browser. |
|
|
518
517
|
| [install-kit](https://github.com/askalf/install-kit) | curl-pipe-bash template for self-hosted Docker apps — banner, prereq probes, `.env` scaffolding with crypto-rand secrets, healthcheck wait loop. |
|
|
519
518
|
| [pgflex](https://github.com/askalf/pgflex) | One Postgres API, two modes — real PostgreSQL for production, PGlite (in-process WASM) for standalone / dev. Same SQL, drop the server when you don't need it. |
|
package/dist/cc-template.d.ts
CHANGED
|
@@ -317,6 +317,7 @@ export declare function buildCCRequest(clientBody: Record<string, unknown>, bill
|
|
|
317
317
|
effort?: EffortValue;
|
|
318
318
|
maxTokens?: number | 'client';
|
|
319
319
|
systemPrompt?: string;
|
|
320
|
+
skipFields?: ReadonlySet<string>;
|
|
320
321
|
}): {
|
|
321
322
|
body: Record<string, unknown>;
|
|
322
323
|
toolMap: Map<string, ToolMapping>;
|
package/dist/cc-template.js
CHANGED
|
@@ -1278,24 +1278,45 @@ export function buildCCRequest(clientBody, billingTag, cacheControl, identity, o
|
|
|
1278
1278
|
ccRequest.max_tokens = resolveMaxTokens(opts.maxTokens, clientBody);
|
|
1279
1279
|
// Model-specific fields — order: thinking, context_management, output_config
|
|
1280
1280
|
//
|
|
1281
|
-
//
|
|
1282
|
-
//
|
|
1283
|
-
//
|
|
1284
|
-
//
|
|
1285
|
-
//
|
|
1286
|
-
//
|
|
1287
|
-
//
|
|
1281
|
+
// Layered guard:
|
|
1282
|
+
//
|
|
1283
|
+
// 1. Haiku skips all three by construction (existing behavior).
|
|
1284
|
+
//
|
|
1285
|
+
// 2. `thinking: {type:"adaptive"}` is a 4.6-generation feature; older
|
|
1286
|
+
// Opus/Sonnet 4-5 models 400 it (`"adaptive thinking is not supported
|
|
1287
|
+
// on this model"`). `context_management.edits[clear_thinking_*]` is
|
|
1288
|
+
// tied to thinking — sending it without an enabled thinking field
|
|
1289
|
+
// 400s too (`"clear_thinking_* strategy requires thinking to be
|
|
1290
|
+
// enabled or adaptive"`). Both are gated on `supportsAdaptiveThinking`;
|
|
1291
|
+
// either both ship or neither does.
|
|
1292
|
+
//
|
|
1293
|
+
// 3. Each remaining injection is also opt-out via `opts.skipFields`.
|
|
1294
|
+
// Non-CC clients (e.g. apps calling dario via the Anthropic SDK)
|
|
1295
|
+
// sometimes hit model endpoints that still 400 on these fields with
|
|
1296
|
+
// "Extra inputs are not permitted" even when supportsAdaptiveThinking
|
|
1297
|
+
// is true. Operators set `--skip-fields=context_management,…` (or
|
|
1298
|
+
// DARIO_SKIP_FIELDS=…) to suppress the offending field while keeping
|
|
1299
|
+
// all other CC fingerprinting (headers, beta flags, metadata) intact
|
|
1300
|
+
// — Max billing pool routing is unchanged.
|
|
1288
1301
|
//
|
|
1289
1302
|
// `output_config.effort` is independent of thinking and ships for all
|
|
1290
|
-
// non-Haiku models. Default `'high'`
|
|
1291
|
-
// `--effort` flag overrides; `'client'`
|
|
1292
|
-
// client sent (or falls back to `'high'` if
|
|
1303
|
+
// non-Haiku models that aren't opted out via skipFields. Default `'high'`
|
|
1304
|
+
// matches CC 2.1.116's wire value; `--effort` flag overrides; `'client'`
|
|
1305
|
+
// passes through whatever the client sent (or falls back to `'high'` if
|
|
1306
|
+
// absent). See dario#87.
|
|
1293
1307
|
if (!isHaiku) {
|
|
1308
|
+
const skip = opts.skipFields;
|
|
1294
1309
|
if (supportsAdaptiveThinking(model)) {
|
|
1295
|
-
|
|
1296
|
-
|
|
1310
|
+
if (!skip || !skip.has('thinking')) {
|
|
1311
|
+
ccRequest.thinking = { type: 'adaptive' };
|
|
1312
|
+
}
|
|
1313
|
+
if (!skip || !skip.has('context_management')) {
|
|
1314
|
+
ccRequest.context_management = { edits: [{ type: 'clear_thinking_20251015', keep: 'all' }] };
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
if (!skip || !skip.has('output_config')) {
|
|
1318
|
+
ccRequest.output_config = { effort: resolveEffort(opts.effort, clientBody) };
|
|
1297
1319
|
}
|
|
1298
|
-
ccRequest.output_config = { effort: resolveEffort(opts.effort, clientBody) };
|
|
1299
1320
|
}
|
|
1300
1321
|
ccRequest.stream = stream;
|
|
1301
1322
|
// Replay the captured top-level key order. The hardcoded build order above
|
package/dist/cli.d.ts
CHANGED
|
@@ -41,6 +41,13 @@ export declare function resolveSystemPromptFlag(args: string[], envVar: string |
|
|
|
41
41
|
* - empty entries / whitespace-only entries / duplicates are dropped.
|
|
42
42
|
*/
|
|
43
43
|
export declare function parsePassthroughBetasFlag(args: string[], envVar: string | undefined): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Parse `--skip-fields=<csv>` (or DARIO_SKIP_FIELDS env) into a deduped
|
|
46
|
+
* trimmed list of CC body field names. Unrecognized values are passed
|
|
47
|
+
* through; proxy.ts validates against the allowed set at startup and
|
|
48
|
+
* warns on each typo. Same edge-case handling as parsePassthroughBetasFlag.
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseSkipFieldsFlag(args: string[], envVar: string | undefined): string[];
|
|
44
51
|
/**
|
|
45
52
|
* Parse `--max-tokens=<N|client>` + `DARIO_MAX_TOKENS` env (dario#88).
|
|
46
53
|
* Numeric values pin; `client` (case-insensitive) = passthrough client's
|
package/dist/cli.js
CHANGED
|
@@ -513,6 +513,11 @@ async function proxy() {
|
|
|
513
513
|
?? overageNotifyFromEnv
|
|
514
514
|
?? fileCfg.overageGuard?.notifyOs
|
|
515
515
|
?? true;
|
|
516
|
+
// --skip-fields=name1,name2 — CC body fields to omit from outbound
|
|
517
|
+
// requests. Allowed values: thinking, context_management, output_config.
|
|
518
|
+
// Falls back to DARIO_SKIP_FIELDS env var. See ProxyOptions.skipFields
|
|
519
|
+
// for rationale.
|
|
520
|
+
const skipFields = parseSkipFieldsFlag(args, process.env['DARIO_SKIP_FIELDS']);
|
|
516
521
|
// Non-loopback bind without DARIO_API_KEY turns dario into an open
|
|
517
522
|
// OAuth-subscription relay for anyone on the reachable network. Refuse
|
|
518
523
|
// to start rather than rely on the operator to read the startup banner.
|
|
@@ -532,7 +537,7 @@ async function proxy() {
|
|
|
532
537
|
console.error(`[dario] Override (not recommended): pass --unsafe-no-auth if you have out-of-band network controls and accept the risk.`);
|
|
533
538
|
process.exit(1);
|
|
534
539
|
}
|
|
535
|
-
await startProxy({ port, host, verbose, verboseBodies, model, passthrough, preserveTools, hybridTools, mergeTools, noAutoDetect, strictTls, pacingMinMs, pacingJitterMs, thinkTimeBaseMs, thinkTimePerTokenMs, thinkTimeJitterMs, thinkTimeMaxMs, sessionStartMinMs, sessionStartJitterMs, stealth, drainOnClose, sessionIdleRotateMs, sessionRotateJitterMs, sessionMaxAgeMs, sessionPerClient, preserveOrchestrationTags, noLiveCapture, strictTemplate, maxConcurrent, maxQueued, queueTimeoutMs, effort, maxTokens, logFile, passthroughBetas, systemPrompt, overageGuardEnabled, overageGuardBehavior, overageGuardCooldownMs, overageGuardNotifyOs });
|
|
540
|
+
await startProxy({ port, host, verbose, verboseBodies, model, passthrough, preserveTools, hybridTools, mergeTools, noAutoDetect, strictTls, pacingMinMs, pacingJitterMs, thinkTimeBaseMs, thinkTimePerTokenMs, thinkTimeJitterMs, thinkTimeMaxMs, sessionStartMinMs, sessionStartJitterMs, stealth, drainOnClose, sessionIdleRotateMs, sessionRotateJitterMs, sessionMaxAgeMs, sessionPerClient, preserveOrchestrationTags, noLiveCapture, strictTemplate, maxConcurrent, maxQueued, queueTimeoutMs, effort, maxTokens, logFile, passthroughBetas, skipFields, systemPrompt, overageGuardEnabled, overageGuardBehavior, overageGuardCooldownMs, overageGuardNotifyOs });
|
|
536
541
|
}
|
|
537
542
|
/**
|
|
538
543
|
* Parse `--system-prompt=<verbatim|partial|aggressive|filepath>` (or the
|
|
@@ -604,6 +609,28 @@ export function parsePassthroughBetasFlag(args, envVar) {
|
|
|
604
609
|
}
|
|
605
610
|
return out;
|
|
606
611
|
}
|
|
612
|
+
/**
|
|
613
|
+
* Parse `--skip-fields=<csv>` (or DARIO_SKIP_FIELDS env) into a deduped
|
|
614
|
+
* trimmed list of CC body field names. Unrecognized values are passed
|
|
615
|
+
* through; proxy.ts validates against the allowed set at startup and
|
|
616
|
+
* warns on each typo. Same edge-case handling as parsePassthroughBetasFlag.
|
|
617
|
+
*/
|
|
618
|
+
export function parseSkipFieldsFlag(args, envVar) {
|
|
619
|
+
const eqArg = args.find((a) => a.startsWith('--skip-fields='));
|
|
620
|
+
const raw = eqArg !== undefined ? eqArg.slice('--skip-fields='.length) : envVar;
|
|
621
|
+
if (!raw)
|
|
622
|
+
return [];
|
|
623
|
+
const seen = new Set();
|
|
624
|
+
const out = [];
|
|
625
|
+
for (const piece of raw.split(',')) {
|
|
626
|
+
const trimmed = piece.trim();
|
|
627
|
+
if (trimmed.length > 0 && !seen.has(trimmed)) {
|
|
628
|
+
seen.add(trimmed);
|
|
629
|
+
out.push(trimmed);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return out;
|
|
633
|
+
}
|
|
607
634
|
/**
|
|
608
635
|
* Parse `--log-file=<path>` or `--log-file <path>`. Returns the path
|
|
609
636
|
* string when present, undefined otherwise. An empty path (e.g.
|
|
@@ -1346,6 +1373,17 @@ async function help() {
|
|
|
1346
1373
|
on your account but isn't in the captured
|
|
1347
1374
|
template. Env: DARIO_PASSTHROUGH_BETAS.
|
|
1348
1375
|
|
|
1376
|
+
--skip-fields=CSV CC body fields to NOT inject into outbound
|
|
1377
|
+
requests. Allowed: thinking,
|
|
1378
|
+
context_management, output_config. Headers
|
|
1379
|
+
and metadata stay intact (Max billing
|
|
1380
|
+
unchanged). Use when an upstream model 400s
|
|
1381
|
+
"Extra inputs are not permitted" on one of
|
|
1382
|
+
these fields — typically a non-CC SDK
|
|
1383
|
+
client routed through dario to a model
|
|
1384
|
+
that rejects the field despite the beta
|
|
1385
|
+
header. Env: DARIO_SKIP_FIELDS.
|
|
1386
|
+
|
|
1349
1387
|
--upstream-proxy=URL / --via=URL
|
|
1350
1388
|
Route all of dario's outbound fetch
|
|
1351
1389
|
calls (api.anthropic.com, OpenAI-compat
|
package/dist/proxy.d.ts
CHANGED
|
@@ -143,6 +143,18 @@ interface ProxyOptions {
|
|
|
143
143
|
* pinned flags has been rejected and is therefore being dropped.
|
|
144
144
|
*/
|
|
145
145
|
passthroughBetas?: string[];
|
|
146
|
+
/**
|
|
147
|
+
* CC body fields to NOT inject into outbound requests. Allowed values:
|
|
148
|
+
* `thinking`, `context_management`, `output_config`. Sourced from
|
|
149
|
+
* `--skip-fields=name1,name2` or `DARIO_SKIP_FIELDS`. Used when an
|
|
150
|
+
* upstream model 400s on a CC-shaped body field with "Extra inputs are
|
|
151
|
+
* not permitted" (observed 2026-05-18 with a non-CC SDK client routed
|
|
152
|
+
* through dario to claude-sonnet-4-6 — `context_management` rejected
|
|
153
|
+
* despite the beta header). Skipping a field leaves all other CC
|
|
154
|
+
* fingerprinting intact (headers, beta flags, metadata, OAuth identity),
|
|
155
|
+
* so Max billing pool routing is unchanged.
|
|
156
|
+
*/
|
|
157
|
+
skipFields?: string[];
|
|
146
158
|
/**
|
|
147
159
|
* System-prompt mode for the Claude backend. Empirically validated as
|
|
148
160
|
* unfingerprinted by the billing classifier in docs/research/system-prompt-classifier-study.md.
|
package/dist/proxy.js
CHANGED
|
@@ -495,6 +495,27 @@ export async function startProxy(opts = {}) {
|
|
|
495
495
|
if (passthroughBetas.size > 0) {
|
|
496
496
|
console.log(` Beta passthrough: ${[...passthroughBetas].sort().join(', ')} (always forwarded; per-account rejection cache still applies)`);
|
|
497
497
|
}
|
|
498
|
+
// CC body fields to suppress. Allowed values: thinking, context_management,
|
|
499
|
+
// output_config. Anything else is silently ignored after a warn (so a typo
|
|
500
|
+
// doesn't quietly disable nothing). See ProxyOptions.skipFields.
|
|
501
|
+
const ALLOWED_SKIP_FIELDS = new Set(['thinking', 'context_management', 'output_config']);
|
|
502
|
+
const skipFields = new Set();
|
|
503
|
+
for (const raw of [
|
|
504
|
+
...(opts.skipFields ?? []),
|
|
505
|
+
...((process.env.DARIO_SKIP_FIELDS ?? '').split(',')),
|
|
506
|
+
]) {
|
|
507
|
+
const trimmed = raw.trim();
|
|
508
|
+
if (trimmed.length === 0)
|
|
509
|
+
continue;
|
|
510
|
+
if (!ALLOWED_SKIP_FIELDS.has(trimmed)) {
|
|
511
|
+
console.warn(`[dario] WARNING: --skip-fields value ${JSON.stringify(trimmed)} is not recognized; ignoring. Allowed: ${[...ALLOWED_SKIP_FIELDS].join(', ')}.`);
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
skipFields.add(trimmed);
|
|
515
|
+
}
|
|
516
|
+
if (skipFields.size > 0) {
|
|
517
|
+
console.log(` Skip CC body fields: ${[...skipFields].sort().join(', ')} (omitted from outbound non-haiku requests; headers and metadata unchanged)`);
|
|
518
|
+
}
|
|
498
519
|
// Tool-routing mode mutex. preserve / hybrid / merge each shape the
|
|
499
520
|
// outbound `tools` array differently; combining two would mean two
|
|
500
521
|
// different bodies. Refuse to start with a clear error rather than
|
|
@@ -1369,6 +1390,7 @@ export async function startProxy(opts = {}) {
|
|
|
1369
1390
|
effort: opts.effort,
|
|
1370
1391
|
maxTokens: opts.maxTokens,
|
|
1371
1392
|
systemPrompt: opts.systemPrompt,
|
|
1393
|
+
skipFields,
|
|
1372
1394
|
});
|
|
1373
1395
|
detectedClientForLog = detectedClient;
|
|
1374
1396
|
preserveToolsEffective = Boolean(opts.preserveTools)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Use your Claude Pro/Max subscription in any tool — Cursor, Cline, Aider, the Agent SDK, your scripts — at subscription pricing, not per-token API bills. One local Anthropic + OpenAI-compatible endpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|