Show session expiry warning in statusline
When the fetcher gets a 401/403, it writes an error state to the cache file instead of silently failing. The statusline reads this and shows "Token: session expired — refresh cookie" so the user knows to re-extract the sessionKey cookie from claude.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,13 @@ const CACHE_FILE = process.env.CLAUDE_USAGE_CACHE
|
|||||||
|| path.join(process.env.TMPDIR || '/tmp', 'claude_usage.json');
|
|| path.join(process.env.TMPDIR || '/tmp', 'claude_usage.json');
|
||||||
const ORG_ID = process.env.CLAUDE_ORG_ID || '';
|
const ORG_ID = process.env.CLAUDE_ORG_ID || '';
|
||||||
|
|
||||||
|
// --- Cache writer ---
|
||||||
|
function writeCache(data) {
|
||||||
|
const cacheDir = path.dirname(CACHE_FILE);
|
||||||
|
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
|
||||||
|
fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
// --- Session Key ---
|
// --- Session Key ---
|
||||||
function getSessionKey() {
|
function getSessionKey() {
|
||||||
// env var first
|
// env var first
|
||||||
@@ -52,7 +59,12 @@ async function getOrgId(sessionKey) {
|
|||||||
headers: headers(sessionKey),
|
headers: headers(sessionKey),
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
});
|
});
|
||||||
if (!resp.ok) throw new Error('Failed to list orgs: ' + resp.status);
|
if (!resp.ok) {
|
||||||
|
if (resp.status === 401 || resp.status === 403) {
|
||||||
|
writeCache({ _error: 'auth_expired', _status: resp.status });
|
||||||
|
}
|
||||||
|
throw new Error('Failed to list orgs: ' + resp.status);
|
||||||
|
}
|
||||||
const orgs = await resp.json();
|
const orgs = await resp.json();
|
||||||
if (!orgs.length) throw new Error('No organizations found');
|
if (!orgs.length) throw new Error('No organizations found');
|
||||||
return orgs[0].uuid;
|
return orgs[0].uuid;
|
||||||
@@ -85,19 +97,17 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
|
writeCache({ _error: resp.status === 401 || resp.status === 403
|
||||||
|
? 'auth_expired' : 'api_error', _status: resp.status });
|
||||||
console.error('API error: ' + resp.status);
|
console.error('API error: ' + resp.status);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
|
writeCache(data);
|
||||||
// Ensure cache dir exists
|
console.log('OK \u2014 wrote ' + CACHE_FILE);
|
||||||
const cacheDir = path.dirname(CACHE_FILE);
|
|
||||||
if (!fs.existsSync(cacheDir)) fs.mkdirSync(cacheDir, { recursive: true });
|
|
||||||
|
|
||||||
fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));
|
|
||||||
console.log('OK — wrote ' + CACHE_FILE);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
writeCache({ _error: 'fetch_failed', _message: e.message });
|
||||||
console.error('Fetch error: ' + e.message);
|
console.error('Fetch error: ' + e.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,12 @@ function readCache() {
|
|||||||
if (!fs.existsSync(CACHE_FILE)) return null;
|
if (!fs.existsSync(CACHE_FILE)) return null;
|
||||||
const stat = fs.statSync(CACHE_FILE);
|
const stat = fs.statSync(CACHE_FILE);
|
||||||
const ageS = (Date.now() - stat.mtimeMs) / 1000;
|
const ageS = (Date.now() - stat.mtimeMs) / 1000;
|
||||||
|
const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
|
||||||
|
// Error state written by fetcher — always show regardless of age
|
||||||
|
if (data._error) return data;
|
||||||
|
// Normal data — respect max age
|
||||||
if (ageS > CACHE_MAX_AGE_S) return null;
|
if (ageS > CACHE_MAX_AGE_S) return null;
|
||||||
return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
|
return data;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -60,6 +64,11 @@ function formatMinutes(isoStr) {
|
|||||||
|
|
||||||
function getUsagePart(data) {
|
function getUsagePart(data) {
|
||||||
if (!data) return '';
|
if (!data) return '';
|
||||||
|
|
||||||
|
// Error state from fetcher
|
||||||
|
if (data._error === 'auth_expired') return 'Token: session expired — refresh cookie';
|
||||||
|
if (data._error) return 'Token: fetch error';
|
||||||
|
|
||||||
const parts = [];
|
const parts = [];
|
||||||
|
|
||||||
if (data.five_hour && data.five_hour.utilization > 0) {
|
if (data.five_hour && data.five_hour.utilization > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user