@askalf/dario
Advanced tools
+33
-0
@@ -163,1 +163,34 @@ export interface AccountCredentials { | ||
| export declare function resyncLoginFromCredentialsIfStale(): Promise<'no-pool' | 'no-login' | 'no-creds' | 'in-sync' | 'resynced' | 'creds-stale'>; | ||
| /** | ||
| * Mirror the pool's freshly-refreshed `login` account token back into the | ||
| * legacy `~/.dario/credentials.json` store. dario#808. | ||
| * | ||
| * The divergence #805 fixed runs one way (credentials.json stale, login.json | ||
| * fresh) but left the two files diverged: the pool's refresh loop advances | ||
| * accounts/login.json while nothing ever writes credentials.json, so the | ||
| * legacy file stays frozen at the last `dario login`. Consequences: | ||
| * - `dario doctor` reads credentials.json for its OAuth row and prints | ||
| * 'expired'/'expiring' in pool-of-1 mode even when the live pool token is | ||
| * fresh and the fleet is 200-healthy — an alarm-inducing false positive. | ||
| * - any other reader of credentials.json (a co-resident Claude Code, an ops | ||
| * script) sees a stale token indefinitely. | ||
| * | ||
| * Fix: whenever the pool refreshes the `login` account, mirror the new token | ||
| * into credentials.json so the legacy file tracks the pool store. Only the | ||
| * `login` alias is mirrored — it's the one back-filled FROM credentials.json | ||
| * (ensureLoginCredentialsInPool), so it's the only account whose canonical | ||
| * home is that file; `work`/`personal` accounts have no legacy counterpart. | ||
| * | ||
| * Freshness-guarded, symmetric with #805: mirror only when the refreshed login | ||
| * token is strictly NEWER than the current credentials.json (by `expiresAt`). | ||
| * A newer-or-equal credentials.json means another process (e.g. a concurrent | ||
| * `dario login --force-reauth`) just wrote a fresher family — never clobber it; | ||
| * resyncLoginFromCredentialsIfStale pulls that direction on next startup. | ||
| * | ||
| * Best-effort: a mirror failure must never fail the refresh that produced the | ||
| * live token. Returns one of: | ||
| * - 'skip-not-login' : alias isn't the reserved `login` — nothing to mirror | ||
| * - 'mirrored' : credentials.json updated to the pool token | ||
| * - 'creds-newer' : credentials.json is newer-or-equal — left untouched | ||
| */ | ||
| export declare function mirrorLoginToCredentials(refreshed: AccountCredentials): Promise<'skip-not-login' | 'mirrored' | 'creds-newer'>; |
+51
-1
@@ -26,3 +26,3 @@ /** | ||
| import { detectCCOAuthConfig } from './cc-oauth-detect.js'; | ||
| import { loadCredentials, buildManualAuthorizeUrl, parseManualPaste, readLineFromStdin, enumerateKeychainCredentials } from './oauth.js'; | ||
| import { loadCredentials, saveCredentialsTokens, buildManualAuthorizeUrl, parseManualPaste, readLineFromStdin, enumerateKeychainCredentials } from './oauth.js'; | ||
| import { openBrowser } from './open-browser.js'; | ||
@@ -623,1 +623,51 @@ import { redactSecrets } from './redact.js'; | ||
| } | ||
| /** | ||
| * Mirror the pool's freshly-refreshed `login` account token back into the | ||
| * legacy `~/.dario/credentials.json` store. dario#808. | ||
| * | ||
| * The divergence #805 fixed runs one way (credentials.json stale, login.json | ||
| * fresh) but left the two files diverged: the pool's refresh loop advances | ||
| * accounts/login.json while nothing ever writes credentials.json, so the | ||
| * legacy file stays frozen at the last `dario login`. Consequences: | ||
| * - `dario doctor` reads credentials.json for its OAuth row and prints | ||
| * 'expired'/'expiring' in pool-of-1 mode even when the live pool token is | ||
| * fresh and the fleet is 200-healthy — an alarm-inducing false positive. | ||
| * - any other reader of credentials.json (a co-resident Claude Code, an ops | ||
| * script) sees a stale token indefinitely. | ||
| * | ||
| * Fix: whenever the pool refreshes the `login` account, mirror the new token | ||
| * into credentials.json so the legacy file tracks the pool store. Only the | ||
| * `login` alias is mirrored — it's the one back-filled FROM credentials.json | ||
| * (ensureLoginCredentialsInPool), so it's the only account whose canonical | ||
| * home is that file; `work`/`personal` accounts have no legacy counterpart. | ||
| * | ||
| * Freshness-guarded, symmetric with #805: mirror only when the refreshed login | ||
| * token is strictly NEWER than the current credentials.json (by `expiresAt`). | ||
| * A newer-or-equal credentials.json means another process (e.g. a concurrent | ||
| * `dario login --force-reauth`) just wrote a fresher family — never clobber it; | ||
| * resyncLoginFromCredentialsIfStale pulls that direction on next startup. | ||
| * | ||
| * Best-effort: a mirror failure must never fail the refresh that produced the | ||
| * live token. Returns one of: | ||
| * - 'skip-not-login' : alias isn't the reserved `login` — nothing to mirror | ||
| * - 'mirrored' : credentials.json updated to the pool token | ||
| * - 'creds-newer' : credentials.json is newer-or-equal — left untouched | ||
| */ | ||
| export async function mirrorLoginToCredentials(refreshed) { | ||
| if (refreshed.alias !== MIGRATED_LOGIN_ALIAS) | ||
| return 'skip-not-login'; | ||
| const creds = await loadCredentials(); | ||
| const currentExpiry = creds?.claudeAiOauth?.expiresAt ?? 0; | ||
| // Only mirror a strictly-newer pool token. Equal expiry means the files | ||
| // already agree (or a same-second write elsewhere); newer credentials.json | ||
| // is another process's fresher family we must not overwrite (#805 direction). | ||
| if (currentExpiry >= refreshed.expiresAt) | ||
| return 'creds-newer'; | ||
| await saveCredentialsTokens({ | ||
| accessToken: refreshed.accessToken, | ||
| refreshToken: refreshed.refreshToken, | ||
| expiresAt: refreshed.expiresAt, | ||
| scopes: refreshed.scopes ?? creds?.claudeAiOauth?.scopes ?? [], | ||
| }); | ||
| return 'mirrored'; | ||
| } |
+9
-0
@@ -77,2 +77,11 @@ /** | ||
| /** | ||
| * Mirror a set of OAuth tokens into the legacy `~/.dario/credentials.json` | ||
| * store. Thin durable-write wrapper over `saveCredentials` for callers outside | ||
| * this module — specifically the pool's login-account mirror (dario#808), which | ||
| * keeps credentials.json tracking the pool store after a background/startup | ||
| * refresh advanced `accounts/login.json`. Shares saveCredentials' durability | ||
| * (fsync temp + dir, #790), cache invalidation, and refresh-dead-flag clear. | ||
| */ | ||
| export declare function saveCredentialsTokens(tokens: OAuthTokens): Promise<void>; | ||
| /** | ||
| * Automatic OAuth flow using a local callback server (same as Claude Code). | ||
@@ -79,0 +88,0 @@ * Opens browser, captures the authorization code automatically. |
+11
-0
@@ -428,2 +428,13 @@ /** | ||
| /** | ||
| * Mirror a set of OAuth tokens into the legacy `~/.dario/credentials.json` | ||
| * store. Thin durable-write wrapper over `saveCredentials` for callers outside | ||
| * this module — specifically the pool's login-account mirror (dario#808), which | ||
| * keeps credentials.json tracking the pool store after a background/startup | ||
| * refresh advanced `accounts/login.json`. Shares saveCredentials' durability | ||
| * (fsync temp + dir, #790), cache invalidation, and refresh-dead-flag clear. | ||
| */ | ||
| export async function saveCredentialsTokens(tokens) { | ||
| await saveCredentials({ claudeAiOauth: tokens }); | ||
| } | ||
| /** | ||
| * Automatic OAuth flow using a local callback server (same as Claude Code). | ||
@@ -430,0 +441,0 @@ * Opens browser, captures the authorization code automatically. |
+1
-1
| { | ||
| "name": "@askalf/dario", | ||
| "version": "5.2.10", | ||
| "version": "5.2.11", | ||
| "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,0 +5,0 @@ "type": "module", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1431803
0.48%27672
0.43%123
-0.81%