@askalf/dario 4.8.3 → 4.8.5
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 +21 -14
- package/dist/accounts.d.ts +5 -0
- package/dist/accounts.js +1 -1
- package/dist/doctor.d.ts +35 -0
- package/dist/doctor.js +66 -0
- package/dist/live-fingerprint.d.ts +1 -1
- package/dist/live-fingerprint.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
**Anthropic ships restrictions to subscribers through wire-shape changes that don't appear in any user-facing changelog. dario makes them visible.** A three-class drift watcher catches each silent change — new CC binaries, in-version remote-config changes, and classifier-rule shifts — auto-opens a fix PR with a unified diff inline, and the public record names what shifted and when. The proxy keeps your subscription doing what it did yesterday until you choose otherwise. Receipts below.
|
|
21
|
-
|
|
22
20
|
You're already paying $20, $100, or $200 a month for Claude. Then Cursor wants an API key. Aider wants an API key. Cline, Continue, Zed, your scripts — every one of them bills you **again**, per token, while the subscription you already bought sits idle in Claude Code.
|
|
23
21
|
|
|
24
22
|
**dario is one local endpoint that routes all of them through the Claude subscription you already pay for.** Point any Anthropic- or OpenAI-compatible tool at `http://localhost:3456` and you're done. No per-tool config, no second bill.
|
|
@@ -281,19 +279,9 @@ Why "halt at hit #1" is the right default: subscribers should never see a single
|
|
|
281
279
|
|
|
282
280
|
---
|
|
283
281
|
|
|
284
|
-
##
|
|
285
|
-
|
|
286
|
-
Four LLMs reviewed the codebase cold, same prompt ([`reviews/PROMPT.md`](./reviews/PROMPT.md)), each signed a verdict:
|
|
287
|
-
|
|
288
|
-
> "Not vibe-coded; it reads like production-grade infrastructure that happens to be open-source." — **Grok 4** ([full](./reviews/grok-4-2026-04-21.md))
|
|
289
|
-
>
|
|
290
|
-
> "The implementation isn't just a simple header swap; it is a sophisticated request-level deepfake." — **Gemini 2.0 Pro** ([full](./reviews/gemini-2-pro-2026-04-21.md))
|
|
291
|
-
>
|
|
292
|
-
> "Not 'best-effort mimicry'; it's capture-and-replay of a real client." — **GPT-5.3** ([full](./reviews/gpt-5.3-2026-04-21.md))
|
|
293
|
-
>
|
|
294
|
-
> "The fingerprint-replay claim is backed by the code." — **Claude Opus 4.7** ([full](./reviews/claude-opus-4-7-2026-04-21.md))
|
|
282
|
+
## How it actually works
|
|
295
283
|
|
|
296
|
-
|
|
284
|
+
dario doesn't *guess* Claude Code's request shape — it captures it live from your installed `claude` binary on every startup, drift-detects against each upstream CC release, and replays it byte-for-byte. That's why the billing classifier can't tell the difference. Deep dive: [`docs/wire-fidelity.md`](./docs/wire-fidelity.md).
|
|
297
285
|
|
|
298
286
|
---
|
|
299
287
|
|
|
@@ -364,6 +352,7 @@ The tool doesn't know. The backend doesn't know. Dario is the seam.
|
|
|
364
352
|
- **Runs any non-Claude-Code agent.** A 64-entry schema-verified `TOOL_MAP` pre-maps Cline, Roo, Kilo, Cursor, Windsurf, Continue, Copilot, OpenHands, OpenClaw, Hermes, [hands](https://github.com/askalf/hands) tool names to CC's native set. No flag, no validator errors. → [`docs/integrations/agent-compat.md`](./docs/integrations/agent-compat.md)
|
|
365
353
|
- **Shim mode** *(deprecated in v4.2; removal scheduled for v5.x)*. The original "no HTTP hop" path that patched `globalThis.fetch` inside a `dario shim -- <cmd>` child process. Empirically only matches 3 of the 8 wire-shape axes the billing classifier inspects (system blocks, agent identity, header order) and falls back to total passthrough when the client sends a 1-block system — which `claude -p` and Agent-SDK both do. Use **proxy mode** for any non-CC client; that's the only mode that rebuilds every request to CC's full canonical shape. Shim emits a deprecation banner on every invocation. See [CHANGELOG v4.2.0](./CHANGELOG.md) for the side-by-side fingerprint diff that drove this call.
|
|
366
354
|
- **Recover output capability.** `dario proxy --system-prompt=partial` strips CC's tone/verbosity/no-comments constraints for 1.2–2.8× more output on open-ended work — empirically without flipping billing (the classifier doesn't read that slot). [Discussion #183](https://github.com/askalf/dario/discussions/183) has the per-prompt receipts. → [`docs/system-prompt.md`](./docs/system-prompt.md)
|
|
355
|
+
- **Honor client thinking (`--honor-client-thinking`, v4.8.3).** Default: dario rebuilds the outbound request with CC's interactive thinking shape regardless of what the client sent (adaptive when CC would use adaptive). Pass `--honor-client-thinking` or set `DARIO_HONOR_CLIENT_THINKING=1` to pass the client's `thinking` block through unchanged — for non-CC clients (Cursor, Cline, Agent SDK) that explicitly set their own thinking config and want it respected. Off by default; the rebuild-to-CC path is what keeps the subscription pool routing.
|
|
367
356
|
- **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)
|
|
368
357
|
- **Active overage protection (v4.1).** Halts the proxy on any `representative-claim: overage` response and returns 503 to subsequent requests until you run `dario resume` or the cooldown clears. Visibility-only mode (`--overage-behavior=warn`) for operators who want the signal without disrupting traffic. Halt state visible in TUI Status/Hits/Analytics tabs, surfaced as named SSE events, and as a best-effort native desktop notification. [#288](https://github.com/askalf/dario/issues/288).
|
|
369
358
|
|
|
@@ -391,6 +380,23 @@ cd $(npm root -g)/@askalf/dario && npm ls --production
|
|
|
391
380
|
|
|
392
381
|
---
|
|
393
382
|
|
|
383
|
+
## Project status — maintenance mode
|
|
384
|
+
|
|
385
|
+
As of **2026-05-19**, dario is in maintenance mode. New feature work has stopped; what runs unattended is the part that matters for keeping your subscription routing intact:
|
|
386
|
+
|
|
387
|
+
- **Drift watchers** open auto-rebake PRs within ~30 min of each new Claude Code release (Class A) and within ~30 min of in-version remote-config drift (Class B).
|
|
388
|
+
- **Compat suite** ([`compat-test-self-hosted.yml`](./.github/workflows/compat-test-self-hosted.yml)) gates every wire-shape-affecting PR against a live Anthropic call before merge — green compat means the rebake didn't break the subscription path.
|
|
389
|
+
- **Auto-release pipeline** publishes to npm + ghcr the moment a rebake PR merges; an [idempotency gate](./.github/workflows/cc-drift-auto-release.yml) backfills any registry that lagged so partial releases self-heal.
|
|
390
|
+
- **NPM_TOKEN health monitor** runs daily and opens a GitHub issue if the token rotates, expires, or has its scopes changed — token rot becomes a 24h-detection issue instead of an invisible release failure.
|
|
391
|
+
- **Billing-classifier canary** fires a single daily probe to detect when Anthropic shifts classifier rules (Class C), so you find out before traffic silently moves to the wrong pool.
|
|
392
|
+
- **Recovery runbook** ([`docs/recovery.md`](./docs/recovery.md)) covers the residual manual cases — OAuth credential rotation, runner re-registration, ghcr backfill — sorted by how often they actually come up.
|
|
393
|
+
|
|
394
|
+
The proxy, TUI, multi-account pool, overage guard, drift detection, and the 2026-06-15 billing-cliff protection are all stable surface; the only material runtime addition since this status changed is `--honor-client-thinking` (see Capabilities). If something breaks because Anthropic shipped something new, the watchers + compat suite catch it within a release cycle and the maintainer reviews the bot-PR.
|
|
395
|
+
|
|
396
|
+
Feature velocity moved to the [askalf platform](https://askalf.org) — a self-hosted AI workforce that uses dario as its LLM substrate. Same engineering rigor (drift detection, SLSA provenance, zero-telemetry), aimed at the workforce layer above the proxy.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
394
400
|
## Who it's for
|
|
395
401
|
|
|
396
402
|
**Best fit:** developers juggling multiple LLM tools and per-tool API keys · Claude Pro/Max subscribers who want their plan usable everywhere, not just in Claude Code · teams running local/hosted OpenAI-compat servers who want one stable local endpoint · Agent SDK users who want OAuth-subscription routing with zero code change (`baseURL: 'http://localhost:3456'`) · power users wanting multi-account pooling + 429 failover on their own machine.
|
|
@@ -509,6 +515,7 @@ Ordered by relevance to a dario reader — projects that route through dario fir
|
|
|
509
515
|
|
|
510
516
|
| Project | What it does |
|
|
511
517
|
|---|---|
|
|
518
|
+
| [askalf platform](https://askalf.org) | Self-hosted AI workforce — agents that run real business + life work, not more devops bots. Uses dario as its LLM substrate; same engineering rigor, workforce layer above the proxy. *Shipping soon.* |
|
|
512
519
|
| [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. |
|
|
513
520
|
| [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. |
|
|
514
521
|
| [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. |
|
package/dist/accounts.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ export declare function loadAccount(alias: string): Promise<AccountCredentials |
|
|
|
12
12
|
export declare function loadAllAccounts(): Promise<AccountCredentials[]>;
|
|
13
13
|
export declare function saveAccount(creds: AccountCredentials): Promise<void>;
|
|
14
14
|
export declare function removeAccount(alias: string): Promise<boolean>;
|
|
15
|
+
/** Detect deviceId + accountUuid from an installed Claude Code. */
|
|
16
|
+
export declare function detectClaudeIdentity(): Promise<{
|
|
17
|
+
deviceId: string;
|
|
18
|
+
accountUuid: string;
|
|
19
|
+
} | null>;
|
|
15
20
|
/** Refresh an account's OAuth token using dario's auto-detected CC OAuth config. */
|
|
16
21
|
export declare function refreshAccountToken(creds: AccountCredentials): Promise<AccountCredentials>;
|
|
17
22
|
/** Test-only — inspect the in-flight map. Production code has no business peeking. */
|
package/dist/accounts.js
CHANGED
|
@@ -108,7 +108,7 @@ export async function removeAccount(alias) {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
/** Detect deviceId + accountUuid from an installed Claude Code. */
|
|
111
|
-
async function detectClaudeIdentity() {
|
|
111
|
+
export async function detectClaudeIdentity() {
|
|
112
112
|
const paths = [
|
|
113
113
|
join(homedir(), '.claude', '.claude.json'),
|
|
114
114
|
join(homedir(), '.claude.json'),
|
package/dist/doctor.d.ts
CHANGED
|
@@ -38,6 +38,41 @@ export declare function exitCodeFor(checks: Check[]): number;
|
|
|
38
38
|
* text. Emitted by `dario doctor --json`.
|
|
39
39
|
*/
|
|
40
40
|
export declare function formatChecksJson(checks: Check[]): string;
|
|
41
|
+
/**
|
|
42
|
+
* Pure function: compare each pool account's stored {deviceId, accountUuid}
|
|
43
|
+
* against the live `.claude.json` identity and return Check rows describing
|
|
44
|
+
* any drift. Factored out of runChecks so it's unit-testable without I/O.
|
|
45
|
+
*
|
|
46
|
+
* Drift surfaces when a user re-installs Claude Code (or switches the active
|
|
47
|
+
* account inside CC) AFTER `dario accounts add`, so the stored snapshot in
|
|
48
|
+
* `~/.dario/accounts/<alias>.json` no longer matches what the proxy reads
|
|
49
|
+
* live from `~/.claude.json` per request. Anthropic cross-validates the
|
|
50
|
+
* OAuth bearer against `metadata.user_id` (built from the live deviceId)
|
|
51
|
+
* and 401s with `authentication_error` on non-Haiku models when they
|
|
52
|
+
* disagree — Haiku is more permissive and may succeed despite the mismatch,
|
|
53
|
+
* which makes the failure mode look intermittent and account-tier-shaped
|
|
54
|
+
* even though it's an identity-staleness bug.
|
|
55
|
+
*
|
|
56
|
+
* Single-account mode (no pool, just `~/.dario/credentials.json`) is not
|
|
57
|
+
* covered here: the proxy reads identity live and dario never stored a
|
|
58
|
+
* baseline to compare against. Future: add `dario doctor --identity` for
|
|
59
|
+
* an opt-in network probe that hits Anthropic with the bearer and live
|
|
60
|
+
* deviceId to confirm they align.
|
|
61
|
+
*/
|
|
62
|
+
export interface IdentityDriftInput {
|
|
63
|
+
/** Live `{deviceId, accountUuid}` from `~/.claude.json`, or null if absent. */
|
|
64
|
+
live: {
|
|
65
|
+
deviceId: string;
|
|
66
|
+
accountUuid: string;
|
|
67
|
+
} | null;
|
|
68
|
+
/** Pool account snapshots — `[]` for single-account mode. */
|
|
69
|
+
poolAccounts: Array<{
|
|
70
|
+
alias: string;
|
|
71
|
+
deviceId: string;
|
|
72
|
+
accountUuid: string;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
75
|
+
export declare function checkIdentityDrift(input: IdentityDriftInput): Check[];
|
|
41
76
|
export declare function probeNpmLatestCC(): string | null;
|
|
42
77
|
export interface RunChecksOptions {
|
|
43
78
|
/**
|
package/dist/doctor.js
CHANGED
|
@@ -65,6 +65,52 @@ export function formatChecksJson(checks) {
|
|
|
65
65
|
checks,
|
|
66
66
|
}, null, 2);
|
|
67
67
|
}
|
|
68
|
+
export function checkIdentityDrift(input) {
|
|
69
|
+
const { live, poolAccounts } = input;
|
|
70
|
+
// Short-prefix for surfaced IDs — 64-char userIDs and 36-char UUIDs are
|
|
71
|
+
// noisy in a doctor report. Operators only need enough to recognize / diff
|
|
72
|
+
// by eye; full values stay in the source files.
|
|
73
|
+
const shortId = (s) => (s ? `${s.slice(0, 8)}…` : '(empty)');
|
|
74
|
+
if (!live || (!live.deviceId && !live.accountUuid)) {
|
|
75
|
+
return [{
|
|
76
|
+
status: 'info',
|
|
77
|
+
label: 'Identity',
|
|
78
|
+
detail: 'no ~/.claude.json found — proxy will send requests without metadata.user_id, which routes them to Extra Usage billing instead of the Max plan allocation. Run Claude Code at least once to generate it.',
|
|
79
|
+
}];
|
|
80
|
+
}
|
|
81
|
+
if (poolAccounts.length === 0) {
|
|
82
|
+
return [{
|
|
83
|
+
status: 'info',
|
|
84
|
+
label: 'Identity',
|
|
85
|
+
detail: `~/.claude.json userID=${shortId(live.deviceId)} — single-account mode reads identity live per-request, so drift between the loaded bearer and ~/.claude.json only surfaces as 401 from Anthropic on non-Haiku models. Pool mode (\`dario accounts add\`) snapshots identity for drift detection.`,
|
|
86
|
+
}];
|
|
87
|
+
}
|
|
88
|
+
const aligned = [];
|
|
89
|
+
const drifted = [];
|
|
90
|
+
for (const acc of poolAccounts) {
|
|
91
|
+
const deviceMatch = acc.deviceId === live.deviceId;
|
|
92
|
+
const acctMatch = acc.accountUuid === live.accountUuid;
|
|
93
|
+
if (deviceMatch && acctMatch) {
|
|
94
|
+
aligned.push(acc.alias);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const which = !deviceMatch && !acctMatch ? 'both' : !deviceMatch ? 'deviceId' : 'accountUuid';
|
|
98
|
+
drifted.push(`${acc.alias} (${which})`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (drifted.length === 0) {
|
|
102
|
+
return [{
|
|
103
|
+
status: 'ok',
|
|
104
|
+
label: 'Identity',
|
|
105
|
+
detail: `${aligned.length}/${poolAccounts.length} pool account${poolAccounts.length === 1 ? '' : 's'} match ~/.claude.json (userID=${shortId(live.deviceId)})`,
|
|
106
|
+
}];
|
|
107
|
+
}
|
|
108
|
+
return [{
|
|
109
|
+
status: 'warn',
|
|
110
|
+
label: 'Identity',
|
|
111
|
+
detail: `${drifted.length}/${poolAccounts.length} pool account${poolAccounts.length === 1 ? '' : 's'} drifted from ~/.claude.json (live userID=${shortId(live.deviceId)}): ${drifted.join('; ')} — re-run \`dario accounts add <alias>\` to refresh the stored snapshot, or non-Haiku requests on the drifted account(s) will 401`,
|
|
112
|
+
}];
|
|
113
|
+
}
|
|
68
114
|
/**
|
|
69
115
|
* Ask npm for the latest @anthropic-ai/claude-code version. One 3s
|
|
70
116
|
* timeout; failures return null so doctor silently drops the check.
|
|
@@ -567,6 +613,26 @@ export async function runChecks(opts = {}) {
|
|
|
567
613
|
catch (err) {
|
|
568
614
|
checks.push({ status: 'warn', label: 'Pool', detail: `check failed: ${err.message}` });
|
|
569
615
|
}
|
|
616
|
+
// ---- Identity drift (pool account snapshot vs live ~/.claude.json)
|
|
617
|
+
try {
|
|
618
|
+
const { detectClaudeIdentity, listAccountAliases, loadAllAccounts } = await import('./accounts.js');
|
|
619
|
+
const live = await detectClaudeIdentity();
|
|
620
|
+
const aliases = await listAccountAliases();
|
|
621
|
+
const loaded = aliases.length ? await loadAllAccounts() : [];
|
|
622
|
+
const driftChecks = checkIdentityDrift({
|
|
623
|
+
live,
|
|
624
|
+
poolAccounts: loaded.map((a) => ({
|
|
625
|
+
alias: a.alias,
|
|
626
|
+
deviceId: a.deviceId,
|
|
627
|
+
accountUuid: a.accountUuid,
|
|
628
|
+
})),
|
|
629
|
+
});
|
|
630
|
+
for (const c of driftChecks)
|
|
631
|
+
checks.push(c);
|
|
632
|
+
}
|
|
633
|
+
catch (err) {
|
|
634
|
+
checks.push({ status: 'warn', label: 'Identity', detail: `check failed: ${err.message}` });
|
|
635
|
+
}
|
|
570
636
|
// ---- Secondary backends
|
|
571
637
|
try {
|
|
572
638
|
const { listBackends } = await import('./openai-backend.js');
|
|
@@ -282,7 +282,7 @@ export declare function _resetInstalledVersionProbeForTest(): void;
|
|
|
282
282
|
*/
|
|
283
283
|
export declare const SUPPORTED_CC_RANGE: {
|
|
284
284
|
readonly min: "1.0.0";
|
|
285
|
-
readonly maxTested: "2.1.
|
|
285
|
+
readonly maxTested: "2.1.145";
|
|
286
286
|
};
|
|
287
287
|
/**
|
|
288
288
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/dist/live-fingerprint.js
CHANGED
|
@@ -777,7 +777,7 @@ export function _resetInstalledVersionProbeForTest() {
|
|
|
777
777
|
*/
|
|
778
778
|
export const SUPPORTED_CC_RANGE = {
|
|
779
779
|
min: '1.0.0',
|
|
780
|
-
maxTested: '2.1.
|
|
780
|
+
maxTested: '2.1.145',
|
|
781
781
|
};
|
|
782
782
|
/**
|
|
783
783
|
* Compare two dotted-numeric version strings. Returns negative if `a<b`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.5",
|
|
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": {
|
|
@@ -22,7 +22,7 @@
|
|
|
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
24
|
"test": "node --test --test-concurrency=8 test/all.test.mjs",
|
|
25
|
-
"test:serial": "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 && node test/request-queue.mjs && node test/effort-flag.mjs && node test/template-invariants.mjs",
|
|
25
|
+
"test:serial": "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/doctor-identity-drift.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 && node test/request-queue.mjs && node test/effort-flag.mjs && node test/template-invariants.mjs",
|
|
26
26
|
"audit": "npm audit --production --audit-level=high",
|
|
27
27
|
"prepublishOnly": "npm run build",
|
|
28
28
|
"start": "node dist/cli.js",
|