@askalf/dario 3.19.3 → 3.19.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 CHANGED
@@ -565,7 +565,7 @@ Yes — anything that speaks the OpenAI Chat Completions API. Groq, OpenRouter,
565
565
  `dario doctor`. One command, one aggregated report — dario version, Node, platform, CC binary compat, template source + age + drift, OAuth status, pool state, backends, home dir. Exit code 1 if any check fails. Paste the output when you file an issue.
566
566
 
567
567
  **What happens when Anthropic rotates the OAuth config?**
568
- 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-v3.json`, keyed by the CC binary fingerprint.
568
+ 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.
569
569
 
570
570
  **What happens when Anthropic changes the CC request template?**
571
571
  Dario extracts the live request template from your installed Claude Code binary on startup — the system prompt, tool schemas, user-agent, beta flags, and header insertion order — and uses those to replay requests instead of a version pinned into dario itself. When CC ships a new version with a tweaked template, the next `dario proxy` run picks it up automatically. Drift detection (v3.17) forces a refresh when the installed CC version changes under dario.
@@ -28,9 +28,10 @@
28
28
  * "MANUAL_REDIRECT_URL" on platform.claude.com is only used when dario's
29
29
  * local HTTP server can't bind a port; dario never hits that path.)
30
30
  *
31
- * Results are cached per-binary-hash at ~/.dario/cc-oauth-cache-v2.json so
32
- * startup only re-scans when the user upgrades Claude Code. The -v2 suffix
33
- * invalidates the v3.4.0-v3.4.2 caches that held the wrong (dev) client_id.
31
+ * Results are cached per-binary-hash at ~/.dario/cc-oauth-cache-v4.json so
32
+ * startup only re-scans when the user upgrades Claude Code. The cache suffix
33
+ * is bumped each time scope handling or the fallback config changes, so
34
+ * upgrading dario picks up the new values without a manual cache clear.
34
35
  */
35
36
  export interface DetectedOAuthConfig {
36
37
  clientId: string;
@@ -28,9 +28,10 @@
28
28
  * "MANUAL_REDIRECT_URL" on platform.claude.com is only used when dario's
29
29
  * local HTTP server can't bind a port; dario never hits that path.)
30
30
  *
31
- * Results are cached per-binary-hash at ~/.dario/cc-oauth-cache-v2.json so
32
- * startup only re-scans when the user upgrades Claude Code. The -v2 suffix
33
- * invalidates the v3.4.0-v3.4.2 caches that held the wrong (dev) client_id.
31
+ * Results are cached per-binary-hash at ~/.dario/cc-oauth-cache-v4.json so
32
+ * startup only re-scans when the user upgrades Claude Code. The cache suffix
33
+ * is bumped each time scope handling or the fallback config changes, so
34
+ * upgrading dario picks up the new values without a manual cache clear.
34
35
  */
35
36
  import { readFile, writeFile, mkdir, stat, open as openFile } from 'node:fs/promises';
36
37
  import { existsSync } from 'node:fs';
@@ -44,23 +45,25 @@ const FALLBACK = {
44
45
  clientId: '9d1c250a-e61b-44d9-88ed-5944d1962f5e',
45
46
  authorizeUrl: 'https://claude.com/cai/oauth/authorize',
46
47
  tokenUrl: 'https://platform.claude.com/v1/oauth/token',
47
- // Scopes are the full `n36` union from the CC binary, which is the value
48
- // sent during a normal `claude login` (non-setup-token) flow. In CC's
49
- // source: `let D = f ? [TI] : n36` where `f = inferenceOnly` (true only
50
- // for `claude setup-token`). Normal interactive login uses the 6-scope
51
- // union including `org:create_api_key` even though that scope is named
52
- // "Console-only" by convention, CC's own login flow requests it up front.
53
- // Earlier dario versions (3.2.7 through 3.4.3) dropped `org:create_api_key`
54
- // from the list based on a misread of the name; the dev-only client_id
55
- // was lenient enough to accept the shorter list, the prod client_id is not.
56
- scopes: 'org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload',
48
+ // Scopes match CC v2.1.107+ interactive login: the 5-scope user-only set.
49
+ // Between CC v2.1.104 and v2.1.107, Anthropic's authorize endpoint flipped
50
+ // its policy on `org:create_api_key` for this client_id the shorter list
51
+ // is now the only accepted one, and the 6-scope form returns "Invalid
52
+ // request format". CC's own binary dropped `org:create_api_key` from the
53
+ // `n36` union to match. Dario #42 (tetsuco, 2026-04-17) surfaced this as
54
+ // a fresh-login failure on macOS against CC v2.1.107.
55
+ //
56
+ // History: dario 3.2.7–3.4.3 once dropped this scope by mistake (misread
57
+ // of the "Console-only" name); 3.4.4 added it back after users hit auth
58
+ // failures with the dev client_id accepting it but prod rejecting. That
59
+ // situation has now inverted — prod rejects the longer list.
60
+ scopes: 'user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload',
57
61
  source: 'fallback',
58
62
  };
59
- // -v3 suffix invalidates v3.4.3 caches that were populated with the wrong
60
- // 4-scope list (the scanner's regex matched a help-message string literal
61
- // in the CC binary instead of the real scope array). See the scanner's
62
- // scope handling below for why scope detection is no longer attempted.
63
- const CACHE_PATH = join(homedir(), '.dario', 'cc-oauth-cache-v3.json');
63
+ // -v4 suffix invalidates v3.x caches populated with the 6-scope list that
64
+ // Anthropic now rejects (dario #42). On upgrade, users regenerate the cache
65
+ // with the new FALLBACK scopes automatically no manual clear required.
66
+ const CACHE_PATH = join(homedir(), '.dario', 'cc-oauth-cache-v4.json');
64
67
  function candidatePaths() {
65
68
  const home = homedir();
66
69
  if (platform() === 'win32') {
package/dist/cli.js CHANGED
@@ -54,8 +54,31 @@ async function login() {
54
54
  await proxy();
55
55
  return;
56
56
  }
57
- console.log(' No Claude Code credentials found. Starting OAuth flow...');
58
- console.log('');
57
+ // Credentials exist but are expired try refresh before falling through
58
+ // to a fresh OAuth flow. Without this, dario silently burned every
59
+ // fresh-login attempt (surfaced by dario #42 when Anthropic's authorize
60
+ // endpoint started rejecting the 6-scope list and `dario login` kept
61
+ // reporting "No credentials found" even though refresh would have worked).
62
+ if (creds?.claudeAiOauth?.refreshToken) {
63
+ console.log(' Existing credentials expired — attempting token refresh...');
64
+ try {
65
+ const tokens = await refreshTokens();
66
+ const expiresIn = Math.round((tokens.expiresAt - Date.now()) / 60000);
67
+ console.log(` Refresh successful! Token expires in ${expiresIn} minutes.`);
68
+ console.log('');
69
+ console.log(' Run `dario proxy` to start the API proxy.');
70
+ console.log('');
71
+ return;
72
+ }
73
+ catch (err) {
74
+ console.log(` Refresh failed (${sanitizeError(err)}). Starting fresh OAuth flow...`);
75
+ console.log('');
76
+ }
77
+ }
78
+ else {
79
+ console.log(' No Claude Code credentials found. Starting OAuth flow...');
80
+ console.log('');
81
+ }
59
82
  try {
60
83
  const tokens = await startAutoOAuthFlow();
61
84
  const expiresIn = Math.round((tokens.expiresAt - Date.now()) / 60000);
@@ -259,7 +259,7 @@ export declare function _resetInstalledVersionProbeForTest(): void;
259
259
  */
260
260
  export declare const SUPPORTED_CC_RANGE: {
261
261
  readonly min: "1.0.0";
262
- readonly maxTested: "2.1.104";
262
+ readonly maxTested: "2.1.112";
263
263
  };
264
264
  /**
265
265
  * Compare two dotted-numeric version strings. Returns negative if `a<b`,
@@ -695,7 +695,7 @@ export function _resetInstalledVersionProbeForTest() {
695
695
  */
696
696
  export const SUPPORTED_CC_RANGE = {
697
697
  min: '1.0.0',
698
- maxTested: '2.1.104',
698
+ maxTested: '2.1.112',
699
699
  };
700
700
  /**
701
701
  * 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": "3.19.3",
3
+ "version": "3.19.5",
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": {