@askalf/dario 3.30.7 → 3.30.8
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/cli.d.ts +7 -0
- package/dist/cli.js +44 -2
- package/dist/proxy.d.ts +15 -0
- package/dist/proxy.js +27 -1
- package/package.json +2 -2
package/dist/cli.d.ts
CHANGED
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
* dario refresh — Force token refresh
|
|
10
10
|
* dario logout — Remove saved credentials
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* Parse a boolean env var. Accepts "1", "true", "yes", "on" (case-insensitive)
|
|
14
|
+
* as truthy; everything else (including unset) is undefined/false. Exported
|
|
15
|
+
* for tests. Used by dario#77 DARIO_STRICT_TEMPLATE / DARIO_NO_LIVE_CAPTURE
|
|
16
|
+
* and any future boolean env mirror.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseBooleanEnv(value: string | undefined): boolean | undefined;
|
|
12
19
|
/**
|
|
13
20
|
* Parse --preserve-orchestration-tags (bare or =value) + env mirror.
|
|
14
21
|
* Exported for tests.
|
package/dist/cli.js
CHANGED
|
@@ -236,6 +236,20 @@ async function proxy() {
|
|
|
236
236
|
// DARIO_PRESERVE_ORCHESTRATION_TAGS=* (preserve all)
|
|
237
237
|
// DARIO_PRESERVE_ORCHESTRATION_TAGS=thinking,env (preserve listed)
|
|
238
238
|
const preserveOrchestrationTags = resolvePreserveOrchestrationTags(args, process.env['DARIO_PRESERVE_ORCHESTRATION_TAGS']);
|
|
239
|
+
// --no-live-capture / --strict-template — template fail-closed knobs.
|
|
240
|
+
// Convergent push-back from Grok + GPT in reviews/: drift resilience
|
|
241
|
+
// should be opt-in-verifiable, not silently best-effort. dario#77.
|
|
242
|
+
// --no-live-capture → skip the background CC capture entirely, use
|
|
243
|
+
// the bundled snapshot; for air-gapped / CI.
|
|
244
|
+
// --strict-template → refuse to start if the loaded template is
|
|
245
|
+
// bundled (no live capture) or drifted from
|
|
246
|
+
// the installed CC; same shape as --strict-tls.
|
|
247
|
+
const noLiveCapture = args.includes('--no-live-capture')
|
|
248
|
+
|| parseBooleanEnv(process.env['DARIO_NO_LIVE_CAPTURE'])
|
|
249
|
+
|| undefined;
|
|
250
|
+
const strictTemplate = args.includes('--strict-template')
|
|
251
|
+
|| parseBooleanEnv(process.env['DARIO_STRICT_TEMPLATE'])
|
|
252
|
+
|| undefined;
|
|
239
253
|
// Non-loopback bind without DARIO_API_KEY turns dario into an open
|
|
240
254
|
// OAuth-subscription relay for anyone on the reachable network. Refuse
|
|
241
255
|
// to start rather than rely on the operator to read the startup banner.
|
|
@@ -255,7 +269,21 @@ async function proxy() {
|
|
|
255
269
|
console.error(`[dario] Override (not recommended): pass --unsafe-no-auth if you have out-of-band network controls and accept the risk.`);
|
|
256
270
|
process.exit(1);
|
|
257
271
|
}
|
|
258
|
-
await startProxy({ port, host, verbose, verboseBodies, model, passthrough, preserveTools, hybridTools, noAutoDetect, strictTls, pacingMinMs, pacingJitterMs, drainOnClose, sessionIdleRotateMs, sessionRotateJitterMs, sessionMaxAgeMs, sessionPerClient, preserveOrchestrationTags });
|
|
272
|
+
await startProxy({ port, host, verbose, verboseBodies, model, passthrough, preserveTools, hybridTools, noAutoDetect, strictTls, pacingMinMs, pacingJitterMs, drainOnClose, sessionIdleRotateMs, sessionRotateJitterMs, sessionMaxAgeMs, sessionPerClient, preserveOrchestrationTags, noLiveCapture, strictTemplate });
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Parse a boolean env var. Accepts "1", "true", "yes", "on" (case-insensitive)
|
|
276
|
+
* as truthy; everything else (including unset) is undefined/false. Exported
|
|
277
|
+
* for tests. Used by dario#77 DARIO_STRICT_TEMPLATE / DARIO_NO_LIVE_CAPTURE
|
|
278
|
+
* and any future boolean env mirror.
|
|
279
|
+
*/
|
|
280
|
+
export function parseBooleanEnv(value) {
|
|
281
|
+
if (value === undefined)
|
|
282
|
+
return undefined;
|
|
283
|
+
const normalized = value.trim().toLowerCase();
|
|
284
|
+
if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on')
|
|
285
|
+
return true;
|
|
286
|
+
return undefined;
|
|
259
287
|
}
|
|
260
288
|
/**
|
|
261
289
|
* Parse --preserve-orchestration-tags (bare or =value) + env mirror.
|
|
@@ -605,7 +633,21 @@ async function help() {
|
|
|
605
633
|
stripped. Default: strip every tag in
|
|
606
634
|
ORCHESTRATION_TAG_NAMES. Env mirror:
|
|
607
635
|
DARIO_PRESERVE_ORCHESTRATION_TAGS=*
|
|
608
|
-
or =tag1,tag2. (v3.
|
|
636
|
+
or =tag1,tag2. (v3.30.7, dario#78)
|
|
637
|
+
--no-live-capture Skip the background live-fingerprint
|
|
638
|
+
refresh entirely. dario uses the bundled
|
|
639
|
+
snapshot and will NOT spawn the installed
|
|
640
|
+
Claude Code binary. For air-gapped /
|
|
641
|
+
reproducible-build / CI-harness runs.
|
|
642
|
+
Env: DARIO_NO_LIVE_CAPTURE=1.
|
|
643
|
+
(v3.30.8, dario#77)
|
|
644
|
+
--strict-template Refuse to start if the loaded template
|
|
645
|
+
is the bundled snapshot (no live capture
|
|
646
|
+
ever succeeded) or drifts from the
|
|
647
|
+
installed CC version. Same philosophy
|
|
648
|
+
as --strict-tls: make the unsafe state
|
|
649
|
+
require intent. Env: DARIO_STRICT_TEMPLATE=1.
|
|
650
|
+
(v3.30.8, dario#77)
|
|
609
651
|
--port=PORT Port to listen on (default: 3456)
|
|
610
652
|
--host=ADDRESS Address to bind to (default: 127.0.0.1)
|
|
611
653
|
Use 0.0.0.0 for LAN; see README for DARIO_API_KEY
|
package/dist/proxy.d.ts
CHANGED
|
@@ -50,6 +50,21 @@ interface ProxyOptions {
|
|
|
50
50
|
* Set(['thinking','env']) = strip everything except those two. dario#78.
|
|
51
51
|
*/
|
|
52
52
|
preserveOrchestrationTags?: Set<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Skip the background live-fingerprint refresh entirely. Use the bundled
|
|
55
|
+
* snapshot even when a live capture would have been possible. For
|
|
56
|
+
* air-gapped / reproducible-build / CI-harness operators who want no
|
|
57
|
+
* subprocess capture of the installed CC binary. dario#77.
|
|
58
|
+
*/
|
|
59
|
+
noLiveCapture?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Fail-closed mode for the template. If the loaded template is the
|
|
62
|
+
* bundled snapshot (live capture has never been run or failed), or if
|
|
63
|
+
* it's a live cache that drifts from the installed CC, refuse to start
|
|
64
|
+
* rather than silently serve the stale shape. Same philosophy as
|
|
65
|
+
* --strict-tls. dario#77.
|
|
66
|
+
*/
|
|
67
|
+
strictTemplate?: boolean;
|
|
53
68
|
}
|
|
54
69
|
export declare function sanitizeError(err: unknown): string;
|
|
55
70
|
/**
|
package/dist/proxy.js
CHANGED
|
@@ -1640,6 +1640,23 @@ export async function startProxy(opts = {}) {
|
|
|
1640
1640
|
if (drift.drifted) {
|
|
1641
1641
|
console.log(`[dario] ⚠ template drift: ${drift.message}`);
|
|
1642
1642
|
}
|
|
1643
|
+
// Strict-template fail-closed mode. Template must be from a live capture
|
|
1644
|
+
// (not the bundled snapshot) and must not have drifted from the installed
|
|
1645
|
+
// CC. Operator opts in via --strict-template / DARIO_STRICT_TEMPLATE=1.
|
|
1646
|
+
// Same philosophy as --strict-tls: make the unsafe state require intent.
|
|
1647
|
+
// dario#77.
|
|
1648
|
+
if (opts.strictTemplate) {
|
|
1649
|
+
if (CC_TEMPLATE._source === 'bundled') {
|
|
1650
|
+
console.error(`[dario] Refusing to start proxy in --strict-template mode: template source is 'bundled' (no live capture available).`);
|
|
1651
|
+
console.error(`[dario] Fix: run \`claude --print hello\` once so dario can capture the live template, then retry. Or drop --strict-template if the bundled fingerprint is acceptable for this run.`);
|
|
1652
|
+
process.exit(1);
|
|
1653
|
+
}
|
|
1654
|
+
if (drift.drifted) {
|
|
1655
|
+
console.error(`[dario] Refusing to start proxy in --strict-template mode: template drift detected (${drift.message}).`);
|
|
1656
|
+
console.error(`[dario] Fix: rm ~/.dario/cc-template.live.json and retry (the next capture will be against your current CC), or drop --strict-template if the drift is acceptable.`);
|
|
1657
|
+
process.exit(1);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1643
1660
|
// Compat check: is the installed CC inside the range this dario
|
|
1644
1661
|
// release has been tested against? Only log when non-OK so the happy
|
|
1645
1662
|
// path stays quiet. `unknown` (no CC on PATH) is also quiet — bundled
|
|
@@ -1661,7 +1678,16 @@ export async function startProxy(opts = {}) {
|
|
|
1661
1678
|
// user's own CC binary request shape and updates ~/.dario/cc-template.live.json
|
|
1662
1679
|
// for the next startup. No-op if CC isn't installed or the cache is fresh.
|
|
1663
1680
|
// Never blocks proxy startup; never throws.
|
|
1664
|
-
|
|
1681
|
+
//
|
|
1682
|
+
// Skipped entirely under --no-live-capture / DARIO_NO_LIVE_CAPTURE=1 —
|
|
1683
|
+
// the operator has opted into a bundled-only shape (air-gapped runs,
|
|
1684
|
+
// reproducible-build CI, deliberate pinning). dario#77.
|
|
1685
|
+
if (!opts.noLiveCapture) {
|
|
1686
|
+
void import('./live-fingerprint.js').then(({ refreshLiveFingerprintAsync }) => refreshLiveFingerprintAsync({ silent: false, force: drift.drifted }).catch(() => { }));
|
|
1687
|
+
}
|
|
1688
|
+
else {
|
|
1689
|
+
console.log('[dario] --no-live-capture: background live fingerprint refresh skipped; using bundled template.');
|
|
1690
|
+
}
|
|
1665
1691
|
server.listen(port, host, () => {
|
|
1666
1692
|
const modeLine = passthrough
|
|
1667
1693
|
? 'Mode: passthrough (OAuth swap only, no injection)'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "3.30.
|
|
3
|
+
"version": "3.30.8",
|
|
4
4
|
"description": "A local LLM router. One endpoint, every provider — Claude subscriptions, OpenAI, OpenRouter, Groq, local LiteLLM, any OpenAI-compat endpoint — your tools don't need to change.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "tsc && cp src/cc-template-data.json dist/ && node -e \"require('fs').mkdirSync('dist/shim',{recursive:true})\" && cp src/shim/runtime.cjs dist/shim/",
|
|
24
|
-
"test": "node test/issue-29-tool-translation.mjs && node test/hybrid-tools.mjs && node test/tool-schema-contract.mjs && node test/scrub-paths.mjs && node test/provider-prefix.mjs && node test/analytics-recording.mjs && node test/analytics-billing-bucket.mjs && node test/failover-429.mjs && node test/pool-sticky.mjs && node test/live-fingerprint.mjs && node test/shim-runtime.mjs && node test/shim-e2e.mjs && node test/proxy-header-order.mjs && node test/proxy-body-order.mjs && node test/runtime-fingerprint.mjs && node test/pacing.mjs && node test/stream-drain.mjs && node test/subagent.mjs && node test/mcp-protocol.mjs && node test/mcp-tools.mjs && node test/mcp-e2e.mjs && node test/session-rotation.mjs && node test/drift-detection.mjs && node test/cc-authorize-probe-classifier.mjs && node test/compat-range.mjs && node test/doctor-formatter.mjs && node test/atomic-write.mjs && node test/account-refresh-singleflight.mjs && node test/streaming-edge-cases.mjs && node test/client-detection.mjs && node test/manual-oauth-flow.mjs && node test/scrub-template.mjs && node test/sanitize-messages.mjs && node test/platform-tools.mjs",
|
|
24
|
+
"test": "node test/issue-29-tool-translation.mjs && node test/hybrid-tools.mjs && node test/tool-schema-contract.mjs && node test/scrub-paths.mjs && node test/provider-prefix.mjs && node test/analytics-recording.mjs && node test/analytics-billing-bucket.mjs && node test/failover-429.mjs && node test/pool-sticky.mjs && node test/live-fingerprint.mjs && node test/shim-runtime.mjs && node test/shim-e2e.mjs && node test/proxy-header-order.mjs && node test/proxy-body-order.mjs && node test/runtime-fingerprint.mjs && node test/pacing.mjs && node test/stream-drain.mjs && node test/subagent.mjs && node test/mcp-protocol.mjs && node test/mcp-tools.mjs && node test/mcp-e2e.mjs && node test/session-rotation.mjs && node test/drift-detection.mjs && node test/cc-authorize-probe-classifier.mjs && node test/compat-range.mjs && node test/doctor-formatter.mjs && node test/atomic-write.mjs && node test/account-refresh-singleflight.mjs && node test/streaming-edge-cases.mjs && node test/client-detection.mjs && node test/manual-oauth-flow.mjs && node test/scrub-template.mjs && node test/sanitize-messages.mjs && node test/platform-tools.mjs && node test/strict-template-flags.mjs",
|
|
25
25
|
"audit": "npm audit --production --audit-level=high",
|
|
26
26
|
"prepublishOnly": "npm run build",
|
|
27
27
|
"start": "node dist/cli.js",
|