@askalf/dario 4.8.99 → 4.8.101

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 CHANGED
@@ -129,7 +129,7 @@ Switching providers is a model-name change, not a reconfigure. Add a backend onc
129
129
  Two layers, separated:
130
130
 
131
131
  1. **Tiered pricing is fine.** Anthropic can charge differently for first-party use vs. third-party use. Every SaaS does this.
132
- 2. **Hiding the tier from the customer is not.** When the public docs say "1M context available on Sonnet/Opus" but the auth layer rejects every attempt to access it on the OAuth path most subscribers use — when the billing classifier silently flips your request to overage without saying which signal triggered it — that's information asymmetry weaponized into product design.
132
+ 2. **Hiding the tier from the customer is not.** When the public docs say "1M context available on Sonnet/Opus" but on the OAuth path most subscribers use it's off by default (the `context-1m` beta isn't in the default set, so you get the 200K window unless you know the flag to turn it back on) — when the billing classifier silently flips your request to overage without saying which signal triggered it — that's information asymmetry weaponized into product design.
133
133
 
134
134
  Both vendors sell the same two products: a flat-rate subscription and a metered API. OpenAI keeps them physically separate — ChatGPT Plus is chat-only with no API surface; the API is a different product with its own key; you pick one. Anthropic separates them too, but its **subscription** is reached through the *same API-shaped interface* Claude Code uses, and which bucket a request bills to — subscription vs. metered overage — is decided by an **undocumented classifier** reading signals in the request, not by you choosing a product.
135
135
 
@@ -162,7 +162,7 @@ dario doesn't *guess* Claude Code's request shape — it captures it live from y
162
162
 
163
163
  | Silent wire-shape change (no subscriber changelog) | Effect on subscribers | dario shipped |
164
164
  |---|---|---|
165
- | `context-1m-2025-08-07` dropped from the default beta set + rejected on OAuth auth | Subscription users lose >200K context on Sonnet/Opus | v3.38.3–4 (2026-05-14/15) |
165
+ | `context-1m-2025-08-07` dropped from the default beta set on the OAuth path | Subscription requests default to the 200K window on Sonnet/Opus unless the beta is re-added | v3.38.3–4 (2026-05-14/15) |
166
166
  | `thinking: {type:"adaptive"}` gated per-model server-side | Sonnet/Opus 4-5 through any proxy 400s every request | [v3.38.5](https://github.com/askalf/dario/pull/273) — 2026-05-15 |
167
167
  | `TodoWrite`/`TodoRead` replaced by the `Task*` family, no migration note | Clients hardcoding `todo_*` send unrecognized tools | [v3.38.6](https://github.com/askalf/dario/pull/274) — 13 min later |
168
168
  | **Claude Fable 5** ships as CC's flagship (v2.1.170) with undocumented wire quirks: a required `fallback-credit-2026-06-01` beta, soft-refusal of `max`/`xhigh` effort, and a `[1m]`-only `context-1m` beta | Subscription fable traffic 200-refused (empty body) without the flag; wrong effort silently returns nothing | [v4.8.46–52](https://github.com/askalf/dario/pulls?q=fable) — 2026-06-09 |
@@ -171,8 +171,8 @@ dario doesn't *guess* Claude Code's request shape — it captures it live from y
171
171
 
172
172
  And it gets subtler: v4.2.1 (2026-05-17) shipped receipts for **same CC binary, different wire output 24 hours apart** — Anthropic ships changes through CC's *remote configuration*, not just npm releases. So dario runs **three classes of drift detection**, all auto-detecting and auto-PR'ing:
173
173
 
174
- - **Class A — npm-release drift.** [`cc-drift-watch.yml`](./.github/workflows/cc-drift-watch.yml) (hourly, github-hosted) catches each new CC npm release; [`cc-drift-auto-release.yml`](./.github/workflows/cc-drift-auto-release.yml) auto-drafts, merges, and ships within minutes.
175
- - **Class B — same-binary remote-config drift** *(v4.2.2)*. [`cc-drift-template-watch.yml`](./.github/workflows/cc-drift-template-watch.yml) (every 30 min, self-hosted runner with an authenticated CC install) captures live and **opens an auto-rebake PR** with a unified-line diff inline. The only way to catch this class — github-hosted has no Pro/Max session to capture from.
174
+ - **Class A — npm-release drift.** [`cc-drift-watch.yml`](./.github/workflows/cc-drift-watch.yml) (scheduled hourly, github-hosted) catches each new CC npm release; [`cc-drift-auto-release.yml`](./.github/workflows/cc-drift-auto-release.yml) auto-drafts, merges, and ships within minutes.
175
+ - **Class B — same-binary remote-config drift** *(v4.2.2)*. [`cc-drift-template-watch.yml`](./.github/workflows/cc-drift-template-watch.yml) (scheduled every 30 min, self-hosted runner with an authenticated CC install) captures live and **opens an auto-rebake PR** with a unified-line diff inline. The only way to catch this class — github-hosted has no Pro/Max session to capture from.
176
176
  - **Class C — classifier-rule drift** *(v4.6.0)*. [`cc-billing-classifier-canary.yml`](./.github/workflows/cc-billing-classifier-canary.yml) sends one live request daily and asserts the `representative-claim` header still maps to a subscription bucket — catches Anthropic changing the *rules* while the wire shape is unchanged.
177
177
  - **Guards on the guards.** A [PR-time compat gate](./.github/workflows/compat-test-self-hosted.yml) *(v4.3.0)* runs the full compat suite against a live proxy before any wire-shape PR merges; a [liveness alarm](./.github/workflows/cc-drift-watcher-liveness.yml) *(v4.4.2)* fires if the Class-B watcher goes quiet for 8h. Setup + walkthrough: [`docs/drift-monitor.md`](./docs/drift-monitor.md).
178
178
 
@@ -202,7 +202,7 @@ The tool doesn't know. The backend doesn't know. dario is the seam.
202
202
 
203
203
  A subscriber should never see a single response billed outside their subscription pool during normal operation. One means something is wrong — wire-shape drift, a classifier change, an account misconfig — and continuing to forward requests in the same shape bleeds real money (accounts with extra-usage enabled) or returns a wall of rejections (accounts without it). The first hit is the signal; the second through hundredth are damage.
204
204
 
205
- So the moment any upstream response bills to something other than your subscription pool — `representative-claim: overage`, `api`, or a new credit/SDK bucket like the one the 2026-06-15 Agent-SDK split introduces — dario **halts the proxy**. The check is an allow-list, not a match on `overage`: anything that isn't a known subscription claim (`five_hour`/`seven_day` and their fallbacks) and isn't the `unknown` no-header sentinel trips it, so a credit-bucket claim dario has never seen still halts. Every subsequent request returns `503` with an Anthropic-shaped error body the client surfaces verbatim, until you run `dario resume`, press `R` on the TUI, or the cooldown clears (default 30 min). The halt is visible across the TUI's Status, Hits, and Analytics tabs, fires a best-effort native OS notification, and emits named SSE events. (In `--upstream-api-key` passthrough mode the guard is off `api` billing is the point there, not a failure.)
205
+ So the moment any upstream response bills to something other than your subscription pool — `representative-claim: overage`, `api`, or a new credit/SDK bucket like the one the 2026-06-15 Agent-SDK split introduces — dario **halts the proxy**. The check is an allow-list, not a match on `overage`: anything that isn't a known subscription claim (`five_hour`/`seven_day` and their fallbacks) and isn't the `unknown` no-header sentinel trips it, so a credit-bucket claim dario has never seen still halts. Every subsequent request returns `503` with an Anthropic-shaped error body the client surfaces verbatim, until you run `dario resume`, press `R` on the TUI, or the cooldown clears (default 30 min). The halt is visible across the TUI's Status, Hits, and Analytics tabs, fires a best-effort native OS notification, and emits named SSE events. (In upstream-API-key passthrough mode — set `ANTHROPIC_UPSTREAM_API_KEY` — the guard is off; `api` billing is the point there, not a failure.)
206
206
 
207
207
  ```
208
208
  ┌─ dario ─────────────────────────────[ q quit · Tab next · ? help ]──┐
@@ -242,8 +242,8 @@ Tune via `~/.dario/config.json` → `overageGuard`, or CLI flags: `--overage-beh
242
242
  | Dependencies | **0 runtime.** Verify: `npm ls --production` |
243
243
  | Provenance | Every release [SLSA-attested](https://www.npmjs.com/package/@askalf/dario) via GitHub Actions + Sigstore |
244
244
  | Scanning | [CodeQL](https://github.com/askalf/dario/actions/workflows/codeql.yml) on every push and weekly |
245
- | Tests | **99 test files**, **92 in the default `npm test` suite** (`test/all.test.mjs`) — green on every release |
246
- | Drift response | hourly [`cc-drift-watch.yml`](./.github/workflows/cc-drift-watch.yml) + auto-publish on merge — median CC-release → dario-release under one hour |
245
+ | Tests | **100 test files**, **93 in the default `npm test` suite** (`test/all.test.mjs`) — green on every release |
246
+ | Drift response | scheduled-hourly [`cc-drift-watch.yml`](./.github/workflows/cc-drift-watch.yml) + auto-publish on merge — CC-release → dario-release typically same-day |
247
247
  | Credentials | Never logged, redacted from errors, `0600` on disk in `0700` dirs; MCP server redacts at the tool boundary |
248
248
  | Network | Binds `127.0.0.1` by default; upstream only to configured backends over HTTPS; hardcoded SSRF allowlist |
249
249
  | Telemetry | **None.** No analytics, no tracking, no data collection |
@@ -260,7 +260,7 @@ cd $(npm root -g)/@askalf/dario && npm ls --production
260
260
 
261
261
  dario's surface is feature-complete and stable: the proxy, the TUI, the multi-account pool, the overage guard, the 2026-06-15 cliff protection. What *isn't* stable is the thing it defends against. Anthropic ships wire-shape and classifier changes with no subscriber changelog, on no schedule — so the part of dario that runs unattended is the part that keeps your subscription routing the day they do, and it runs every day.
262
262
 
263
- That defense is live: [three drift watchers](#how-it-works-and-how-it-stays-working) (npm-release hourly, remote-config every 30 min, classifier-rule daily), a PR-time compat gate that runs the full suite against a live proxy before any wire-shape change merges, a liveness alarm if a watcher goes quiet, a daily NPM_TOKEN health check, and an auto-release pipeline that median-ships a fix under an hour after a CC release. When Anthropic moves, the watchers catch it within a release cycle, the bot opens the PR, the maintainer reviews and merges — the receipt log above is that machinery doing its job. Residual manual cases — OAuth rotation, runner re-registration, ghcr backfill — live in the [recovery runbook](./docs/recovery.md).
263
+ That defense is live: [three drift watchers](#how-it-works-and-how-it-stays-working) (npm-release hourly, remote-config every 30 min, classifier-rule daily — cron schedules; GitHub coalesces scheduled runs, so effective intervals run longer), a PR-time compat gate that runs the full suite against a live proxy before any wire-shape change merges, a liveness alarm if a watcher goes quiet, a daily NPM_TOKEN health check, and an auto-release pipeline that ships a fix within hours of a CC release. When Anthropic moves, the watchers catch it within a release cycle, the bot opens the PR, the maintainer reviews and merges — the receipt log above is that machinery doing its job. Residual manual cases — OAuth rotation, runner re-registration, ghcr backfill — live in the [recovery runbook](./docs/recovery.md).
264
264
 
265
265
  New *product* work happens on the [askalf platform](https://askalf.org), a self-hosted AI workforce built on dario. dario itself doesn't need new features — it has one job, and keeping the truth about a moving target current is a job that never stops.
266
266
 
@@ -329,7 +329,7 @@ PRs welcome. Small TypeScript codebase, zero runtime deps. Architecture + file-b
329
329
  git clone https://github.com/askalf/dario && cd dario
330
330
  npm install
331
331
  npm run dev # tsx, no build step
332
- npm test # 92 test files via test/all.test.mjs, green on every release
332
+ npm test # 93 test files via test/all.test.mjs, green on every release
333
333
  npm run e2e # live proxy + OAuth (needs a working Claude backend)
334
334
  ```
335
335
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "_version": "2.1.193",
2
+ "_version": "2.1.195",
3
3
  "_captured": "2026-06-24T06:27:30.671Z",
4
4
  "_source": "bundled",
5
5
  "_schemaVersion": 3,
@@ -1321,7 +1321,7 @@
1321
1321
  "anthropic_beta": "claude-code-20250219,interleaved-thinking-2025-05-14,thinking-token-count-2026-05-13,context-management-2025-06-27,prompt-caching-scope-2026-01-05,mid-conversation-system-2026-04-07,advisor-tool-2026-03-01,effort-2025-11-24",
1322
1322
  "header_values": {
1323
1323
  "accept": "application/json",
1324
- "user-agent": "claude-cli/2.1.193 (external, sdk-cli)",
1324
+ "user-agent": "claude-cli/2.1.195 (external, sdk-cli)",
1325
1325
  "x-stainless-arch": "x64",
1326
1326
  "x-stainless-lang": "js",
1327
1327
  "x-stainless-os": "Linux",
@@ -1346,5 +1346,5 @@
1346
1346
  "output_config",
1347
1347
  "stream"
1348
1348
  ],
1349
- "_supportedMaxTested": "2.1.193"
1349
+ "_supportedMaxTested": "2.1.195"
1350
1350
  }
@@ -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.193";
285
+ readonly maxTested: "2.1.195";
286
286
  };
287
287
  /**
288
288
  * Compare two dotted-numeric version strings. Returns negative if `a<b`,
@@ -786,7 +786,7 @@ export function _resetInstalledVersionProbeForTest() {
786
786
  */
787
787
  export const SUPPORTED_CC_RANGE = {
788
788
  min: '1.0.0',
789
- maxTested: '2.1.193',
789
+ maxTested: '2.1.195',
790
790
  };
791
791
  /**
792
792
  * 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.99",
3
+ "version": "4.8.101",
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": {