@askalf/dario 3.31.12 → 3.31.13

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
@@ -160,7 +160,7 @@ OAuth-backed Claude Max, billed against your plan instead of the API. Activated
160
160
  - **Drift detection** (v3.17). On startup dario probes the installed `claude` binary and compares against the captured template. Mismatch triggers a forced refresh and prints a one-line warning. Users never silently sit on a stale template again.
161
161
  - **Compat matrix** (v3.17, bumped in v3.19.5). `SUPPORTED_CC_RANGE` is encoded in code; installed CC outside the band prints a warn (untested above) or fail (below min) — zero-dep dotted-numeric comparator, no `semver` import per the dep policy.
162
162
  - **Billing tag** reconstructed using CC's own algorithm: `x-anthropic-billing-header: cc_version=<version>.<build_tag>; cc_entrypoint=cli; cch=<5-char-hex>;` where `build_tag = SHA-256(seed + chars[4,7,20] of user message + version).slice(0,3)`.
163
- - **OAuth config auto-detection** from the installed CC binary. When Anthropic rotates `client_id`, authorize URL, or scopes, dario picks up the new values on the next run without needing a release. Cache at `~/.dario/cc-oauth-cache-v4.json`, keyed by the CC binary fingerprint.
163
+ - **OAuth config auto-detection** from the installed CC binary. When Anthropic rotates `client_id`, authorize URL, or scopes, dario picks up the new values on the next run without needing a release. Cache at `~/.dario/cc-oauth-cache-v6.json`, keyed by the CC binary fingerprint. Cache path bumps each time the canonical OAuth config shape changes so stale caches regenerate automatically on upgrade.
164
164
  - **Multi-account pool mode** — see [Multi-account pool mode](#multi-account-pool-mode). Automatic when 2+ accounts are configured.
165
165
  - **Framework scrubbing** — known third-party identity markers (`OpenClaw`, `sessions_*` prefixes, orchestration tags) stripped from system prompt and message content before the request leaves your machine.
166
166
  - **Atomic cache writes + cache corruption recovery** (v3.17). Template cache writes go through pid-qualified `.tmp` + `rename`, so an OS crash mid-write doesn't leave a half-written file. Unparseable cache files get quarantined to `cc-template.live.json.bad-<timestamp>` and dario self-heals on the next capture.
@@ -334,7 +334,9 @@ A version marker (`<!-- dario-sub-agent-version: X -->`) embedded in the markdow
334
334
  |---|---|
335
335
  | `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. |
336
336
  | `dario proxy` | Start the local API proxy on port 3456 |
337
- | `dario doctor` | Aggregated health report — dario / Node / runtime-TLS / CC binary + compat / template + drift / OAuth / pool / backends / sub-agent |
337
+ | `dario doctor [--probe] [--auth-check] [--json]` | Aggregated health report — dario / Node / runtime-TLS / CC binary + compat / template + drift / OAuth / pool / 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 claude-bridge's `/status`, deepdive's health probes, and CI scrapers. |
338
+ | `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) |
339
+ | `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) |
338
340
  | `dario status` | Show Claude backend OAuth token health and expiry |
339
341
  | `dario refresh` | Force an immediate Claude token refresh |
340
342
  | `dario logout` | Delete stored Claude credentials |
@@ -761,7 +763,7 @@ Yes — anything that speaks the OpenAI Chat Completions API. Groq, OpenRouter,
761
763
  `dario doctor`. One command, one aggregated report — dario version, Node, platform, runtime/TLS classification, CC binary compat, template source + age + drift, OAuth status, pool state, backends, sub-agent install state, home dir. Exit code 1 if any check fails. Paste the output when you file an issue. (If you're inside Claude Code, `dario subagent install` once and then ask CC to "use the dario sub-agent to run doctor" — same output, no context switch.)
762
764
 
763
765
  **What happens when Anthropic rotates the OAuth config?**
764
- Dario auto-detects OAuth config from the installed Claude Code binary. When CC ships a new version with rotated values, dario picks them up on the next run. Cache at `~/.dario/cc-oauth-cache-v4.json`, keyed by the CC binary fingerprint. (Path bumped from v3 → v4 in v3.19.4 to invalidate stale caches across the scope-list change that broke the authorize flow between CC v2.1.104 and v2.1.107.)
766
+ Dario auto-detects OAuth config from the installed Claude Code binary. When CC ships a new version with rotated values, dario picks them up on the next run. Cache at `~/.dario/cc-oauth-cache-v6.json`, keyed by the CC binary fingerprint. The cache path version bumps each time the canonical OAuth config shape changes so stale caches regenerate automatically on upgrade — v3 → v4 in v3.19.4 (scope-list flip CC v2.1.104 v2.1.107), v4 v5 in v3.31.3 (authorize URL `claude.com/cai/` `claude.ai/` host normalization), v5 → v6 in v3.31.4 (6-scope restore after CC v2.1.116).
765
767
 
766
768
  If Anthropic rotates the values before the detector is updated, you can temporarily override any field with env vars (`DARIO_OAUTH_CLIENT_ID`, `DARIO_OAUTH_AUTHORIZE_URL`, `DARIO_OAUTH_TOKEN_URL`, `DARIO_OAUTH_SCOPES`) or by writing `~/.dario/oauth-config.override.json`:
767
769
 
@@ -1,6 +1,6 @@
1
1
  {
2
- "_version": "2.1.118",
3
- "_captured": "2026-04-23T15:14:02.377Z",
2
+ "_version": "2.1.119",
3
+ "_captured": "2026-04-24T13:28:12.469Z",
4
4
  "_source": "bundled",
5
5
  "_schemaVersion": 3,
6
6
  "agent_identity": "You are a Claude agent, built on Anthropic's Claude Agent SDK.",
@@ -484,7 +484,7 @@
484
484
  },
485
485
  {
486
486
  "name": "Monitor",
487
- "description": "Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you're waiting for the user to answer a question.\n\nMonitor is for the **streaming** case: \"tell me every time X happens.\" For one-shot \"wait until X is done,\" use Bash with run_in_background instead you'll get a completion notification when it exits.\n\nYour script's stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered \"ERROR\"\n\n # Each file change is an event\n inotifywait -m --format '%e %f' /watched/dir\n\n # Poll GitHub for new PR comments and emit one line per new comment\n last=$(date -u +%Y-%m-%dT%H:%M:%SZ)\n while true; do\n now=$(date -u +%Y-%m-%dT%H:%M:%SZ)\n gh api \"repos/owner/repo/issues/123/comments?since=$last\" --jq '.[] | \"\\(.user.login): \\(.body)\"'\n last=$now; sleep 30\n done\n\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\n**Script quality:**\n- Always use `grep --line-buffered` in pipes — without it, pipe buffering delays events by minutes.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn't kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5-1s for local checks.\n- Write a specific `description` — it appears in every notification (\"errors in deploy.log\" not \"watching logs\").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to \"still running.\" Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered \"elapsed_steps=\"\n\n # Right — one alternation covering progress + the failure signatures you'd act on\n tail -f run.log | grep -E --line-buffered \"elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM\"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means \"the lines you'd act on,\" not \"only good news.\" Never pipe raw logs; use `grep --line-buffered`, `awk`, or a wrapper that emits exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (PR monitoring, log tails) — the monitor runs until you call TaskStop or the session ends. Use TaskStop to cancel early.",
487
+ "description": "Start a background monitor that streams events from a long-running script. Each stdout line is an event — you keep working and notifications arrive in the chat. Events arrive on their own schedule and are not replies from the user, even if one lands while you're waiting for the user to answer a question.\n\nPick by how many notifications you need:\n- **One** (\"tell me when the server is ready / the build finishes\") use **Bash with `run_in_background`** and a command that exits when the condition is true, e.g. `until grep -q \"Ready in\" dev.log; do sleep 0.5; done`. You get a single completion notification when it exits.\n- **One per occurrence, indefinitely** (\"tell me every time an ERROR line appears\") → Monitor with an unbounded command (`tail -f`, `inotifywait -m`, `while true`).\n- **One per occurrence, until a known end** (\"emit each CI step result, stop when the run completes\") → Monitor with a command that emits lines and then exits.\n\nYour script's stdout is the event stream. Each line becomes a notification. Exit ends the watch.\n\n # Each matching log line is an event\n tail -f /var/log/app.log | grep --line-buffered \"ERROR\"\n\n # Each file change is an event\n inotifywait -m --format '%e %f' /watched/dir\n\n # Poll GitHub for new PR comments and emit one line per new comment\n last=$(date -u +%Y-%m-%dT%H:%M:%SZ)\n while true; do\n now=$(date -u +%Y-%m-%dT%H:%M:%SZ)\n gh api \"repos/owner/repo/issues/123/comments?since=$last\" --jq '.[] | \"\\(.user.login): \\(.body)\"'\n last=$now; sleep 30\n done\n\n # Node script that emits events as they arrive (e.g. WebSocket listener)\n node watch-for-events.js\n\n # Per-occurrence with a natural end: emit each CI check as it lands, exit when the run completes\n prev=\"\"\n while true; do\n s=$(gh pr checks 123 --json name,bucket)\n cur=$(jq -r '.[] | select(.bucket!=\"pending\") | \"\\(.name): \\(.bucket)\"' <<<\"$s\" | sort)\n comm -13 <(echo \"$prev\") <(echo \"$cur\")\n prev=$cur\n jq -e 'all(.bucket!=\"pending\")' <<<\"$s\" >/dev/null && break\n sleep 30\n done\n\n**Don't use an unbounded command for a single notification.** `tail -f`, `inotifywait -m`, and `while true` never exit on their own, so the monitor stays armed until timeout even after the event has fired. For \"tell me when X is ready,\" use Bash `run_in_background` with an `until` loop instead (one notification, ends in seconds). Note that `tail -f log | grep -m 1 ...` does *not* fix this: if the log goes quiet after the match, `tail` never receives SIGPIPE and the pipeline hangs anyway.\n\n**Script quality:**\n- Always use `grep --line-buffered` in pipes — without it, pipe buffering delays events by minutes.\n- In poll loops, handle transient failures (`curl ... || true`) — one failed request shouldn't kill the monitor.\n- Poll intervals: 30s+ for remote APIs (rate limits), 0.5-1s for local checks.\n- Write a specific `description` — it appears in every notification (\"errors in deploy.log\" not \"watching logs\").\n- Only stdout is the event stream. Stderr goes to the output file (readable via Read) but does not trigger notifications — for a command you run directly (e.g. `python train.py 2>&1 | grep --line-buffered ...`), merge stderr with `2>&1` so its failures reach your filter. (No effect on `tail -f` of an existing log — that file only contains what its writer redirected.)\n\n**Coverage — silence is not success.** When watching a job or process for an outcome, your filter must match every terminal state, not just the happy path. A monitor that greps only for the success marker stays silent through a crashloop, a hung process, or an unexpected exit — and silence looks identical to \"still running.\" Before arming, ask: *if this process crashed right now, would my filter emit anything?* If not, widen it.\n\n # Wrong — silent on crash, hang, or any non-success exit\n tail -f run.log | grep --line-buffered \"elapsed_steps=\"\n\n # Right — one alternation covering progress + the failure signatures you'd act on\n tail -f run.log | grep -E --line-buffered \"elapsed_steps=|Traceback|Error|FAILED|assert|Killed|OOM\"\n\nFor poll loops checking job state, emit on every terminal status (`succeeded|failed|cancelled|timeout`), not just success. If you cannot confidently enumerate the failure signatures, broaden the grep alternation rather than narrow it — some extra noise is better than missing a crashloop.\n\n**Output volume**: Every stdout line is a conversation message, so the filter should be selective — but selective means \"the lines you'd act on,\" not \"only good news.\" Never pipe raw logs; use `grep --line-buffered`, `awk`, or a wrapper that emits exactly the success and failure signals you care about. Monitors that produce too many events are automatically stopped; restart with a tighter filter if this happens.\n\nStdout lines within 200ms are batched into a single notification, so multiline output from a single event groups naturally.\n\nThe script runs in the same shell environment as Bash. Exit ends the watch (exit code is reported). Timeout → killed. Set `persistent: true` for session-length watches (PR monitoring, log tails) — the monitor runs until you call TaskStop or the session ends. Use TaskStop to cancel early.",
488
488
  "input_schema": {
489
489
  "$schema": "https://json-schema.org/draft/2020-12/schema",
490
490
  "type": "object",
@@ -973,7 +973,7 @@
973
973
  "anthropic_beta": "claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advisor-tool-2026-03-01,effort-2025-11-24,afk-mode-2026-01-31",
974
974
  "header_values": {
975
975
  "accept": "application/json",
976
- "user-agent": "claude-cli/2.1.118 (external, sdk-cli)",
976
+ "user-agent": "claude-cli/2.1.119 (external, sdk-cli)",
977
977
  "x-stainless-arch": "x64",
978
978
  "x-stainless-lang": "js",
979
979
  "x-stainless-os": "Windows",
@@ -998,5 +998,5 @@
998
998
  "output_config",
999
999
  "stream"
1000
1000
  ],
1001
- "_supportedMaxTested": "2.1.118"
1001
+ "_supportedMaxTested": "2.1.119"
1002
1002
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/dario",
3
- "version": "3.31.12",
3
+ "version": "3.31.13",
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": {