import type { StdinData } from './types.js'; import { AUTOCOMPACT_BUFFER_PERCENT } from './constants.js'; export async function readStdin(): Promise { if (process.stdin.isTTY) { return null; } const chunks: string[] = []; try { process.stdin.setEncoding('utf8'); for await (const chunk of process.stdin) { chunks.push(chunk as string); } const raw = chunks.join(''); if (!raw.trim()) { return null; } return JSON.parse(raw) as StdinData; } catch { return null; } } function getTotalTokens(stdin: StdinData): number { const usage = stdin.context_window?.current_usage; return ( (usage?.input_tokens ?? 0) + (usage?.cache_creation_input_tokens ?? 0) + (usage?.cache_read_input_tokens ?? 0) ); } /** * Get native percentage from Claude Code v2.1.6+ if available. * Returns null if not available or invalid, triggering fallback to manual calculation. */ function getNativePercent(stdin: StdinData): number | null { const nativePercent = stdin.context_window?.used_percentage; if (typeof nativePercent === 'number' && !Number.isNaN(nativePercent)) { return Math.min(100, Math.max(0, Math.round(nativePercent))); } return null; } export function getContextPercent(stdin: StdinData): number { // Prefer native percentage (v2.1.6+) - accurate and matches /context const native = getNativePercent(stdin); if (native !== null) { return native; } // Fallback: manual calculation without buffer const size = stdin.context_window?.context_window_size; if (!size || size <= 0) { return 0; } const totalTokens = getTotalTokens(stdin); return Math.min(100, Math.round((totalTokens / size) * 100)); } export function getBufferedPercent(stdin: StdinData): number { // Prefer native percentage (v2.1.6+) - accurate and matches /context // Native percentage already accounts for context correctly, no buffer needed const native = getNativePercent(stdin); if (native !== null) { return native; } // Fallback: manual calculation with buffer for older Claude Code versions const size = stdin.context_window?.context_window_size; if (!size || size <= 0) { return 0; } const totalTokens = getTotalTokens(stdin); const buffer = size * AUTOCOMPACT_BUFFER_PERCENT; return Math.min(100, Math.round(((totalTokens + buffer) / size) * 100)); } export function getModelName(stdin: StdinData): string { return stdin.model?.display_name ?? stdin.model?.id ?? 'Unknown'; }