diff --git a/dist/claude-config-dir.d.ts b/dist/claude-config-dir.d.ts new file mode 100644 index 0000000..99f7599 --- /dev/null +++ b/dist/claude-config-dir.d.ts @@ -0,0 +1,4 @@ +export declare function getClaudeConfigDir(homeDir: string): string; +export declare function getClaudeConfigJsonPath(homeDir: string): string; +export declare function getHudPluginDir(homeDir: string): string; +//# sourceMappingURL=claude-config-dir.d.ts.map \ No newline at end of file diff --git a/dist/claude-config-dir.d.ts.map b/dist/claude-config-dir.d.ts.map new file mode 100644 index 0000000..a4bb152 --- /dev/null +++ b/dist/claude-config-dir.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"claude-config-dir.d.ts","sourceRoot":"","sources":["../src/claude-config-dir.ts"],"names":[],"mappings":"AAYA,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD"} \ No newline at end of file diff --git a/dist/claude-config-dir.js b/dist/claude-config-dir.js new file mode 100644 index 0000000..ab6e334 --- /dev/null +++ b/dist/claude-config-dir.js @@ -0,0 +1,24 @@ +import * as path from 'node:path'; +function expandHomeDirPrefix(inputPath, homeDir) { + if (inputPath === '~') { + return homeDir; + } + if (inputPath.startsWith('~/') || inputPath.startsWith('~\\')) { + return path.join(homeDir, inputPath.slice(2)); + } + return inputPath; +} +export function getClaudeConfigDir(homeDir) { + const envConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim(); + if (!envConfigDir) { + return path.join(homeDir, '.claude'); + } + return path.resolve(expandHomeDirPrefix(envConfigDir, homeDir)); +} +export function getClaudeConfigJsonPath(homeDir) { + return `${getClaudeConfigDir(homeDir)}.json`; +} +export function getHudPluginDir(homeDir) { + return path.join(getClaudeConfigDir(homeDir), 'plugins', 'claude-hud'); +} +//# sourceMappingURL=claude-config-dir.js.map \ No newline at end of file diff --git a/dist/claude-config-dir.js.map b/dist/claude-config-dir.js.map new file mode 100644 index 0000000..94361a4 --- /dev/null +++ b/dist/claude-config-dir.js.map @@ -0,0 +1 @@ +{"version":3,"file":"claude-config-dir.js","sourceRoot":"","sources":["../src/claude-config-dir.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,SAAS,mBAAmB,CAAC,SAAiB,EAAE,OAAe;IAC7D,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AACzE,CAAC"} \ No newline at end of file diff --git a/dist/config-reader.d.ts b/dist/config-reader.d.ts new file mode 100644 index 0000000..b6d88c9 --- /dev/null +++ b/dist/config-reader.d.ts @@ -0,0 +1,8 @@ +export interface ConfigCounts { + claudeMdCount: number; + rulesCount: number; + mcpCount: number; + hooksCount: number; +} +export declare function countConfigs(cwd?: string): Promise; +//# sourceMappingURL=config-reader.d.ts.map \ No newline at end of file diff --git a/dist/config-reader.d.ts.map b/dist/config-reader.d.ts.map new file mode 100644 index 0000000..9fca571 --- /dev/null +++ b/dist/config-reader.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config-reader.d.ts","sourceRoot":"","sources":["../src/config-reader.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AA4GD,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkHtE"} \ No newline at end of file diff --git a/dist/config-reader.js b/dist/config-reader.js new file mode 100644 index 0000000..6462d95 --- /dev/null +++ b/dist/config-reader.js @@ -0,0 +1,204 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { createDebug } from './debug.js'; +import { getClaudeConfigDir, getClaudeConfigJsonPath } from './claude-config-dir.js'; +const debug = createDebug('config'); +function getMcpServerNames(filePath) { + if (!fs.existsSync(filePath)) + return new Set(); + try { + const content = fs.readFileSync(filePath, 'utf8'); + const config = JSON.parse(content); + if (config.mcpServers && typeof config.mcpServers === 'object') { + return new Set(Object.keys(config.mcpServers)); + } + } + catch (error) { + debug(`Failed to read MCP servers from ${filePath}:`, error); + } + return new Set(); +} +function getDisabledMcpServers(filePath, key) { + if (!fs.existsSync(filePath)) + return new Set(); + try { + const content = fs.readFileSync(filePath, 'utf8'); + const config = JSON.parse(content); + if (Array.isArray(config[key])) { + const validNames = config[key].filter((s) => typeof s === 'string'); + if (validNames.length !== config[key].length) { + debug(`${key} in ${filePath} contains non-string values, ignoring them`); + } + return new Set(validNames); + } + } + catch (error) { + debug(`Failed to read ${key} from ${filePath}:`, error); + } + return new Set(); +} +function countMcpServersInFile(filePath, excludeFrom) { + const servers = getMcpServerNames(filePath); + if (excludeFrom) { + const exclude = getMcpServerNames(excludeFrom); + for (const name of exclude) { + servers.delete(name); + } + } + return servers.size; +} +function countHooksInFile(filePath) { + if (!fs.existsSync(filePath)) + return 0; + try { + const content = fs.readFileSync(filePath, 'utf8'); + const config = JSON.parse(content); + if (config.hooks && typeof config.hooks === 'object') { + return Object.keys(config.hooks).length; + } + } + catch (error) { + debug(`Failed to read hooks from ${filePath}:`, error); + } + return 0; +} +function countRulesInDir(rulesDir) { + if (!fs.existsSync(rulesDir)) + return 0; + let count = 0; + try { + const entries = fs.readdirSync(rulesDir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(rulesDir, entry.name); + if (entry.isDirectory()) { + count += countRulesInDir(fullPath); + } + else if (entry.isFile() && entry.name.endsWith('.md')) { + count++; + } + } + } + catch (error) { + debug(`Failed to read rules from ${rulesDir}:`, error); + } + return count; +} +function normalizePathForComparison(inputPath) { + let normalized = path.normalize(path.resolve(inputPath)); + const root = path.parse(normalized).root; + while (normalized.length > root.length && normalized.endsWith(path.sep)) { + normalized = normalized.slice(0, -1); + } + return process.platform === 'win32' ? normalized.toLowerCase() : normalized; +} +function pathsReferToSameLocation(pathA, pathB) { + if (normalizePathForComparison(pathA) === normalizePathForComparison(pathB)) { + return true; + } + if (!fs.existsSync(pathA) || !fs.existsSync(pathB)) { + return false; + } + try { + const realPathA = fs.realpathSync.native(pathA); + const realPathB = fs.realpathSync.native(pathB); + return normalizePathForComparison(realPathA) === normalizePathForComparison(realPathB); + } + catch { + return false; + } +} +export async function countConfigs(cwd) { + let claudeMdCount = 0; + let rulesCount = 0; + let hooksCount = 0; + const homeDir = os.homedir(); + const claudeDir = getClaudeConfigDir(homeDir); + // Collect all MCP servers across scopes, then subtract disabled ones + const userMcpServers = new Set(); + const projectMcpServers = new Set(); + // === USER SCOPE === + // ~/.claude/CLAUDE.md + if (fs.existsSync(path.join(claudeDir, 'CLAUDE.md'))) { + claudeMdCount++; + } + // ~/.claude/rules/*.md + rulesCount += countRulesInDir(path.join(claudeDir, 'rules')); + // ~/.claude/settings.json (MCPs and hooks) + const userSettings = path.join(claudeDir, 'settings.json'); + for (const name of getMcpServerNames(userSettings)) { + userMcpServers.add(name); + } + hooksCount += countHooksInFile(userSettings); + // {CLAUDE_CONFIG_DIR}.json (additional user-scope MCPs) + const userClaudeJson = getClaudeConfigJsonPath(homeDir); + for (const name of getMcpServerNames(userClaudeJson)) { + userMcpServers.add(name); + } + // Get disabled user-scope MCPs from ~/.claude.json + const disabledUserMcps = getDisabledMcpServers(userClaudeJson, 'disabledMcpServers'); + for (const name of disabledUserMcps) { + userMcpServers.delete(name); + } + // === PROJECT SCOPE === + // Avoid double-counting when project .claude directory is the same location as user scope. + const projectClaudeDir = cwd ? path.join(cwd, '.claude') : null; + const projectClaudeOverlapsUserScope = projectClaudeDir + ? pathsReferToSameLocation(projectClaudeDir, claudeDir) + : false; + if (cwd) { + // {cwd}/CLAUDE.md + if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) { + claudeMdCount++; + } + // {cwd}/CLAUDE.local.md + if (fs.existsSync(path.join(cwd, 'CLAUDE.local.md'))) { + claudeMdCount++; + } + // {cwd}/.claude/CLAUDE.md (alternative location, skip when it is user scope) + if (!projectClaudeOverlapsUserScope && fs.existsSync(path.join(cwd, '.claude', 'CLAUDE.md'))) { + claudeMdCount++; + } + // {cwd}/.claude/CLAUDE.local.md + if (fs.existsSync(path.join(cwd, '.claude', 'CLAUDE.local.md'))) { + claudeMdCount++; + } + // {cwd}/.claude/rules/*.md (recursive) + // Skip when it overlaps with user-scope rules. + if (!projectClaudeOverlapsUserScope) { + rulesCount += countRulesInDir(path.join(cwd, '.claude', 'rules')); + } + // {cwd}/.mcp.json (project MCP config) - tracked separately for disabled filtering + const mcpJsonServers = getMcpServerNames(path.join(cwd, '.mcp.json')); + // {cwd}/.claude/settings.json (project settings) + // Skip when it overlaps with user-scope settings. + const projectSettings = path.join(cwd, '.claude', 'settings.json'); + if (!projectClaudeOverlapsUserScope) { + for (const name of getMcpServerNames(projectSettings)) { + projectMcpServers.add(name); + } + hooksCount += countHooksInFile(projectSettings); + } + // {cwd}/.claude/settings.local.json (local project settings) + const localSettings = path.join(cwd, '.claude', 'settings.local.json'); + for (const name of getMcpServerNames(localSettings)) { + projectMcpServers.add(name); + } + hooksCount += countHooksInFile(localSettings); + // Get disabled .mcp.json servers from settings.local.json + const disabledMcpJsonServers = getDisabledMcpServers(localSettings, 'disabledMcpjsonServers'); + for (const name of disabledMcpJsonServers) { + mcpJsonServers.delete(name); + } + // Add remaining .mcp.json servers to project set + for (const name of mcpJsonServers) { + projectMcpServers.add(name); + } + } + // Total MCP count = user servers + project servers + // Note: Deduplication only occurs within each scope, not across scopes. + // A server with the same name in both user and project scope counts as 2 (separate configs). + const mcpCount = userMcpServers.size + projectMcpServers.size; + return { claudeMdCount, rulesCount, mcpCount, hooksCount }; +} +//# sourceMappingURL=config-reader.js.map \ No newline at end of file diff --git a/dist/config-reader.js.map b/dist/config-reader.js.map new file mode 100644 index 0000000..835a7f1 --- /dev/null +++ b/dist/config-reader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config-reader.js","sourceRoot":"","sources":["../src/config-reader.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/config.d.ts b/dist/config.d.ts new file mode 100644 index 0000000..5a68abe --- /dev/null +++ b/dist/config.d.ts @@ -0,0 +1,55 @@ +export type LineLayoutType = 'compact' | 'expanded'; +export type AutocompactBufferMode = 'enabled' | 'disabled'; +export type ContextValueMode = 'percent' | 'tokens' | 'remaining'; +export type HudElement = 'project' | 'context' | 'usage' | 'environment' | 'tools' | 'agents' | 'todos'; +export type HudColorName = 'red' | 'green' | 'yellow' | 'magenta' | 'cyan' | 'brightBlue' | 'brightMagenta'; +export interface HudColorOverrides { + context: HudColorName; + usage: HudColorName; + warning: HudColorName; + usageWarning: HudColorName; + critical: HudColorName; +} +export declare const DEFAULT_ELEMENT_ORDER: HudElement[]; +export interface HudConfig { + lineLayout: LineLayoutType; + showSeparators: boolean; + pathLevels: 1 | 2 | 3; + elementOrder: HudElement[]; + gitStatus: { + enabled: boolean; + showDirty: boolean; + showAheadBehind: boolean; + showFileStats: boolean; + }; + display: { + showModel: boolean; + showProject: boolean; + showContextBar: boolean; + contextValue: ContextValueMode; + showConfigCounts: boolean; + showDuration: boolean; + showSpeed: boolean; + showTokenBreakdown: boolean; + showUsage: boolean; + usageBarEnabled: boolean; + showTools: boolean; + showAgents: boolean; + showTodos: boolean; + showSessionName: boolean; + autocompactBuffer: AutocompactBufferMode; + usageThreshold: number; + sevenDayThreshold: number; + environmentThreshold: number; + }; + usage: { + cacheTtlSeconds: number; + failureCacheTtlSeconds: number; + }; + colors: HudColorOverrides; +} +export declare const DEFAULT_CONFIG: HudConfig; +export declare function getConfigPath(): string; +export declare function mergeConfig(userConfig: Partial): HudConfig; +export declare function loadConfig(): Promise; +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/dist/config.d.ts.map b/dist/config.d.ts.map new file mode 100644 index 0000000..921ab50 --- /dev/null +++ b/dist/config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC;AAEpD,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,UAAU,CAAC;AAC3D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAClE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AACxG,MAAM,MAAM,YAAY,GACpB,KAAK,GACL,OAAO,GACP,QAAQ,GACR,SAAS,GACT,MAAM,GACN,YAAY,GACZ,eAAe,CAAC;AAEpB,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,eAAO,MAAM,qBAAqB,EAAE,UAAU,EAQ7C,CAAC;AAIF,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,cAAc,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;QACzB,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,OAAO,EAAE;QACP,SAAS,EAAE,OAAO,CAAC;QACnB,WAAW,EAAE,OAAO,CAAC;QACrB,cAAc,EAAE,OAAO,CAAC;QACxB,YAAY,EAAE,gBAAgB,CAAC;QAC/B,gBAAgB,EAAE,OAAO,CAAC;QAC1B,YAAY,EAAE,OAAO,CAAC;QACtB,SAAS,EAAE,OAAO,CAAC;QACnB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;QACzB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;QACzB,iBAAiB,EAAE,qBAAqB,CAAC;QACzC,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,KAAK,EAAE;QACL,eAAe,EAAE,MAAM,CAAC;QACxB,sBAAsB,EAAE,MAAM,CAAC;KAChC,CAAC;IACF,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,eAAO,MAAM,cAAc,EAAE,SA0C5B,CAAC;AAEF,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AA6FD,wBAAgB,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAiHrE;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAcrD"} \ No newline at end of file diff --git a/dist/config.js b/dist/config.js new file mode 100644 index 0000000..460b34c --- /dev/null +++ b/dist/config.js @@ -0,0 +1,253 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import * as os from 'node:os'; +import { getHudPluginDir } from './claude-config-dir.js'; +export const DEFAULT_ELEMENT_ORDER = [ + 'project', + 'context', + 'usage', + 'environment', + 'tools', + 'agents', + 'todos', +]; +const KNOWN_ELEMENTS = new Set(DEFAULT_ELEMENT_ORDER); +export const DEFAULT_CONFIG = { + lineLayout: 'expanded', + showSeparators: false, + pathLevels: 1, + elementOrder: [...DEFAULT_ELEMENT_ORDER], + gitStatus: { + enabled: true, + showDirty: true, + showAheadBehind: false, + showFileStats: false, + }, + display: { + showModel: true, + showProject: true, + showContextBar: true, + contextValue: 'percent', + showConfigCounts: false, + showDuration: false, + showSpeed: false, + showTokenBreakdown: true, + showUsage: true, + usageBarEnabled: true, + showTools: false, + showAgents: false, + showTodos: false, + showSessionName: false, + autocompactBuffer: 'enabled', + usageThreshold: 0, + sevenDayThreshold: 80, + environmentThreshold: 0, + }, + usage: { + cacheTtlSeconds: 60, + failureCacheTtlSeconds: 15, + }, + colors: { + context: 'green', + usage: 'brightBlue', + warning: 'yellow', + usageWarning: 'brightMagenta', + critical: 'red', + }, +}; +export function getConfigPath() { + const homeDir = os.homedir(); + return path.join(getHudPluginDir(homeDir), 'config.json'); +} +function validatePathLevels(value) { + return value === 1 || value === 2 || value === 3; +} +function validateLineLayout(value) { + return value === 'compact' || value === 'expanded'; +} +function validateAutocompactBuffer(value) { + return value === 'enabled' || value === 'disabled'; +} +function validateContextValue(value) { + return value === 'percent' || value === 'tokens' || value === 'remaining'; +} +function validateColorName(value) { + return value === 'red' + || value === 'green' + || value === 'yellow' + || value === 'magenta' + || value === 'cyan' + || value === 'brightBlue' + || value === 'brightMagenta'; +} +function validateElementOrder(value) { + if (!Array.isArray(value) || value.length === 0) { + return [...DEFAULT_ELEMENT_ORDER]; + } + const seen = new Set(); + const elementOrder = []; + for (const item of value) { + if (typeof item !== 'string' || !KNOWN_ELEMENTS.has(item)) { + continue; + } + const element = item; + if (seen.has(element)) { + continue; + } + seen.add(element); + elementOrder.push(element); + } + return elementOrder.length > 0 ? elementOrder : [...DEFAULT_ELEMENT_ORDER]; +} +function migrateConfig(userConfig) { + const migrated = { ...userConfig }; + if ('layout' in userConfig && !('lineLayout' in userConfig)) { + if (typeof userConfig.layout === 'string') { + // Legacy string migration (v0.0.x → v0.1.x) + if (userConfig.layout === 'separators') { + migrated.lineLayout = 'compact'; + migrated.showSeparators = true; + } + else { + migrated.lineLayout = 'compact'; + migrated.showSeparators = false; + } + } + else if (typeof userConfig.layout === 'object' && userConfig.layout !== null) { + // Object layout written by third-party tools — extract nested fields + const obj = userConfig.layout; + if (typeof obj.lineLayout === 'string') + migrated.lineLayout = obj.lineLayout; + if (typeof obj.showSeparators === 'boolean') + migrated.showSeparators = obj.showSeparators; + if (typeof obj.pathLevels === 'number') + migrated.pathLevels = obj.pathLevels; + } + delete migrated.layout; + } + return migrated; +} +function validateThreshold(value, max = 100) { + if (typeof value !== 'number') + return 0; + return Math.max(0, Math.min(max, value)); +} +function validatePositiveInt(value, defaultValue) { + if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) + return defaultValue; + return value; +} +export function mergeConfig(userConfig) { + const migrated = migrateConfig(userConfig); + const lineLayout = validateLineLayout(migrated.lineLayout) + ? migrated.lineLayout + : DEFAULT_CONFIG.lineLayout; + const showSeparators = typeof migrated.showSeparators === 'boolean' + ? migrated.showSeparators + : DEFAULT_CONFIG.showSeparators; + const pathLevels = validatePathLevels(migrated.pathLevels) + ? migrated.pathLevels + : DEFAULT_CONFIG.pathLevels; + const elementOrder = validateElementOrder(migrated.elementOrder); + const gitStatus = { + enabled: typeof migrated.gitStatus?.enabled === 'boolean' + ? migrated.gitStatus.enabled + : DEFAULT_CONFIG.gitStatus.enabled, + showDirty: typeof migrated.gitStatus?.showDirty === 'boolean' + ? migrated.gitStatus.showDirty + : DEFAULT_CONFIG.gitStatus.showDirty, + showAheadBehind: typeof migrated.gitStatus?.showAheadBehind === 'boolean' + ? migrated.gitStatus.showAheadBehind + : DEFAULT_CONFIG.gitStatus.showAheadBehind, + showFileStats: typeof migrated.gitStatus?.showFileStats === 'boolean' + ? migrated.gitStatus.showFileStats + : DEFAULT_CONFIG.gitStatus.showFileStats, + }; + const display = { + showModel: typeof migrated.display?.showModel === 'boolean' + ? migrated.display.showModel + : DEFAULT_CONFIG.display.showModel, + showProject: typeof migrated.display?.showProject === 'boolean' + ? migrated.display.showProject + : DEFAULT_CONFIG.display.showProject, + showContextBar: typeof migrated.display?.showContextBar === 'boolean' + ? migrated.display.showContextBar + : DEFAULT_CONFIG.display.showContextBar, + contextValue: validateContextValue(migrated.display?.contextValue) + ? migrated.display.contextValue + : DEFAULT_CONFIG.display.contextValue, + showConfigCounts: typeof migrated.display?.showConfigCounts === 'boolean' + ? migrated.display.showConfigCounts + : DEFAULT_CONFIG.display.showConfigCounts, + showDuration: typeof migrated.display?.showDuration === 'boolean' + ? migrated.display.showDuration + : DEFAULT_CONFIG.display.showDuration, + showSpeed: typeof migrated.display?.showSpeed === 'boolean' + ? migrated.display.showSpeed + : DEFAULT_CONFIG.display.showSpeed, + showTokenBreakdown: typeof migrated.display?.showTokenBreakdown === 'boolean' + ? migrated.display.showTokenBreakdown + : DEFAULT_CONFIG.display.showTokenBreakdown, + showUsage: typeof migrated.display?.showUsage === 'boolean' + ? migrated.display.showUsage + : DEFAULT_CONFIG.display.showUsage, + usageBarEnabled: typeof migrated.display?.usageBarEnabled === 'boolean' + ? migrated.display.usageBarEnabled + : DEFAULT_CONFIG.display.usageBarEnabled, + showTools: typeof migrated.display?.showTools === 'boolean' + ? migrated.display.showTools + : DEFAULT_CONFIG.display.showTools, + showAgents: typeof migrated.display?.showAgents === 'boolean' + ? migrated.display.showAgents + : DEFAULT_CONFIG.display.showAgents, + showTodos: typeof migrated.display?.showTodos === 'boolean' + ? migrated.display.showTodos + : DEFAULT_CONFIG.display.showTodos, + showSessionName: typeof migrated.display?.showSessionName === 'boolean' + ? migrated.display.showSessionName + : DEFAULT_CONFIG.display.showSessionName, + autocompactBuffer: validateAutocompactBuffer(migrated.display?.autocompactBuffer) + ? migrated.display.autocompactBuffer + : DEFAULT_CONFIG.display.autocompactBuffer, + usageThreshold: validateThreshold(migrated.display?.usageThreshold, 100), + sevenDayThreshold: validateThreshold(migrated.display?.sevenDayThreshold, 100), + environmentThreshold: validateThreshold(migrated.display?.environmentThreshold, 100), + }; + const usage = { + cacheTtlSeconds: validatePositiveInt(migrated.usage?.cacheTtlSeconds, DEFAULT_CONFIG.usage.cacheTtlSeconds), + failureCacheTtlSeconds: validatePositiveInt(migrated.usage?.failureCacheTtlSeconds, DEFAULT_CONFIG.usage.failureCacheTtlSeconds), + }; + const colors = { + context: validateColorName(migrated.colors?.context) + ? migrated.colors.context + : DEFAULT_CONFIG.colors.context, + usage: validateColorName(migrated.colors?.usage) + ? migrated.colors.usage + : DEFAULT_CONFIG.colors.usage, + warning: validateColorName(migrated.colors?.warning) + ? migrated.colors.warning + : DEFAULT_CONFIG.colors.warning, + usageWarning: validateColorName(migrated.colors?.usageWarning) + ? migrated.colors.usageWarning + : DEFAULT_CONFIG.colors.usageWarning, + critical: validateColorName(migrated.colors?.critical) + ? migrated.colors.critical + : DEFAULT_CONFIG.colors.critical, + }; + return { lineLayout, showSeparators, pathLevels, elementOrder, gitStatus, display, usage, colors }; +} +export async function loadConfig() { + const configPath = getConfigPath(); + try { + if (!fs.existsSync(configPath)) { + return DEFAULT_CONFIG; + } + const content = fs.readFileSync(configPath, 'utf-8'); + const userConfig = JSON.parse(content); + return mergeConfig(userConfig); + } + catch { + return DEFAULT_CONFIG; + } +} +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/dist/config.js.map b/dist/config.js.map new file mode 100644 index 0000000..a53fd53 --- /dev/null +++ b/dist/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAwBzD,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,SAAS;IACT,SAAS;IACT,OAAO;IACP,aAAa;IACb,OAAO;IACP,QAAQ;IACR,OAAO;CACR,CAAC;AAEF,MAAM,cAAc,GAAG,IAAI,GAAG,CAAa,qBAAqB,CAAC,CAAC;AAwClE,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,UAAU,EAAE,UAAU;IACtB,cAAc,EAAE,KAAK;IACrB,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,CAAC,GAAG,qBAAqB,CAAC;IACxC,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,KAAK;KACrB;IACD,OAAO,EAAE;QACP,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,IAAI;QACjB,cAAc,EAAE,IAAI;QACpB,YAAY,EAAE,SAAS;QACvB,gBAAgB,EAAE,KAAK;QACvB,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,KAAK;QAChB,kBAAkB,EAAE,IAAI;QACxB,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,IAAI;QACrB,SAAS,EAAE,KAAK;QAChB,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,KAAK;QAChB,eAAe,EAAE,KAAK;QACtB,iBAAiB,EAAE,SAAS;QAC5B,cAAc,EAAE,CAAC;QACjB,iBAAiB,EAAE,EAAE;QACrB,oBAAoB,EAAE,CAAC;KACxB;IACD,KAAK,EAAE;QACL,eAAe,EAAE,EAAE;QACnB,sBAAsB,EAAE,EAAE;KAC3B;IACD,MAAM,EAAE;QACN,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,QAAQ;QACjB,YAAY,EAAE,eAAe;QAC7B,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,OAAO,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,UAAU,CAAC;AACrD,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAC/C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,UAAU,CAAC;AACrD,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,WAAW,CAAC;AAC5E,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,OAAO,KAAK,KAAK,KAAK;WACjB,KAAK,KAAK,OAAO;WACjB,KAAK,KAAK,QAAQ;WAClB,KAAK,KAAK,SAAS;WACnB,KAAK,KAAK,MAAM;WAChB,KAAK,KAAK,YAAY;WACtB,KAAK,KAAK,eAAe,CAAC;AACjC,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,qBAAqB,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;IACnC,MAAM,YAAY,GAAiB,EAAE,CAAC;IAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAkB,CAAC,EAAE,CAAC;YACxE,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,IAAkB,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACtB,SAAS;QACX,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC;AAC7E,CAAC;AAMD,SAAS,aAAa,CAAC,UAA6C;IAClE,MAAM,QAAQ,GAAG,EAAE,GAAG,UAAU,EAAuC,CAAC;IAExE,IAAI,QAAQ,IAAI,UAAU,IAAI,CAAC,CAAC,YAAY,IAAI,UAAU,CAAC,EAAE,CAAC;QAC5D,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,4CAA4C;YAC5C,IAAI,UAAU,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;gBACvC,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;gBAChC,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;gBAChC,QAAQ,CAAC,cAAc,GAAG,KAAK,CAAC;YAClC,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAC/E,qEAAqE;YACrE,MAAM,GAAG,GAAG,UAAU,CAAC,MAAiC,CAAC;YACzD,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;gBAAE,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC,UAAiB,CAAC;YACpF,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,SAAS;gBAAE,QAAQ,CAAC,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC;YAC1F,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;gBAAE,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC,UAAiB,CAAC;QACtF,CAAC;QACD,OAAO,QAAQ,CAAC,MAAM,CAAC;IACzB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,GAAG,GAAG,GAAG;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAE,YAAoB;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,YAAY,CAAC;IAC7F,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,UAA8B;IACxD,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAE3C,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC;QACxD,CAAC,CAAC,QAAQ,CAAC,UAAU;QACrB,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC;IAE9B,MAAM,cAAc,GAAG,OAAO,QAAQ,CAAC,cAAc,KAAK,SAAS;QACjE,CAAC,CAAC,QAAQ,CAAC,cAAc;QACzB,CAAC,CAAC,cAAc,CAAC,cAAc,CAAC;IAElC,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC;QACxD,CAAC,CAAC,QAAQ,CAAC,UAAU;QACrB,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC;IAE9B,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAEjE,MAAM,SAAS,GAAG;QAChB,OAAO,EAAE,OAAO,QAAQ,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS;YACvD,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO;YAC5B,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,OAAO;QACpC,SAAS,EAAE,OAAO,QAAQ,CAAC,SAAS,EAAE,SAAS,KAAK,SAAS;YAC3D,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS;YAC9B,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,SAAS;QACtC,eAAe,EAAE,OAAO,QAAQ,CAAC,SAAS,EAAE,eAAe,KAAK,SAAS;YACvE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,eAAe;YACpC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,eAAe;QAC5C,aAAa,EAAE,OAAO,QAAQ,CAAC,SAAS,EAAE,aAAa,KAAK,SAAS;YACnE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,aAAa;YAClC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,aAAa;KAC3C,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,SAAS,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YACzD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;YAC5B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS;QACpC,WAAW,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,WAAW,KAAK,SAAS;YAC7D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW;YAC9B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW;QACtC,cAAc,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS;YACnE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc;YACjC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,cAAc;QACzC,YAAY,EAAE,oBAAoB,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;YAChE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY;YAC/B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,YAAY;QACvC,gBAAgB,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,gBAAgB,KAAK,SAAS;YACvE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB;YACnC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,gBAAgB;QAC3C,YAAY,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,YAAY,KAAK,SAAS;YAC/D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY;YAC/B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,YAAY;QACvC,SAAS,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YACzD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;YAC5B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS;QACpC,kBAAkB,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,kBAAkB,KAAK,SAAS;YAC3E,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,kBAAkB;YACrC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,kBAAkB;QAC7C,SAAS,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YACzD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;YAC5B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS;QACpC,eAAe,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,eAAe,KAAK,SAAS;YACrE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe;YAClC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe;QAC1C,SAAS,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YACzD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;YAC5B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS;QACpC,UAAU,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,UAAU,KAAK,SAAS;YAC3D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU;YAC7B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU;QACrC,SAAS,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS;YACzD,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS;YAC5B,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS;QACpC,eAAe,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,eAAe,KAAK,SAAS;YACrE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe;YAClC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,eAAe;QAC1C,iBAAiB,EAAE,yBAAyB,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;YAC/E,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAiB;YACpC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,iBAAiB;QAC5C,cAAc,EAAE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,CAAC;QACxE,iBAAiB,EAAE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,CAAC;QAC9E,oBAAoB,EAAE,iBAAiB,CAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,CAAC;KACrF,CAAC;IAEF,MAAM,KAAK,GAAG;QACZ,eAAe,EAAE,mBAAmB,CAClC,QAAQ,CAAC,KAAK,EAAE,eAAe,EAC/B,cAAc,CAAC,KAAK,CAAC,eAAe,CACrC;QACD,sBAAsB,EAAE,mBAAmB,CACzC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EACtC,cAAc,CAAC,KAAK,CAAC,sBAAsB,CAC5C;KACF,CAAC;IAEF,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;YAClD,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO;YACzB,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO;QACjC,KAAK,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;YAC9C,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK;YACvB,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK;QAC/B,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;YAClD,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO;YACzB,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO;QACjC,YAAY,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;YAC5D,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY;YAC9B,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,YAAY;QACtC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;YACpD,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ;YAC1B,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ;KACnC,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACrG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAuB,CAAC;QAC7D,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/constants.d.ts b/dist/constants.d.ts new file mode 100644 index 0000000..02a8411 --- /dev/null +++ b/dist/constants.d.ts @@ -0,0 +1,11 @@ +/** + * Autocompact buffer percentage. + * + * NOTE: This value is applied as a percentage of Claude Code's reported + * context window size. The `33k/200k` example is just the 200k-window case. + * It is empirically derived from current Claude Code `/context` output, is + * not officially documented by Anthropic, and may need adjustment if users + * report mismatches in future Claude Code versions. + */ +export declare const AUTOCOMPACT_BUFFER_PERCENT = 0.165; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/constants.d.ts.map b/dist/constants.d.ts.map new file mode 100644 index 0000000..e46746f --- /dev/null +++ b/dist/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,QAAQ,CAAC"} \ No newline at end of file diff --git a/dist/constants.js b/dist/constants.js new file mode 100644 index 0000000..6a4179b --- /dev/null +++ b/dist/constants.js @@ -0,0 +1,11 @@ +/** + * Autocompact buffer percentage. + * + * NOTE: This value is applied as a percentage of Claude Code's reported + * context window size. The `33k/200k` example is just the 200k-window case. + * It is empirically derived from current Claude Code `/context` output, is + * not officially documented by Anthropic, and may need adjustment if users + * report mismatches in future Claude Code versions. + */ +export const AUTOCOMPACT_BUFFER_PERCENT = 0.165; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/constants.js.map b/dist/constants.js.map new file mode 100644 index 0000000..0814a4c --- /dev/null +++ b/dist/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC"} \ No newline at end of file diff --git a/dist/debug.d.ts b/dist/debug.d.ts new file mode 100644 index 0000000..542ae24 --- /dev/null +++ b/dist/debug.d.ts @@ -0,0 +1,6 @@ +/** + * Create a namespaced debug logger + * @param namespace - Tag for log messages (e.g., 'config', 'usage') + */ +export declare function createDebug(namespace: string): (msg: string, ...args: unknown[]) => void; +//# sourceMappingURL=debug.d.ts.map \ No newline at end of file diff --git a/dist/debug.d.ts.map b/dist/debug.d.ts.map new file mode 100644 index 0000000..5e4d298 --- /dev/null +++ b/dist/debug.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,IACrB,KAAK,MAAM,EAAE,GAAG,MAAM,OAAO,EAAE,KAAG,IAAI,CAK7D"} \ No newline at end of file diff --git a/dist/debug.js b/dist/debug.js new file mode 100644 index 0000000..962097a --- /dev/null +++ b/dist/debug.js @@ -0,0 +1,15 @@ +// Shared debug logging utility +// Enable via: DEBUG=claude-hud or DEBUG=* +const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*'; +/** + * Create a namespaced debug logger + * @param namespace - Tag for log messages (e.g., 'config', 'usage') + */ +export function createDebug(namespace) { + return function debug(msg, ...args) { + if (DEBUG) { + console.error(`[claude-hud:${namespace}] ${msg}`, ...args); + } + }; +} +//# sourceMappingURL=debug.js.map \ No newline at end of file diff --git a/dist/debug.js.map b/dist/debug.js.map new file mode 100644 index 0000000..6ebcc25 --- /dev/null +++ b/dist/debug.js.map @@ -0,0 +1 @@ +{"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0CAA0C;AAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;AAErF;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAO,SAAS,KAAK,CAAC,GAAW,EAAE,GAAG,IAAe;QACnD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,eAAe,SAAS,KAAK,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/dist/extra-cmd.d.ts b/dist/extra-cmd.d.ts new file mode 100644 index 0000000..b35fd87 --- /dev/null +++ b/dist/extra-cmd.d.ts @@ -0,0 +1,23 @@ +export interface ExtraLabel { + label: string; +} +/** + * Sanitize output to prevent terminal escape injection. + * Strips ANSI escapes, OSC sequences, control characters, and bidi controls. + */ +export declare function sanitize(input: string): string; +/** + * Parse --extra-cmd argument from process.argv + * Supports both: --extra-cmd "command" and --extra-cmd="command" + */ +export declare function parseExtraCmdArg(argv?: string[]): string | null; +/** + * Execute a command and parse JSON output expecting { label: string } + * Returns null on any error (timeout, parse failure, missing label) + * + * SECURITY NOTE: The cmd parameter is sourced exclusively from CLI arguments + * (--extra-cmd) typed by the user. Since the user controls their own shell, + * shell injection is not a concern here - it's intentional user input. + */ +export declare function runExtraCmd(cmd: string, timeout?: number): Promise; +//# sourceMappingURL=extra-cmd.d.ts.map \ No newline at end of file diff --git a/dist/extra-cmd.d.ts.map b/dist/extra-cmd.d.ts.map new file mode 100644 index 0000000..4a535ac --- /dev/null +++ b/dist/extra-cmd.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"extra-cmd.d.ts","sourceRoot":"","sources":["../src/extra-cmd.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,MAAM,GAAG,IAAI,CA8B7E;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmCnG"} \ No newline at end of file diff --git a/dist/extra-cmd.js b/dist/extra-cmd.js new file mode 100644 index 0000000..3438f0a --- /dev/null +++ b/dist/extra-cmd.js @@ -0,0 +1,103 @@ +import { exec } from 'node:child_process'; +import { promisify } from 'node:util'; +const execAsync = promisify(exec); +const MAX_BUFFER = 10 * 1024; // 10KB - plenty for a label +const MAX_LABEL_LENGTH = 50; +const TIMEOUT_MS = 3000; +const isDebug = process.env.DEBUG?.includes('claude-hud') ?? false; +function debug(message) { + if (isDebug) { + console.error(`[claude-hud:extra-cmd] ${message}`); + } +} +/** + * Sanitize output to prevent terminal escape injection. + * Strips ANSI escapes, OSC sequences, control characters, and bidi controls. + */ +export function sanitize(input) { + return input + .replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '') // CSI sequences + .replace(/\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)/g, '') // OSC sequences + .replace(/\x1B[@-Z\\-_]/g, '') // 7-bit C1 / ESC Fe + .replace(/[\u0000-\u001F\u007F-\u009F]/g, '') // C0/C1 controls + .replace(/[\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069\u206A-\u206F]/g, ''); // bidi +} +/** + * Parse --extra-cmd argument from process.argv + * Supports both: --extra-cmd "command" and --extra-cmd="command" + */ +export function parseExtraCmdArg(argv = process.argv) { + for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + // Handle --extra-cmd=value syntax + if (arg.startsWith('--extra-cmd=')) { + const value = arg.slice('--extra-cmd='.length); + if (value === '') { + debug('Warning: --extra-cmd value is empty, ignoring'); + return null; + } + return value; + } + // Handle --extra-cmd value syntax + if (arg === '--extra-cmd') { + if (i + 1 >= argv.length) { + debug('Warning: --extra-cmd specified but no value provided'); + return null; + } + const value = argv[i + 1]; + if (value === '') { + debug('Warning: --extra-cmd value is empty, ignoring'); + return null; + } + return value; + } + } + return null; +} +/** + * Execute a command and parse JSON output expecting { label: string } + * Returns null on any error (timeout, parse failure, missing label) + * + * SECURITY NOTE: The cmd parameter is sourced exclusively from CLI arguments + * (--extra-cmd) typed by the user. Since the user controls their own shell, + * shell injection is not a concern here - it's intentional user input. + */ +export async function runExtraCmd(cmd, timeout = TIMEOUT_MS) { + try { + const { stdout } = await execAsync(cmd, { + timeout, + maxBuffer: MAX_BUFFER, + }); + const data = JSON.parse(stdout.trim()); + if (typeof data === 'object' && + data !== null && + 'label' in data && + typeof data.label === 'string') { + let label = sanitize(data.label); + if (label.length > MAX_LABEL_LENGTH) { + label = label.slice(0, MAX_LABEL_LENGTH - 1) + '…'; + } + return label; + } + debug(`Command output missing 'label' field or invalid type: ${JSON.stringify(data)}`); + return null; + } + catch (err) { + if (err instanceof Error) { + if (err.message.includes('TIMEOUT') || err.message.includes('killed')) { + debug(`Command timed out after ${timeout}ms: ${cmd}`); + } + else if (err instanceof SyntaxError) { + debug(`Failed to parse JSON output: ${err.message}`); + } + else { + debug(`Command failed: ${err.message}`); + } + } + else { + debug(`Command failed with unknown error`); + } + return null; + } +} +//# sourceMappingURL=extra-cmd.js.map \ No newline at end of file diff --git a/dist/extra-cmd.js.map b/dist/extra-cmd.js.map new file mode 100644 index 0000000..b0efaf6 --- /dev/null +++ b/dist/extra-cmd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extra-cmd.js","sourceRoot":"","sources":["../src/extra-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,4BAA4B;AAC1D,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC;AAEnE,SAAS,KAAK,CAAC,OAAe;IAC5B,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAMD;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,KAAK;SACT,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC,gBAAgB;SACxD,OAAO,CAAC,oCAAoC,EAAE,EAAE,CAAC,CAAC,gBAAgB;SAClE,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,oBAAoB;SAClD,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC,iBAAiB;SAC9D,OAAO,CAAC,8DAA8D,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO;AACzF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAiB,OAAO,CAAC,IAAI;IAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,kCAAkC;QAClC,IAAI,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACjB,KAAK,CAAC,+CAA+C,CAAC,CAAC;gBACvD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,kCAAkC;QAClC,IAAI,GAAG,KAAK,aAAa,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACzB,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBAC9D,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACjB,KAAK,CAAC,+CAA+C,CAAC,CAAC;gBACvD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,UAAkB,UAAU;IACzE,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;YACtC,OAAO;YACP,SAAS,EAAE,UAAU;SACtB,CAAC,CAAC;QACH,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,IACE,OAAO,IAAI,KAAK,QAAQ;YACxB,IAAI,KAAK,IAAI;YACb,OAAO,IAAI,IAAI;YACf,OAAQ,IAAmB,CAAC,KAAK,KAAK,QAAQ,EAC9C,CAAC;YACD,IAAI,KAAK,GAAG,QAAQ,CAAE,IAAmB,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;gBACpC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;YACrD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,CAAC,yDAAyD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;YACzB,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtE,KAAK,CAAC,2BAA2B,OAAO,OAAO,GAAG,EAAE,CAAC,CAAC;YACxD,CAAC;iBAAM,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;gBACtC,KAAK,CAAC,gCAAgC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,mBAAmB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/git.d.ts b/dist/git.d.ts new file mode 100644 index 0000000..6bef2e4 --- /dev/null +++ b/dist/git.d.ts @@ -0,0 +1,16 @@ +export interface FileStats { + modified: number; + added: number; + deleted: number; + untracked: number; +} +export interface GitStatus { + branch: string; + isDirty: boolean; + ahead: number; + behind: number; + fileStats?: FileStats; +} +export declare function getGitBranch(cwd?: string): Promise; +export declare function getGitStatus(cwd?: string): Promise; +//# sourceMappingURL=git.d.ts.map \ No newline at end of file diff --git a/dist/git.d.ts.map b/dist/git.d.ts.map new file mode 100644 index 0000000..92acdbb --- /dev/null +++ b/dist/git.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAavE;AAED,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAqD1E"} \ No newline at end of file diff --git a/dist/git.js b/dist/git.js new file mode 100644 index 0000000..5f9e189 --- /dev/null +++ b/dist/git.js @@ -0,0 +1,86 @@ +import { execFile } from 'node:child_process'; +import { promisify } from 'node:util'; +const execFileAsync = promisify(execFile); +export async function getGitBranch(cwd) { + if (!cwd) + return null; + try { + const { stdout } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd, timeout: 1000, encoding: 'utf8' }); + return stdout.trim() || null; + } + catch { + return null; + } +} +export async function getGitStatus(cwd) { + if (!cwd) + return null; + try { + // Get branch name + const { stdout: branchOut } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd, timeout: 1000, encoding: 'utf8' }); + const branch = branchOut.trim(); + if (!branch) + return null; + // Check for dirty state and parse file stats + let isDirty = false; + let fileStats; + try { + const { stdout: statusOut } = await execFileAsync('git', ['--no-optional-locks', 'status', '--porcelain'], { cwd, timeout: 1000, encoding: 'utf8' }); + const trimmed = statusOut.trim(); + isDirty = trimmed.length > 0; + if (isDirty) { + fileStats = parseFileStats(trimmed); + } + } + catch { + // Ignore errors, assume clean + } + // Get ahead/behind counts + let ahead = 0; + let behind = 0; + try { + const { stdout: revOut } = await execFileAsync('git', ['rev-list', '--left-right', '--count', '@{upstream}...HEAD'], { cwd, timeout: 1000, encoding: 'utf8' }); + const parts = revOut.trim().split(/\s+/); + if (parts.length === 2) { + behind = parseInt(parts[0], 10) || 0; + ahead = parseInt(parts[1], 10) || 0; + } + } + catch { + // No upstream or error, keep 0/0 + } + return { branch, isDirty, ahead, behind, fileStats }; + } + catch { + return null; + } +} +/** + * Parse git status --porcelain output and count file stats (Starship-compatible format) + * Status codes: M=modified, A=added, D=deleted, ??=untracked + */ +function parseFileStats(porcelainOutput) { + const stats = { modified: 0, added: 0, deleted: 0, untracked: 0 }; + const lines = porcelainOutput.split('\n').filter(Boolean); + for (const line of lines) { + if (line.length < 2) + continue; + const index = line[0]; // staged status + const worktree = line[1]; // unstaged status + if (line.startsWith('??')) { + stats.untracked++; + } + else if (index === 'A') { + stats.added++; + } + else if (index === 'D' || worktree === 'D') { + stats.deleted++; + } + else if (index === 'M' || worktree === 'M' || index === 'R' || index === 'C') { + // M=modified, R=renamed (counts as modified), C=copied (counts as modified) + stats.modified++; + } + } + return stats; +} +//# sourceMappingURL=git.js.map \ No newline at end of file diff --git a/dist/git.js.map b/dist/git.js.map new file mode 100644 index 0000000..d76445a --- /dev/null +++ b/dist/git.js.map @@ -0,0 +1 @@ +{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..dc63033 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,24 @@ +import { readStdin } from './stdin.js'; +import { parseTranscript } from './transcript.js'; +import { render } from './render/index.js'; +import { countConfigs } from './config-reader.js'; +import { getGitStatus } from './git.js'; +import { getUsage } from './usage-api.js'; +import { loadConfig } from './config.js'; +import { parseExtraCmdArg, runExtraCmd } from './extra-cmd.js'; +export type MainDeps = { + readStdin: typeof readStdin; + parseTranscript: typeof parseTranscript; + countConfigs: typeof countConfigs; + getGitStatus: typeof getGitStatus; + getUsage: typeof getUsage; + loadConfig: typeof loadConfig; + parseExtraCmdArg: typeof parseExtraCmdArg; + runExtraCmd: typeof runExtraCmd; + render: typeof render; + now: () => number; + log: (...args: unknown[]) => void; +}; +export declare function main(overrides?: Partial): Promise; +export declare function formatSessionDuration(sessionStart?: Date, now?: () => number): string; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map new file mode 100644 index 0000000..67d48ee --- /dev/null +++ b/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAK/D,MAAM,MAAM,QAAQ,GAAG;IACrB,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,eAAe,EAAE,OAAO,eAAe,CAAC;IACxC,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,wBAAsB,IAAI,CAAC,SAAS,GAAE,OAAO,CAAC,QAAQ,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE3E;AAED,wBAAgB,qBAAqB,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,GAAG,GAAE,MAAM,MAAyB,GAAG,MAAM,CAcvG"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..ce0c905 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,97 @@ +import { readStdin } from './stdin.js'; +import { parseTranscript } from './transcript.js'; +import { render } from './render/index.js'; +import { countConfigs } from './config-reader.js'; +import { getGitStatus } from './git.js'; +import { getUsage } from './usage-api.js'; +import { loadConfig } from './config.js'; +import { parseExtraCmdArg, runExtraCmd } from './extra-cmd.js'; +import { fileURLToPath } from 'node:url'; +import { realpathSync } from 'node:fs'; +export async function main(overrides = {}) { + const deps = { + readStdin, + parseTranscript, + countConfigs, + getGitStatus, + getUsage, + loadConfig, + parseExtraCmdArg, + runExtraCmd, + render, + now: () => Date.now(), + log: console.log, + ...overrides, + }; + try { + const stdin = await deps.readStdin(); + if (!stdin) { + deps.log('[claude-hud] Initializing...'); + return; + } + const transcriptPath = stdin.transcript_path ?? ''; + const transcript = await deps.parseTranscript(transcriptPath); + const { claudeMdCount, rulesCount, mcpCount, hooksCount } = await deps.countConfigs(stdin.cwd); + const config = await deps.loadConfig(); + const gitStatus = config.gitStatus.enabled + ? await deps.getGitStatus(stdin.cwd) + : null; + // Only fetch usage if enabled in config (replaces env var requirement) + const usageData = config.display.showUsage !== false + ? await deps.getUsage({ + ttls: { + cacheTtlMs: config.usage.cacheTtlSeconds * 1000, + failureCacheTtlMs: config.usage.failureCacheTtlSeconds * 1000, + }, + }) + : null; + const extraCmd = deps.parseExtraCmdArg(); + const extraLabel = extraCmd ? await deps.runExtraCmd(extraCmd) : null; + const sessionDuration = formatSessionDuration(transcript.sessionStart, deps.now); + const ctx = { + stdin, + transcript, + claudeMdCount, + rulesCount, + mcpCount, + hooksCount, + sessionDuration, + gitStatus, + usageData, + config, + extraLabel, + }; + deps.render(ctx); + } + catch (error) { + deps.log('[claude-hud] Error:', error instanceof Error ? error.message : 'Unknown error'); + } +} +export function formatSessionDuration(sessionStart, now = () => Date.now()) { + if (!sessionStart) { + return ''; + } + const ms = now() - sessionStart.getTime(); + const mins = Math.floor(ms / 60000); + if (mins < 1) + return '<1m'; + if (mins < 60) + return `${mins}m`; + const hours = Math.floor(mins / 60); + const remainingMins = mins % 60; + return `${hours}h ${remainingMins}m`; +} +const scriptPath = fileURLToPath(import.meta.url); +const argvPath = process.argv[1]; +const isSamePath = (a, b) => { + try { + return realpathSync(a) === realpathSync(b); + } + catch { + return a === b; + } +}; +if (argvPath && isSamePath(argvPath, scriptPath)) { + void main(); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..8ed9706 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/agents-line.d.ts b/dist/render/agents-line.d.ts new file mode 100644 index 0000000..a9e0584 --- /dev/null +++ b/dist/render/agents-line.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../types.js'; +export declare function renderAgentsLine(ctx: RenderContext): string | null; +//# sourceMappingURL=agents-line.d.ts.map \ No newline at end of file diff --git a/dist/render/agents-line.d.ts.map b/dist/render/agents-line.d.ts.map new file mode 100644 index 0000000..f35c3b3 --- /dev/null +++ b/dist/render/agents-line.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"agents-line.d.ts","sourceRoot":"","sources":["../../src/render/agents-line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,aAAa,CAAC;AAG7D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAqBlE"} \ No newline at end of file diff --git a/dist/render/agents-line.js b/dist/render/agents-line.js new file mode 100644 index 0000000..febaa6d --- /dev/null +++ b/dist/render/agents-line.js @@ -0,0 +1,44 @@ +import { yellow, green, magenta, dim } from './colors.js'; +export function renderAgentsLine(ctx) { + const { agents } = ctx.transcript; + const runningAgents = agents.filter((a) => a.status === 'running'); + const recentCompleted = agents + .filter((a) => a.status === 'completed') + .slice(-2); + const toShow = [...runningAgents, ...recentCompleted].slice(-3); + if (toShow.length === 0) { + return null; + } + const lines = []; + for (const agent of toShow) { + lines.push(formatAgent(agent)); + } + return lines.join('\n'); +} +function formatAgent(agent) { + const statusIcon = agent.status === 'running' ? yellow('◐') : green('✓'); + const type = magenta(agent.type); + const model = agent.model ? dim(`[${agent.model}]`) : ''; + const desc = agent.description ? dim(`: ${truncateDesc(agent.description)}`) : ''; + const elapsed = formatElapsed(agent); + return `${statusIcon} ${type}${model ? ` ${model}` : ''}${desc} ${dim(`(${elapsed})`)}`; +} +function truncateDesc(desc, maxLen = 40) { + if (desc.length <= maxLen) + return desc; + return desc.slice(0, maxLen - 3) + '...'; +} +function formatElapsed(agent) { + const now = Date.now(); + const start = agent.startTime.getTime(); + const end = agent.endTime?.getTime() ?? now; + const ms = end - start; + if (ms < 1000) + return '<1s'; + if (ms < 60000) + return `${Math.round(ms / 1000)}s`; + const mins = Math.floor(ms / 60000); + const secs = Math.round((ms % 60000) / 1000); + return `${mins}m ${secs}s`; +} +//# sourceMappingURL=agents-line.js.map \ No newline at end of file diff --git a/dist/render/agents-line.js.map b/dist/render/agents-line.js.map new file mode 100644 index 0000000..8e7e84a --- /dev/null +++ b/dist/render/agents-line.js.map @@ -0,0 +1 @@ +{"version":3,"file":"agents-line.js","sourceRoot":"","sources":["../../src/render/agents-line.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/colors.d.ts b/dist/render/colors.d.ts new file mode 100644 index 0000000..4dd0ade --- /dev/null +++ b/dist/render/colors.d.ts @@ -0,0 +1,15 @@ +import type { HudColorOverrides } from '../config.js'; +export declare const RESET = "\u001B[0m"; +export declare function green(text: string): string; +export declare function yellow(text: string): string; +export declare function red(text: string): string; +export declare function cyan(text: string): string; +export declare function magenta(text: string): string; +export declare function dim(text: string): string; +export declare function warning(text: string, colors?: Partial): string; +export declare function critical(text: string, colors?: Partial): string; +export declare function getContextColor(percent: number, colors?: Partial): string; +export declare function getQuotaColor(percent: number, colors?: Partial): string; +export declare function quotaBar(percent: number, width?: number, colors?: Partial): string; +export declare function coloredBar(percent: number, width?: number, colors?: Partial): string; +//# sourceMappingURL=colors.d.ts.map \ No newline at end of file diff --git a/dist/render/colors.d.ts.map b/dist/render/colors.d.ts.map new file mode 100644 index 0000000..f5e4107 --- /dev/null +++ b/dist/render/colors.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/render/colors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEpE,eAAO,MAAM,KAAK,cAAY,CAAC;AAgC/B,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAEjF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAElF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAI5F;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAI1F;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAOzG;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAO3G"} \ No newline at end of file diff --git a/dist/render/colors.js b/dist/render/colors.js new file mode 100644 index 0000000..5149ead --- /dev/null +++ b/dist/render/colors.js @@ -0,0 +1,82 @@ +export const RESET = '\x1b[0m'; +const DIM = '\x1b[2m'; +const RED = '\x1b[31m'; +const GREEN = '\x1b[32m'; +const YELLOW = '\x1b[33m'; +const MAGENTA = '\x1b[35m'; +const CYAN = '\x1b[36m'; +const BRIGHT_BLUE = '\x1b[94m'; +const BRIGHT_MAGENTA = '\x1b[95m'; +const ANSI_BY_NAME = { + red: RED, + green: GREEN, + yellow: YELLOW, + magenta: MAGENTA, + cyan: CYAN, + brightBlue: BRIGHT_BLUE, + brightMagenta: BRIGHT_MAGENTA, +}; +function resolveAnsi(name, fallback) { + if (!name) { + return fallback; + } + return ANSI_BY_NAME[name] ?? fallback; +} +function colorize(text, color) { + return `${color}${text}${RESET}`; +} +export function green(text) { + return colorize(text, GREEN); +} +export function yellow(text) { + return colorize(text, YELLOW); +} +export function red(text) { + return colorize(text, RED); +} +export function cyan(text) { + return colorize(text, CYAN); +} +export function magenta(text) { + return colorize(text, MAGENTA); +} +export function dim(text) { + return colorize(text, DIM); +} +export function warning(text, colors) { + return colorize(text, resolveAnsi(colors?.warning, YELLOW)); +} +export function critical(text, colors) { + return colorize(text, resolveAnsi(colors?.critical, RED)); +} +export function getContextColor(percent, colors) { + if (percent >= 85) + return resolveAnsi(colors?.critical, RED); + if (percent >= 70) + return resolveAnsi(colors?.warning, YELLOW); + return resolveAnsi(colors?.context, GREEN); +} +export function getQuotaColor(percent, colors) { + if (percent >= 90) + return resolveAnsi(colors?.critical, RED); + if (percent >= 75) + return resolveAnsi(colors?.usageWarning, BRIGHT_MAGENTA); + return resolveAnsi(colors?.usage, BRIGHT_BLUE); +} +export function quotaBar(percent, width = 10, colors) { + const safeWidth = Number.isFinite(width) ? Math.max(0, Math.round(width)) : 0; + const safePercent = Number.isFinite(percent) ? Math.min(100, Math.max(0, percent)) : 0; + const filled = Math.round((safePercent / 100) * safeWidth); + const empty = safeWidth - filled; + const color = getQuotaColor(safePercent, colors); + return `${color}${'█'.repeat(filled)}${DIM}${'░'.repeat(empty)}${RESET}`; +} +export function coloredBar(percent, width = 10, colors) { + const safeWidth = Number.isFinite(width) ? Math.max(0, Math.round(width)) : 0; + const safePercent = Number.isFinite(percent) ? Math.min(100, Math.max(0, percent)) : 0; + const filled = Math.round((safePercent / 100) * safeWidth); + const empty = safeWidth - filled; + const color = getContextColor(safePercent, colors); + return `${color}${'█'.repeat(filled)}${DIM}${'░'.repeat(empty)}${RESET}`; +} +//# sourceMappingURL=colors.js.map \ No newline at end of file diff --git a/dist/render/colors.js.map b/dist/render/colors.js.map new file mode 100644 index 0000000..b396d3d --- /dev/null +++ b/dist/render/colors.js.map @@ -0,0 +1 @@ +{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/render/colors.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/index.d.ts b/dist/render/index.d.ts new file mode 100644 index 0000000..8d14d5c --- /dev/null +++ b/dist/render/index.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../types.js'; +export declare function render(ctx: RenderContext): void; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/render/index.d.ts.map b/dist/render/index.d.ts.map new file mode 100644 index 0000000..3b251c2 --- /dev/null +++ b/dist/render/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+ZjD,wBAAgB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAiD/C"} \ No newline at end of file diff --git a/dist/render/index.js b/dist/render/index.js new file mode 100644 index 0000000..aed35d5 --- /dev/null +++ b/dist/render/index.js @@ -0,0 +1,385 @@ +import { DEFAULT_ELEMENT_ORDER } from '../config.js'; +import { renderSessionLine } from './session-line.js'; +import { renderToolsLine } from './tools-line.js'; +import { renderAgentsLine } from './agents-line.js'; +import { renderTodosLine } from './todos-line.js'; +import { renderIdentityLine, renderProjectLine, renderEnvironmentLine, renderUsageLine, } from './lines/index.js'; +import { dim, RESET } from './colors.js'; +// eslint-disable-next-line no-control-regex +const ANSI_ESCAPE_PATTERN = /^\x1b\[[0-9;]*m/; +const ANSI_ESCAPE_GLOBAL = /\x1b\[[0-9;]*m/g; +const GRAPHEME_SEGMENTER = typeof Intl.Segmenter === 'function' + ? new Intl.Segmenter(undefined, { granularity: 'grapheme' }) + : null; +function stripAnsi(str) { + return str.replace(ANSI_ESCAPE_GLOBAL, ''); +} +function getTerminalWidth() { + const stdoutColumns = process.stdout?.columns; + if (typeof stdoutColumns === 'number' && Number.isFinite(stdoutColumns) && stdoutColumns > 0) { + return Math.floor(stdoutColumns); + } + // When running as a statusline subprocess, stdout is piped but stderr is + // still connected to the real terminal — use it to get the actual width. + const stderrColumns = process.stderr?.columns; + if (typeof stderrColumns === 'number' && Number.isFinite(stderrColumns) && stderrColumns > 0) { + return Math.floor(stderrColumns); + } + const envColumns = Number.parseInt(process.env.COLUMNS ?? '', 10); + if (Number.isFinite(envColumns) && envColumns > 0) { + return envColumns; + } + return null; +} +function splitAnsiTokens(str) { + const tokens = []; + let i = 0; + while (i < str.length) { + const ansiMatch = ANSI_ESCAPE_PATTERN.exec(str.slice(i)); + if (ansiMatch) { + tokens.push({ type: 'ansi', value: ansiMatch[0] }); + i += ansiMatch[0].length; + continue; + } + let j = i; + while (j < str.length) { + const nextAnsi = ANSI_ESCAPE_PATTERN.exec(str.slice(j)); + if (nextAnsi) { + break; + } + j += 1; + } + tokens.push({ type: 'text', value: str.slice(i, j) }); + i = j; + } + return tokens; +} +function segmentGraphemes(text) { + if (!text) { + return []; + } + if (!GRAPHEME_SEGMENTER) { + return Array.from(text); + } + return Array.from(GRAPHEME_SEGMENTER.segment(text), segment => segment.segment); +} +function isWideCodePoint(codePoint) { + return codePoint >= 0x1100 && (codePoint <= 0x115F || // Hangul Jamo + codePoint === 0x2329 || + codePoint === 0x232A || + (codePoint >= 0x2E80 && codePoint <= 0xA4CF && codePoint !== 0x303F) || + (codePoint >= 0xAC00 && codePoint <= 0xD7A3) || + (codePoint >= 0xF900 && codePoint <= 0xFAFF) || + (codePoint >= 0xFE10 && codePoint <= 0xFE19) || + (codePoint >= 0xFE30 && codePoint <= 0xFE6F) || + (codePoint >= 0xFF00 && codePoint <= 0xFF60) || + (codePoint >= 0xFFE0 && codePoint <= 0xFFE6) || + (codePoint >= 0x1F300 && codePoint <= 0x1FAFF) || + (codePoint >= 0x20000 && codePoint <= 0x3FFFD)); +} +function graphemeWidth(grapheme) { + if (!grapheme || /^\p{Control}$/u.test(grapheme)) { + return 0; + } + // Emoji glyphs and ZWJ sequences generally render as double-width. + if (/\p{Extended_Pictographic}/u.test(grapheme)) { + return 2; + } + let hasVisibleBase = false; + let width = 0; + for (const char of Array.from(grapheme)) { + if (/^\p{Mark}$/u.test(char) || char === '\u200D' || char === '\uFE0F') { + continue; + } + hasVisibleBase = true; + const codePoint = char.codePointAt(0); + if (codePoint !== undefined && isWideCodePoint(codePoint)) { + width = Math.max(width, 2); + } + else { + width = Math.max(width, 1); + } + } + return hasVisibleBase ? width : 0; +} +function visualLength(str) { + let width = 0; + for (const token of splitAnsiTokens(str)) { + if (token.type === 'ansi') { + continue; + } + for (const grapheme of segmentGraphemes(token.value)) { + width += graphemeWidth(grapheme); + } + } + return width; +} +function sliceVisible(str, maxVisible) { + if (maxVisible <= 0) { + return ''; + } + let result = ''; + let visibleWidth = 0; + let done = false; + let i = 0; + while (i < str.length && !done) { + const ansiMatch = ANSI_ESCAPE_PATTERN.exec(str.slice(i)); + if (ansiMatch) { + result += ansiMatch[0]; + i += ansiMatch[0].length; + continue; + } + let j = i; + while (j < str.length) { + const nextAnsi = ANSI_ESCAPE_PATTERN.exec(str.slice(j)); + if (nextAnsi) { + break; + } + j += 1; + } + const plainChunk = str.slice(i, j); + for (const grapheme of segmentGraphemes(plainChunk)) { + const graphemeCellWidth = graphemeWidth(grapheme); + if (visibleWidth + graphemeCellWidth > maxVisible) { + done = true; + break; + } + result += grapheme; + visibleWidth += graphemeCellWidth; + } + i = j; + } + return result; +} +function truncateToWidth(str, maxWidth) { + if (maxWidth <= 0 || visualLength(str) <= maxWidth) { + return str; + } + const suffix = maxWidth >= 3 ? '...' : '.'.repeat(maxWidth); + const keep = Math.max(0, maxWidth - suffix.length); + return `${sliceVisible(str, keep)}${suffix}${RESET}`; +} +function splitLineBySeparators(line) { + const segments = []; + const separators = []; + let currentStart = 0; + let i = 0; + while (i < line.length) { + const ansiMatch = ANSI_ESCAPE_PATTERN.exec(line.slice(i)); + if (ansiMatch) { + i += ansiMatch[0].length; + continue; + } + const separator = line.startsWith(' | ', i) + ? ' | ' + : (line.startsWith(' │ ', i) ? ' │ ' : null); + if (separator) { + segments.push(line.slice(currentStart, i)); + separators.push(separator); + i += separator.length; + currentStart = i; + continue; + } + i += 1; + } + segments.push(line.slice(currentStart)); + return { segments, separators }; +} +function splitWrapParts(line) { + const { segments, separators } = splitLineBySeparators(line); + if (segments.length === 0) { + return []; + } + let parts = [{ + separator: '', + segment: segments[0], + }]; + for (let segmentIndex = 1; segmentIndex < segments.length; segmentIndex += 1) { + parts.push({ + separator: separators[segmentIndex - 1] ?? ' | ', + segment: segments[segmentIndex], + }); + } + // Keep the leading [model | provider] block together. + // This avoids splitting inside the model badge while still splitting + // separators elsewhere in the line. + const firstVisible = stripAnsi(parts[0].segment).trimStart(); + const firstHasOpeningBracket = firstVisible.startsWith('['); + const firstHasClosingBracket = stripAnsi(parts[0].segment).includes(']'); + if (firstHasOpeningBracket && !firstHasClosingBracket && parts.length > 1) { + let mergedSegment = parts[0].segment; + let consumeIndex = 1; + while (consumeIndex < parts.length) { + const nextPart = parts[consumeIndex]; + mergedSegment += `${nextPart.separator}${nextPart.segment}`; + consumeIndex += 1; + if (stripAnsi(nextPart.segment).includes(']')) { + break; + } + } + parts = [ + { separator: '', segment: mergedSegment }, + ...parts.slice(consumeIndex), + ]; + } + return parts; +} +function wrapLineToWidth(line, maxWidth) { + if (maxWidth <= 0 || visualLength(line) <= maxWidth) { + return [line]; + } + const parts = splitWrapParts(line); + if (parts.length <= 1) { + return [truncateToWidth(line, maxWidth)]; + } + const wrapped = []; + let current = parts[0].segment; + for (const part of parts.slice(1)) { + const candidate = `${current}${part.separator}${part.segment}`; + if (visualLength(candidate) <= maxWidth) { + current = candidate; + continue; + } + wrapped.push(truncateToWidth(current, maxWidth)); + current = part.segment; + } + if (current) { + wrapped.push(truncateToWidth(current, maxWidth)); + } + return wrapped; +} +function makeSeparator(length) { + return dim('─'.repeat(Math.max(length, 1))); +} +const ACTIVITY_ELEMENTS = new Set(['tools', 'agents', 'todos']); +function collectActivityLines(ctx) { + const activityLines = []; + const display = ctx.config?.display; + if (display?.showTools !== false) { + const toolsLine = renderToolsLine(ctx); + if (toolsLine) { + activityLines.push(toolsLine); + } + } + if (display?.showAgents !== false) { + const agentsLine = renderAgentsLine(ctx); + if (agentsLine) { + activityLines.push(agentsLine); + } + } + if (display?.showTodos !== false) { + const todosLine = renderTodosLine(ctx); + if (todosLine) { + activityLines.push(todosLine); + } + } + return activityLines; +} +function renderElementLine(ctx, element) { + const display = ctx.config?.display; + switch (element) { + case 'project': + return renderProjectLine(ctx); + case 'context': + return renderIdentityLine(ctx); + case 'usage': + return renderUsageLine(ctx); + case 'environment': + return renderEnvironmentLine(ctx); + case 'tools': + return display?.showTools === false ? null : renderToolsLine(ctx); + case 'agents': + return display?.showAgents === false ? null : renderAgentsLine(ctx); + case 'todos': + return display?.showTodos === false ? null : renderTodosLine(ctx); + } +} +function renderCompact(ctx) { + const lines = []; + const sessionLine = renderSessionLine(ctx); + if (sessionLine) { + lines.push(sessionLine); + } + return lines; +} +function renderExpanded(ctx) { + const elementOrder = ctx.config?.elementOrder ?? DEFAULT_ELEMENT_ORDER; + const seen = new Set(); + const lines = []; + for (let index = 0; index < elementOrder.length; index += 1) { + const element = elementOrder[index]; + if (seen.has(element)) { + continue; + } + const nextElement = elementOrder[index + 1]; + if ((element === 'context' && nextElement === 'usage' && !seen.has('usage')) + || (element === 'usage' && nextElement === 'context' && !seen.has('context'))) { + seen.add(element); + seen.add(nextElement); + const firstLine = renderElementLine(ctx, element); + const secondLine = renderElementLine(ctx, nextElement); + if (firstLine && secondLine) { + lines.push({ line: `${firstLine} │ ${secondLine}`, isActivity: false }); + } + else if (firstLine) { + lines.push({ line: firstLine, isActivity: false }); + } + else if (secondLine) { + lines.push({ line: secondLine, isActivity: false }); + } + continue; + } + seen.add(element); + const line = renderElementLine(ctx, element); + if (!line) { + continue; + } + lines.push({ + line, + isActivity: ACTIVITY_ELEMENTS.has(element), + }); + } + return lines; +} +export function render(ctx) { + const lineLayout = ctx.config?.lineLayout ?? 'expanded'; + const showSeparators = ctx.config?.showSeparators ?? false; + const terminalWidth = getTerminalWidth(); + let lines; + if (lineLayout === 'expanded') { + const renderedLines = renderExpanded(ctx); + lines = renderedLines.map(({ line }) => line); + if (showSeparators) { + const firstActivityIndex = renderedLines.findIndex(({ isActivity }) => isActivity); + if (firstActivityIndex > 0) { + const separatorBaseWidth = Math.max(...renderedLines + .slice(0, firstActivityIndex) + .map(({ line }) => visualLength(line)), 20); + const separatorWidth = terminalWidth + ? Math.min(separatorBaseWidth, terminalWidth) + : separatorBaseWidth; + lines.splice(firstActivityIndex, 0, makeSeparator(separatorWidth)); + } + } + } + else { + const headerLines = renderCompact(ctx); + const activityLines = collectActivityLines(ctx); + lines = [...headerLines]; + if (showSeparators && activityLines.length > 0) { + const maxWidth = Math.max(...headerLines.map(visualLength), 20); + const separatorWidth = terminalWidth ? Math.min(maxWidth, terminalWidth) : maxWidth; + lines.push(makeSeparator(separatorWidth)); + } + lines.push(...activityLines); + } + const physicalLines = lines.flatMap(line => line.split('\n')); + const visibleLines = terminalWidth + ? physicalLines.flatMap(line => wrapLineToWidth(line, terminalWidth)) + : physicalLines; + for (const line of visibleLines) { + const outputLine = `${RESET}${line}`; + console.log(outputLine); + } +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/render/index.js.map b/dist/render/index.js.map new file mode 100644 index 0000000..736028a --- /dev/null +++ b/dist/render/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/lines/environment.d.ts b/dist/render/lines/environment.d.ts new file mode 100644 index 0000000..aa52a20 --- /dev/null +++ b/dist/render/lines/environment.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../../types.js'; +export declare function renderEnvironmentLine(ctx: RenderContext): string | null; +//# sourceMappingURL=environment.d.ts.map \ No newline at end of file diff --git a/dist/render/lines/environment.d.ts.map b/dist/render/lines/environment.d.ts.map new file mode 100644 index 0000000..a3b7145 --- /dev/null +++ b/dist/render/lines/environment.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../../src/render/lines/environment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAqCvE"} \ No newline at end of file diff --git a/dist/render/lines/environment.js b/dist/render/lines/environment.js new file mode 100644 index 0000000..d0a921b --- /dev/null +++ b/dist/render/lines/environment.js @@ -0,0 +1,30 @@ +import { dim } from '../colors.js'; +export function renderEnvironmentLine(ctx) { + const display = ctx.config?.display; + if (display?.showConfigCounts === false) { + return null; + } + const totalCounts = ctx.claudeMdCount + ctx.rulesCount + ctx.mcpCount + ctx.hooksCount; + const threshold = display?.environmentThreshold ?? 0; + if (totalCounts === 0 || totalCounts < threshold) { + return null; + } + const parts = []; + if (ctx.claudeMdCount > 0) { + parts.push(`${ctx.claudeMdCount} CLAUDE.md`); + } + if (ctx.rulesCount > 0) { + parts.push(`${ctx.rulesCount} rules`); + } + if (ctx.mcpCount > 0) { + parts.push(`${ctx.mcpCount} MCPs`); + } + if (ctx.hooksCount > 0) { + parts.push(`${ctx.hooksCount} hooks`); + } + if (parts.length === 0) { + return null; + } + return dim(parts.join(' | ')); +} +//# sourceMappingURL=environment.js.map \ No newline at end of file diff --git a/dist/render/lines/environment.js.map b/dist/render/lines/environment.js.map new file mode 100644 index 0000000..4b9c7e3 --- /dev/null +++ b/dist/render/lines/environment.js.map @@ -0,0 +1 @@ +{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../../src/render/lines/environment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,UAAU,qBAAqB,CAAC,GAAkB;IACtD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAEpC,IAAI,OAAO,EAAE,gBAAgB,KAAK,KAAK,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC;IACvF,MAAM,SAAS,GAAG,OAAO,EAAE,oBAAoB,IAAI,CAAC,CAAC;IAErD,IAAI,WAAW,KAAK,CAAC,IAAI,WAAW,GAAG,SAAS,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,GAAG,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,aAAa,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAChC,CAAC"} \ No newline at end of file diff --git a/dist/render/lines/identity.d.ts b/dist/render/lines/identity.d.ts new file mode 100644 index 0000000..e525e64 --- /dev/null +++ b/dist/render/lines/identity.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../../types.js'; +export declare function renderIdentityLine(ctx: RenderContext): string; +//# sourceMappingURL=identity.d.ts.map \ No newline at end of file diff --git a/dist/render/lines/identity.d.ts.map b/dist/render/lines/identity.d.ts.map new file mode 100644 index 0000000..da08799 --- /dev/null +++ b/dist/render/lines/identity.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../src/render/lines/identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAOpD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CA8B7D"} \ No newline at end of file diff --git a/dist/render/lines/identity.js b/dist/render/lines/identity.js new file mode 100644 index 0000000..c053293 --- /dev/null +++ b/dist/render/lines/identity.js @@ -0,0 +1,54 @@ +import { getContextPercent, getBufferedPercent, getTotalTokens } from '../../stdin.js'; +import { coloredBar, dim, getContextColor, RESET } from '../colors.js'; +import { getAdaptiveBarWidth } from '../../utils/terminal.js'; +const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*'; +export function renderIdentityLine(ctx) { + const rawPercent = getContextPercent(ctx.stdin); + const bufferedPercent = getBufferedPercent(ctx.stdin); + const autocompactMode = ctx.config?.display?.autocompactBuffer ?? 'enabled'; + const percent = autocompactMode === 'disabled' ? rawPercent : bufferedPercent; + const colors = ctx.config?.colors; + if (DEBUG && autocompactMode === 'disabled') { + console.error(`[claude-hud:context] autocompactBuffer=disabled, showing raw ${rawPercent}% (buffered would be ${bufferedPercent}%)`); + } + const display = ctx.config?.display; + const contextValueMode = display?.contextValue ?? 'percent'; + const contextValue = formatContextValue(ctx, percent, contextValueMode); + const contextValueDisplay = `${getContextColor(percent, colors)}${contextValue}${RESET}`; + let line = display?.showContextBar !== false + ? `${dim('Context')} ${coloredBar(percent, getAdaptiveBarWidth(), colors)} ${contextValueDisplay}` + : `${dim('Context')} ${contextValueDisplay}`; + if (display?.showTokenBreakdown !== false && percent >= 85) { + const usage = ctx.stdin.context_window?.current_usage; + if (usage) { + const input = formatTokens(usage.input_tokens ?? 0); + const cache = formatTokens((usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0)); + line += dim(` (in: ${input}, cache: ${cache})`); + } + } + return line; +} +function formatTokens(n) { + if (n >= 1000000) { + return `${(n / 1000000).toFixed(1)}M`; + } + if (n >= 1000) { + return `${(n / 1000).toFixed(0)}k`; + } + return n.toString(); +} +function formatContextValue(ctx, percent, mode) { + if (mode === 'tokens') { + const totalTokens = getTotalTokens(ctx.stdin); + const size = ctx.stdin.context_window?.context_window_size ?? 0; + if (size > 0) { + return `${formatTokens(totalTokens)}/${formatTokens(size)}`; + } + return formatTokens(totalTokens); + } + if (mode === 'remaining') { + return `${Math.max(0, 100 - percent)}%`; + } + return `${percent}%`; +} +//# sourceMappingURL=identity.js.map \ No newline at end of file diff --git a/dist/render/lines/identity.js.map b/dist/render/lines/identity.js.map new file mode 100644 index 0000000..09f4727 --- /dev/null +++ b/dist/render/lines/identity.js.map @@ -0,0 +1 @@ +{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/render/lines/identity.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/lines/index.d.ts b/dist/render/lines/index.d.ts new file mode 100644 index 0000000..65f1716 --- /dev/null +++ b/dist/render/lines/index.d.ts @@ -0,0 +1,5 @@ +export { renderIdentityLine } from './identity.js'; +export { renderProjectLine } from './project.js'; +export { renderEnvironmentLine } from './environment.js'; +export { renderUsageLine } from './usage.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/render/lines/index.d.ts.map b/dist/render/lines/index.d.ts.map new file mode 100644 index 0000000..85268f4 --- /dev/null +++ b/dist/render/lines/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/render/lines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"} \ No newline at end of file diff --git a/dist/render/lines/index.js b/dist/render/lines/index.js new file mode 100644 index 0000000..0ebb844 --- /dev/null +++ b/dist/render/lines/index.js @@ -0,0 +1,5 @@ +export { renderIdentityLine } from './identity.js'; +export { renderProjectLine } from './project.js'; +export { renderEnvironmentLine } from './environment.js'; +export { renderUsageLine } from './usage.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/render/lines/index.js.map b/dist/render/lines/index.js.map new file mode 100644 index 0000000..4aeb255 --- /dev/null +++ b/dist/render/lines/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/lines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"} \ No newline at end of file diff --git a/dist/render/lines/project.d.ts b/dist/render/lines/project.d.ts new file mode 100644 index 0000000..e55ebdc --- /dev/null +++ b/dist/render/lines/project.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../../types.js'; +export declare function renderProjectLine(ctx: RenderContext): string | null; +//# sourceMappingURL=project.d.ts.map \ No newline at end of file diff --git a/dist/render/lines/project.d.ts.map b/dist/render/lines/project.d.ts.map new file mode 100644 index 0000000..29b529a --- /dev/null +++ b/dist/render/lines/project.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/render/lines/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAgFnE"} \ No newline at end of file diff --git a/dist/render/lines/project.js b/dist/render/lines/project.js new file mode 100644 index 0000000..a73b288 --- /dev/null +++ b/dist/render/lines/project.js @@ -0,0 +1,77 @@ +import { getModelName, getProviderLabel } from '../../stdin.js'; +import { cyan, dim, magenta, yellow, red } from '../colors.js'; +export function renderProjectLine(ctx) { + const display = ctx.config?.display; + const parts = []; + if (display?.showModel !== false) { + const model = getModelName(ctx.stdin); + const providerLabel = getProviderLabel(ctx.stdin); + const showUsage = display?.showUsage !== false; + const planName = showUsage ? ctx.usageData?.planName : undefined; + const hasApiKey = !!process.env.ANTHROPIC_API_KEY; + const billingLabel = showUsage ? (planName ?? (hasApiKey ? red('API') : undefined)) : undefined; + const planDisplay = providerLabel ?? billingLabel; + const modelDisplay = planDisplay ? `${model} | ${planDisplay}` : model; + parts.push(cyan(`[${modelDisplay}]`)); + } + let projectPart = null; + if (display?.showProject !== false && ctx.stdin.cwd) { + const segments = ctx.stdin.cwd.split(/[/\\]/).filter(Boolean); + const pathLevels = ctx.config?.pathLevels ?? 1; + const projectPath = segments.length > 0 ? segments.slice(-pathLevels).join('/') : '/'; + projectPart = yellow(projectPath); + } + let gitPart = ''; + const gitConfig = ctx.config?.gitStatus; + const showGit = gitConfig?.enabled ?? true; + if (showGit && ctx.gitStatus) { + const gitParts = [ctx.gitStatus.branch]; + if ((gitConfig?.showDirty ?? true) && ctx.gitStatus.isDirty) { + gitParts.push('*'); + } + if (gitConfig?.showAheadBehind) { + if (ctx.gitStatus.ahead > 0) { + gitParts.push(` ↑${ctx.gitStatus.ahead}`); + } + if (ctx.gitStatus.behind > 0) { + gitParts.push(` ↓${ctx.gitStatus.behind}`); + } + } + if (gitConfig?.showFileStats && ctx.gitStatus.fileStats) { + const { modified, added, deleted, untracked } = ctx.gitStatus.fileStats; + const statParts = []; + if (modified > 0) + statParts.push(`!${modified}`); + if (added > 0) + statParts.push(`+${added}`); + if (deleted > 0) + statParts.push(`✘${deleted}`); + if (untracked > 0) + statParts.push(`?${untracked}`); + if (statParts.length > 0) { + gitParts.push(` ${statParts.join(' ')}`); + } + } + gitPart = `${magenta('git:(')}${cyan(gitParts.join(''))}${magenta(')')}`; + } + if (projectPart && gitPart) { + parts.push(`${projectPart} ${gitPart}`); + } + else if (projectPart) { + parts.push(projectPart); + } + else if (gitPart) { + parts.push(gitPart); + } + if (display?.showSessionName && ctx.transcript.sessionName) { + parts.push(dim(ctx.transcript.sessionName)); + } + if (ctx.extraLabel) { + parts.push(dim(ctx.extraLabel)); + } + if (parts.length === 0) { + return null; + } + return parts.join(' \u2502 '); +} +//# sourceMappingURL=project.js.map \ No newline at end of file diff --git a/dist/render/lines/project.js.map b/dist/render/lines/project.js.map new file mode 100644 index 0000000..0eff173 --- /dev/null +++ b/dist/render/lines/project.js.map @@ -0,0 +1 @@ +{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/render/lines/project.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/lines/usage.d.ts b/dist/render/lines/usage.d.ts new file mode 100644 index 0000000..a5cc289 --- /dev/null +++ b/dist/render/lines/usage.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../../types.js'; +export declare function renderUsageLine(ctx: RenderContext): string | null; +//# sourceMappingURL=usage.d.ts.map \ No newline at end of file diff --git a/dist/render/lines/usage.d.ts.map b/dist/render/lines/usage.d.ts.map new file mode 100644 index 0000000..6dc4381 --- /dev/null +++ b/dist/render/lines/usage.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/render/lines/usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMpD,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAqEjE"} \ No newline at end of file diff --git a/dist/render/lines/usage.js b/dist/render/lines/usage.js new file mode 100644 index 0000000..f457a30 --- /dev/null +++ b/dist/render/lines/usage.js @@ -0,0 +1,100 @@ +import { isLimitReached } from '../../types.js'; +import { getProviderLabel } from '../../stdin.js'; +import { critical, warning, dim, getQuotaColor, quotaBar, RESET } from '../colors.js'; +import { getAdaptiveBarWidth } from '../../utils/terminal.js'; +export function renderUsageLine(ctx) { + const display = ctx.config?.display; + const colors = ctx.config?.colors; + if (display?.showUsage === false) { + return null; + } + if (!ctx.usageData?.planName) { + return null; + } + if (getProviderLabel(ctx.stdin)) { + return null; + } + const label = dim('Usage'); + if (ctx.usageData.apiUnavailable) { + const errorHint = formatUsageError(ctx.usageData.apiError); + return `${label} ${warning(`⚠${errorHint}`, colors)}`; + } + if (isLimitReached(ctx.usageData)) { + const resetTime = ctx.usageData.fiveHour === 100 + ? formatResetTime(ctx.usageData.fiveHourResetAt) + : formatResetTime(ctx.usageData.sevenDayResetAt); + return `${label} ${critical(`⚠ Limit reached${resetTime ? ` (resets ${resetTime})` : ''}`, colors)}`; + } + const threshold = display?.usageThreshold ?? 0; + const fiveHour = ctx.usageData.fiveHour; + const sevenDay = ctx.usageData.sevenDay; + const effectiveUsage = Math.max(fiveHour ?? 0, sevenDay ?? 0); + if (effectiveUsage < threshold) { + return null; + } + const fiveHourDisplay = formatUsagePercent(ctx.usageData.fiveHour, colors); + const fiveHourReset = formatResetTime(ctx.usageData.fiveHourResetAt); + const usageBarEnabled = display?.usageBarEnabled ?? true; + const fiveHourPart = usageBarEnabled + ? (fiveHourReset + ? `${quotaBar(fiveHour ?? 0, getAdaptiveBarWidth(), colors)} ${fiveHourDisplay} (${fiveHourReset} / 5h)` + : `${quotaBar(fiveHour ?? 0, getAdaptiveBarWidth(), colors)} ${fiveHourDisplay}`) + : (fiveHourReset + ? `5h: ${fiveHourDisplay} (${fiveHourReset})` + : `5h: ${fiveHourDisplay}`); + const sevenDayThreshold = display?.sevenDayThreshold ?? 80; + const syncingSuffix = ctx.usageData.apiError === 'rate-limited' + ? ` ${dim('(syncing...)')}` + : ''; + if (sevenDay !== null && sevenDay >= sevenDayThreshold) { + const sevenDayDisplay = formatUsagePercent(sevenDay, colors); + const sevenDayReset = formatResetTime(ctx.usageData.sevenDayResetAt); + const sevenDayPart = usageBarEnabled + ? (sevenDayReset + ? `${quotaBar(sevenDay, getAdaptiveBarWidth(), colors)} ${sevenDayDisplay} (${sevenDayReset} / 7d)` + : `${quotaBar(sevenDay, getAdaptiveBarWidth(), colors)} ${sevenDayDisplay}`) + : (sevenDayReset + ? `7d: ${sevenDayDisplay} (${sevenDayReset})` + : `7d: ${sevenDayDisplay}`); + return `${label} ${fiveHourPart} | ${sevenDayPart}${syncingSuffix}`; + } + return `${label} ${fiveHourPart}${syncingSuffix}`; +} +function formatUsagePercent(percent, colors) { + if (percent === null) { + return dim('--'); + } + const color = getQuotaColor(percent, colors); + return `${color}${percent}%${RESET}`; +} +function formatUsageError(error) { + if (!error) + return ''; + if (error === 'rate-limited') + return ' (syncing...)'; + if (error.startsWith('http-')) + return ` (${error.slice(5)})`; + return ` (${error})`; +} +function formatResetTime(resetAt) { + if (!resetAt) + return ''; + const now = new Date(); + const diffMs = resetAt.getTime() - now.getTime(); + if (diffMs <= 0) + return ''; + const diffMins = Math.ceil(diffMs / 60000); + if (diffMins < 60) + return `${diffMins}m`; + const hours = Math.floor(diffMins / 60); + const mins = diffMins % 60; + if (hours >= 24) { + const days = Math.floor(hours / 24); + const remHours = hours % 24; + if (remHours > 0) + return `${days}d ${remHours}h`; + return `${days}d`; + } + return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`; +} +//# sourceMappingURL=usage.js.map \ No newline at end of file diff --git a/dist/render/lines/usage.js.map b/dist/render/lines/usage.js.map new file mode 100644 index 0000000..8c119ec --- /dev/null +++ b/dist/render/lines/usage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/render/lines/usage.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/render/session-line.d.ts b/dist/render/session-line.d.ts new file mode 100644 index 0000000..5cff9f6 --- /dev/null +++ b/dist/render/session-line.d.ts @@ -0,0 +1,7 @@ +import type { RenderContext } from '../types.js'; +/** + * Renders the full session line (model + context bar + project + git + counts + usage + duration). + * Used for compact layout mode. + */ +export declare function renderSessionLine(ctx: RenderContext): string; +//# sourceMappingURL=session-line.d.ts.map \ No newline at end of file diff --git a/dist/render/session-line.d.ts.map b/dist/render/session-line.d.ts.map new file mode 100644 index 0000000..8da99c7 --- /dev/null +++ b/dist/render/session-line.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"session-line.d.ts","sourceRoot":"","sources":["../../src/render/session-line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAiN5D"} \ No newline at end of file diff --git a/dist/render/session-line.js b/dist/render/session-line.js new file mode 100644 index 0000000..cd61220 --- /dev/null +++ b/dist/render/session-line.js @@ -0,0 +1,263 @@ +import { isLimitReached } from '../types.js'; +import { getContextPercent, getBufferedPercent, getModelName, getProviderLabel, getTotalTokens } from '../stdin.js'; +import { getOutputSpeed } from '../speed-tracker.js'; +import { coloredBar, critical, cyan, dim, magenta, red, warning, yellow, getContextColor, getQuotaColor, quotaBar, RESET } from './colors.js'; +import { getAdaptiveBarWidth } from '../utils/terminal.js'; +const DEBUG = process.env.DEBUG?.includes('claude-hud') || process.env.DEBUG === '*'; +/** + * Renders the full session line (model + context bar + project + git + counts + usage + duration). + * Used for compact layout mode. + */ +export function renderSessionLine(ctx) { + const model = getModelName(ctx.stdin); + const rawPercent = getContextPercent(ctx.stdin); + const bufferedPercent = getBufferedPercent(ctx.stdin); + const autocompactMode = ctx.config?.display?.autocompactBuffer ?? 'enabled'; + const percent = autocompactMode === 'disabled' ? rawPercent : bufferedPercent; + if (DEBUG && autocompactMode === 'disabled') { + console.error(`[claude-hud:context] autocompactBuffer=disabled, showing raw ${rawPercent}% (buffered would be ${bufferedPercent}%)`); + } + const colors = ctx.config?.colors; + const barWidth = getAdaptiveBarWidth(); + const bar = coloredBar(percent, barWidth, colors); + const parts = []; + const display = ctx.config?.display; + const contextValueMode = display?.contextValue ?? 'percent'; + const contextValue = formatContextValue(ctx, percent, contextValueMode); + const contextValueDisplay = `${getContextColor(percent, colors)}${contextValue}${RESET}`; + // Model and context bar (FIRST) + // Plan name only shows if showUsage is enabled (respects hybrid toggle) + const providerLabel = getProviderLabel(ctx.stdin); + const showUsage = display?.showUsage !== false; + const planName = showUsage ? ctx.usageData?.planName : undefined; + const hasApiKey = !!process.env.ANTHROPIC_API_KEY; + const billingLabel = showUsage ? (planName ?? (hasApiKey ? red('API') : undefined)) : undefined; + const planDisplay = providerLabel ?? billingLabel; + const modelDisplay = planDisplay ? `${model} | ${planDisplay}` : model; + if (display?.showModel !== false && display?.showContextBar !== false) { + parts.push(`${cyan(`[${modelDisplay}]`)} ${bar} ${contextValueDisplay}`); + } + else if (display?.showModel !== false) { + parts.push(`${cyan(`[${modelDisplay}]`)} ${contextValueDisplay}`); + } + else if (display?.showContextBar !== false) { + parts.push(`${bar} ${contextValueDisplay}`); + } + else { + parts.push(contextValueDisplay); + } + // Project path + git status (SECOND) + let projectPart = null; + if (display?.showProject !== false && ctx.stdin.cwd) { + // Split by both Unix (/) and Windows (\) separators for cross-platform support + const segments = ctx.stdin.cwd.split(/[/\\]/).filter(Boolean); + const pathLevels = ctx.config?.pathLevels ?? 1; + // Always join with forward slash for consistent display + // Handle root path (/) which results in empty segments + const projectPath = segments.length > 0 ? segments.slice(-pathLevels).join('/') : '/'; + projectPart = yellow(projectPath); + } + let gitPart = ''; + const gitConfig = ctx.config?.gitStatus; + const showGit = gitConfig?.enabled ?? true; + if (showGit && ctx.gitStatus) { + const gitParts = [ctx.gitStatus.branch]; + // Show dirty indicator + if ((gitConfig?.showDirty ?? true) && ctx.gitStatus.isDirty) { + gitParts.push('*'); + } + // Show ahead/behind (with space separator for readability) + if (gitConfig?.showAheadBehind) { + if (ctx.gitStatus.ahead > 0) { + gitParts.push(` ↑${ctx.gitStatus.ahead}`); + } + if (ctx.gitStatus.behind > 0) { + gitParts.push(` ↓${ctx.gitStatus.behind}`); + } + } + // Show file stats in Starship-compatible format (!modified +added ✘deleted ?untracked) + if (gitConfig?.showFileStats && ctx.gitStatus.fileStats) { + const { modified, added, deleted, untracked } = ctx.gitStatus.fileStats; + const statParts = []; + if (modified > 0) + statParts.push(`!${modified}`); + if (added > 0) + statParts.push(`+${added}`); + if (deleted > 0) + statParts.push(`✘${deleted}`); + if (untracked > 0) + statParts.push(`?${untracked}`); + if (statParts.length > 0) { + gitParts.push(` ${statParts.join(' ')}`); + } + } + gitPart = `${magenta('git:(')}${cyan(gitParts.join(''))}${magenta(')')}`; + } + if (projectPart && gitPart) { + parts.push(`${projectPart} ${gitPart}`); + } + else if (projectPart) { + parts.push(projectPart); + } + else if (gitPart) { + parts.push(gitPart); + } + // Session name (custom title from /rename, or auto-generated slug) + if (display?.showSessionName && ctx.transcript.sessionName) { + parts.push(dim(ctx.transcript.sessionName)); + } + // Config counts (respects environmentThreshold) + if (display?.showConfigCounts !== false) { + const totalCounts = ctx.claudeMdCount + ctx.rulesCount + ctx.mcpCount + ctx.hooksCount; + const envThreshold = display?.environmentThreshold ?? 0; + if (totalCounts > 0 && totalCounts >= envThreshold) { + if (ctx.claudeMdCount > 0) { + parts.push(dim(`${ctx.claudeMdCount} CLAUDE.md`)); + } + if (ctx.rulesCount > 0) { + parts.push(dim(`${ctx.rulesCount} rules`)); + } + if (ctx.mcpCount > 0) { + parts.push(dim(`${ctx.mcpCount} MCPs`)); + } + if (ctx.hooksCount > 0) { + parts.push(dim(`${ctx.hooksCount} hooks`)); + } + } + } + // Usage limits display (shown when enabled in config, respects usageThreshold) + if (display?.showUsage !== false && ctx.usageData?.planName && !providerLabel) { + if (ctx.usageData.apiUnavailable) { + const errorHint = formatUsageError(ctx.usageData.apiError); + parts.push(warning(`usage: ⚠${errorHint}`, colors)); + } + else if (isLimitReached(ctx.usageData)) { + const resetTime = ctx.usageData.fiveHour === 100 + ? formatResetTime(ctx.usageData.fiveHourResetAt) + : formatResetTime(ctx.usageData.sevenDayResetAt); + parts.push(critical(`⚠ Limit reached${resetTime ? ` (resets ${resetTime})` : ''}`, colors)); + } + else { + const usageThreshold = display?.usageThreshold ?? 0; + const fiveHour = ctx.usageData.fiveHour; + const sevenDay = ctx.usageData.sevenDay; + const effectiveUsage = Math.max(fiveHour ?? 0, sevenDay ?? 0); + if (effectiveUsage >= usageThreshold) { + const syncingSuffix = ctx.usageData.apiError === 'rate-limited' + ? ` ${dim('(syncing...)')}` + : ''; + const fiveHourDisplay = formatUsagePercent(fiveHour, colors); + const fiveHourReset = formatResetTime(ctx.usageData.fiveHourResetAt); + const usageBarEnabled = display?.usageBarEnabled ?? true; + const fiveHourPart = usageBarEnabled + ? (fiveHourReset + ? `${quotaBar(fiveHour ?? 0, barWidth, colors)} ${fiveHourDisplay} (${fiveHourReset} / 5h)` + : `${quotaBar(fiveHour ?? 0, barWidth, colors)} ${fiveHourDisplay}`) + : (fiveHourReset + ? `5h: ${fiveHourDisplay} (${fiveHourReset})` + : `5h: ${fiveHourDisplay}`); + const sevenDayThreshold = display?.sevenDayThreshold ?? 80; + if (sevenDay !== null && sevenDay >= sevenDayThreshold) { + const sevenDayDisplay = formatUsagePercent(sevenDay, colors); + const sevenDayReset = formatResetTime(ctx.usageData.sevenDayResetAt); + const sevenDayPart = usageBarEnabled + ? (sevenDayReset + ? `${quotaBar(sevenDay, barWidth, colors)} ${sevenDayDisplay} (${sevenDayReset} / 7d)` + : `${quotaBar(sevenDay, barWidth, colors)} ${sevenDayDisplay}`) + : (sevenDayReset + ? `7d: ${sevenDayDisplay} (${sevenDayReset})` + : `7d: ${sevenDayDisplay}`); + parts.push(`${fiveHourPart} | ${sevenDayPart}${syncingSuffix}`); + } + else { + parts.push(`${fiveHourPart}${syncingSuffix}`); + } + } + } + } + // Session duration + if (display?.showSpeed) { + const speed = getOutputSpeed(ctx.stdin); + if (speed !== null) { + parts.push(dim(`out: ${speed.toFixed(1)} tok/s`)); + } + } + if (display?.showDuration !== false && ctx.sessionDuration) { + parts.push(dim(`⏱️ ${ctx.sessionDuration}`)); + } + if (ctx.extraLabel) { + parts.push(dim(ctx.extraLabel)); + } + let line = parts.join(' | '); + // Token breakdown at high context + if (display?.showTokenBreakdown !== false && percent >= 85) { + const usage = ctx.stdin.context_window?.current_usage; + if (usage) { + const input = formatTokens(usage.input_tokens ?? 0); + const cache = formatTokens((usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0)); + line += dim(` (in: ${input}, cache: ${cache})`); + } + } + return line; +} +function formatTokens(n) { + if (n >= 1000000) { + return `${(n / 1000000).toFixed(1)}M`; + } + if (n >= 1000) { + return `${(n / 1000).toFixed(0)}k`; + } + return n.toString(); +} +function formatContextValue(ctx, percent, mode) { + if (mode === 'tokens') { + const totalTokens = getTotalTokens(ctx.stdin); + const size = ctx.stdin.context_window?.context_window_size ?? 0; + if (size > 0) { + return `${formatTokens(totalTokens)}/${formatTokens(size)}`; + } + return formatTokens(totalTokens); + } + if (mode === 'remaining') { + return `${Math.max(0, 100 - percent)}%`; + } + return `${percent}%`; +} +function formatUsagePercent(percent, colors) { + if (percent === null) { + return dim('--'); + } + const color = getQuotaColor(percent, colors); + return `${color}${percent}%${RESET}`; +} +function formatUsageError(error) { + if (!error) + return ''; + if (error === 'rate-limited') + return ' (syncing...)'; + if (error.startsWith('http-')) + return ` (${error.slice(5)})`; + return ` (${error})`; +} +function formatResetTime(resetAt) { + if (!resetAt) + return ''; + const now = new Date(); + const diffMs = resetAt.getTime() - now.getTime(); + if (diffMs <= 0) + return ''; + const diffMins = Math.ceil(diffMs / 60000); + if (diffMins < 60) + return `${diffMins}m`; + const hours = Math.floor(diffMins / 60); + const mins = diffMins % 60; + if (hours >= 24) { + const days = Math.floor(hours / 24); + const remHours = hours % 24; + if (remHours > 0) + return `${days}d ${remHours}h`; + return `${days}d`; + } + return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`; +} +//# sourceMappingURL=session-line.js.map \ No newline at end of file diff --git a/dist/render/session-line.js.map b/dist/render/session-line.js.map new file mode 100644 index 0000000..c82ecee --- /dev/null +++ b/dist/render/session-line.js.map @@ -0,0 +1 @@ +{"version":3,"file":"session-line.js","sourceRoot":"","sources":["../../src/render/session-line.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9I,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;AAErF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAkB;IAClD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEtC,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,eAAe,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,iBAAiB,IAAI,SAAS,CAAC;IAC5E,MAAM,OAAO,GAAG,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC;IAE9E,IAAI,KAAK,IAAI,eAAe,KAAK,UAAU,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,gEAAgE,UAAU,wBAAwB,eAAe,IAAI,CAAC,CAAC;IACvI,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAClC,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAElD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IACpC,MAAM,gBAAgB,GAAG,OAAO,EAAE,YAAY,IAAI,SAAS,CAAC;IAC5D,MAAM,YAAY,GAAG,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACxE,MAAM,mBAAmB,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,YAAY,GAAG,KAAK,EAAE,CAAC;IAEzF,gCAAgC;IAChC,wEAAwE;IACxE,MAAM,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,KAAK,KAAK,CAAC;IAC/C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAClD,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChG,MAAM,WAAW,GAAG,aAAa,IAAI,YAAY,CAAC;IAClD,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAEvE,IAAI,OAAO,EAAE,SAAS,KAAK,KAAK,IAAI,OAAO,EAAE,cAAc,KAAK,KAAK,EAAE,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,YAAY,GAAG,CAAC,IAAI,GAAG,IAAI,mBAAmB,EAAE,CAAC,CAAC;IAC3E,CAAC;SAAM,IAAI,OAAO,EAAE,SAAS,KAAK,KAAK,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,YAAY,GAAG,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,IAAI,OAAO,EAAE,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,mBAAmB,EAAE,CAAC,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,CAAC;IAED,qCAAqC;IACrC,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,OAAO,EAAE,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACpD,+EAA+E;QAC/E,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,IAAI,CAAC,CAAC;QAC/C,wDAAwD;QACxD,uDAAuD;QACvD,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACtF,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IACxC,MAAM,OAAO,GAAG,SAAS,EAAE,OAAO,IAAI,IAAI,CAAC;IAE3C,IAAI,OAAO,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAa,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAElD,uBAAuB;QACvB,IAAI,CAAC,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YAC5D,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAED,2DAA2D;QAC3D,IAAI,SAAS,EAAE,eAAe,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,IAAI,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,uFAAuF;QACvF,IAAI,SAAS,EAAE,aAAa,IAAI,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;YACxD,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC;YACxE,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,IAAI,QAAQ,GAAG,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;YACjD,IAAI,KAAK,GAAG,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;YAC3C,IAAI,OAAO,GAAG,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;YAC/C,IAAI,SAAS,GAAG,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;YACnD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,OAAO,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,WAAW,IAAI,OAAO,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;SAAM,IAAI,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,mEAAmE;IACnE,IAAI,OAAO,EAAE,eAAe,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,gDAAgD;IAChD,IAAI,OAAO,EAAE,gBAAgB,KAAK,KAAK,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC;QACvF,MAAM,YAAY,GAAG,OAAO,EAAE,oBAAoB,IAAI,CAAC,CAAC;QAExD,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,IAAI,YAAY,EAAE,CAAC;YACnD,IAAI,GAAG,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,aAAa,YAAY,CAAC,CAAC,CAAC;YACpD,CAAC;YAED,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC;YAC7C,CAAC;YAED,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,IAAI,OAAO,EAAE,SAAS,KAAK,KAAK,IAAI,GAAG,CAAC,SAAS,EAAE,QAAQ,IAAI,CAAC,aAAa,EAAE,CAAC;QAC9E,IAAI,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC3D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,KAAK,GAAG;gBAC9C,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC;gBAChD,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,SAAS,CAAC,CAAC,CAAC,YAAY,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9F,CAAC;aAAM,CAAC;YACN,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,CAAC,CAAC;YACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC;YACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC;YACxC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC;YAE9D,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;gBACrC,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,KAAK,cAAc;oBAC7D,CAAC,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,EAAE;oBAC3B,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAC7D,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;gBAErE,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,IAAI,CAAC;gBACzD,MAAM,YAAY,GAAG,eAAe;oBAClC,CAAC,CAAC,CAAC,aAAa;wBACZ,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,eAAe,KAAK,aAAa,QAAQ;wBAC3F,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;oBACxE,CAAC,CAAC,CAAC,aAAa;wBACZ,CAAC,CAAC,OAAO,eAAe,KAAK,aAAa,GAAG;wBAC7C,CAAC,CAAC,OAAO,eAAe,EAAE,CAAC,CAAC;gBAElC,MAAM,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,IAAI,EAAE,CAAC;gBAC3D,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,IAAI,iBAAiB,EAAE,CAAC;oBACvD,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAC7D,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;oBACrE,MAAM,YAAY,GAAG,eAAe;wBAClC,CAAC,CAAC,CAAC,aAAa;4BACZ,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,eAAe,KAAK,aAAa,QAAQ;4BACtF,CAAC,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;wBACnE,CAAC,CAAC,CAAC,aAAa;4BACZ,CAAC,CAAC,OAAO,eAAe,KAAK,aAAa,GAAG;4BAC7C,CAAC,CAAC,OAAO,eAAe,EAAE,CAAC,CAAC;oBAClC,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,MAAM,YAAY,GAAG,aAAa,EAAE,CAAC,CAAC;gBAClE,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,GAAG,aAAa,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,YAAY,KAAK,KAAK,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE7B,kCAAkC;IAClC,IAAI,OAAO,EAAE,kBAAkB,KAAK,KAAK,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAC3D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,aAAa,CAAC;QACtD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;YACpD,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5G,IAAI,IAAI,GAAG,CAAC,SAAS,KAAK,YAAY,KAAK,GAAG,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACjB,OAAO,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACxC,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACd,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAkB,EAAE,OAAe,EAAE,IAAwC;IACvG,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,mBAAmB,IAAI,CAAC,CAAC;QAChE,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9D,CAAC;QACD,OAAO,YAAY,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,OAAO,GAAG,OAAO,GAAG,CAAC;AACvB,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAsB,EAAE,MAA0C;IAC5F,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,GAAG,KAAK,GAAG,OAAO,IAAI,KAAK,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,IAAI,KAAK,KAAK,cAAc;QAAE,OAAO,eAAe,CAAC;IACrD,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7D,OAAO,KAAK,KAAK,GAAG,CAAC;AACvB,CAAC;AAED,SAAS,eAAe,CAAC,OAAoB;IAC3C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;IACjD,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;IAC3C,IAAI,QAAQ,GAAG,EAAE;QAAE,OAAO,GAAG,QAAQ,GAAG,CAAC;IAEzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,QAAQ,GAAG,EAAE,CAAC;IAE3B,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,KAAK,GAAG,EAAE,CAAC;QAC5B,IAAI,QAAQ,GAAG,CAAC;YAAE,OAAO,GAAG,IAAI,KAAK,QAAQ,GAAG,CAAC;QACjD,OAAO,GAAG,IAAI,GAAG,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC;AACvD,CAAC"} \ No newline at end of file diff --git a/dist/render/todos-line.d.ts b/dist/render/todos-line.d.ts new file mode 100644 index 0000000..f69647c --- /dev/null +++ b/dist/render/todos-line.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../types.js'; +export declare function renderTodosLine(ctx: RenderContext): string | null; +//# sourceMappingURL=todos-line.d.ts.map \ No newline at end of file diff --git a/dist/render/todos-line.d.ts.map b/dist/render/todos-line.d.ts.map new file mode 100644 index 0000000..f918f10 --- /dev/null +++ b/dist/render/todos-line.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"todos-line.d.ts","sourceRoot":"","sources":["../../src/render/todos-line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAsBjE"} \ No newline at end of file diff --git a/dist/render/todos-line.js b/dist/render/todos-line.js new file mode 100644 index 0000000..ce5aa16 --- /dev/null +++ b/dist/render/todos-line.js @@ -0,0 +1,25 @@ +import { yellow, green, dim } from './colors.js'; +export function renderTodosLine(ctx) { + const { todos } = ctx.transcript; + if (!todos || todos.length === 0) { + return null; + } + const inProgress = todos.find((t) => t.status === 'in_progress'); + const completed = todos.filter((t) => t.status === 'completed').length; + const total = todos.length; + if (!inProgress) { + if (completed === total && total > 0) { + return `${green('✓')} All todos complete ${dim(`(${completed}/${total})`)}`; + } + return null; + } + const content = truncateContent(inProgress.content); + const progress = dim(`(${completed}/${total})`); + return `${yellow('▸')} ${content} ${progress}`; +} +function truncateContent(content, maxLen = 50) { + if (content.length <= maxLen) + return content; + return content.slice(0, maxLen - 3) + '...'; +} +//# sourceMappingURL=todos-line.js.map \ No newline at end of file diff --git a/dist/render/todos-line.js.map b/dist/render/todos-line.js.map new file mode 100644 index 0000000..dd50828 --- /dev/null +++ b/dist/render/todos-line.js.map @@ -0,0 +1 @@ +{"version":3,"file":"todos-line.js","sourceRoot":"","sources":["../../src/render/todos-line.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,UAAU,eAAe,CAAC,GAAkB;IAChD,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;IAEjC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,IAAI,SAAS,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACrC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,uBAAuB,GAAG,CAAC,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC9E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,SAAS,IAAI,KAAK,GAAG,CAAC,CAAC;IAEhD,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,eAAe,CAAC,OAAe,EAAE,SAAiB,EAAE;IAC3D,IAAI,OAAO,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,OAAO,CAAC;IAC7C,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AAC9C,CAAC"} \ No newline at end of file diff --git a/dist/render/tools-line.d.ts b/dist/render/tools-line.d.ts new file mode 100644 index 0000000..8fa919d --- /dev/null +++ b/dist/render/tools-line.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../types.js'; +export declare function renderToolsLine(ctx: RenderContext): string | null; +//# sourceMappingURL=tools-line.d.ts.map \ No newline at end of file diff --git a/dist/render/tools-line.d.ts.map b/dist/render/tools-line.d.ts.map new file mode 100644 index 0000000..0aeb587 --- /dev/null +++ b/dist/render/tools-line.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"tools-line.d.ts","sourceRoot":"","sources":["../../src/render/tools-line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAoCjE"} \ No newline at end of file diff --git a/dist/render/tools-line.js b/dist/render/tools-line.js new file mode 100644 index 0000000..5b53d73 --- /dev/null +++ b/dist/render/tools-line.js @@ -0,0 +1,43 @@ +import { yellow, green, cyan, dim } from './colors.js'; +export function renderToolsLine(ctx) { + const { tools } = ctx.transcript; + if (tools.length === 0) { + return null; + } + const parts = []; + const runningTools = tools.filter((t) => t.status === 'running'); + const completedTools = tools.filter((t) => t.status === 'completed' || t.status === 'error'); + for (const tool of runningTools.slice(-2)) { + const target = tool.target ? truncatePath(tool.target) : ''; + parts.push(`${yellow('◐')} ${cyan(tool.name)}${target ? dim(`: ${target}`) : ''}`); + } + const toolCounts = new Map(); + for (const tool of completedTools) { + const count = toolCounts.get(tool.name) ?? 0; + toolCounts.set(tool.name, count + 1); + } + const sortedTools = Array.from(toolCounts.entries()) + .sort((a, b) => b[1] - a[1]) + .slice(0, 4); + for (const [name, count] of sortedTools) { + parts.push(`${green('✓')} ${name} ${dim(`×${count}`)}`); + } + if (parts.length === 0) { + return null; + } + return parts.join(' | '); +} +function truncatePath(path, maxLen = 20) { + // Normalize Windows backslashes to forward slashes for consistent display + const normalizedPath = path.replace(/\\/g, '/'); + if (normalizedPath.length <= maxLen) + return normalizedPath; + // Split by forward slash (already normalized) + const parts = normalizedPath.split('/'); + const filename = parts.pop() || normalizedPath; + if (filename.length >= maxLen) { + return filename.slice(0, maxLen - 3) + '...'; + } + return '.../' + filename; +} +//# sourceMappingURL=tools-line.js.map \ No newline at end of file diff --git a/dist/render/tools-line.js.map b/dist/render/tools-line.js.map new file mode 100644 index 0000000..04e002a --- /dev/null +++ b/dist/render/tools-line.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tools-line.js","sourceRoot":"","sources":["../../src/render/tools-line.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/speed-tracker.d.ts b/dist/speed-tracker.d.ts new file mode 100644 index 0000000..1edca8e --- /dev/null +++ b/dist/speed-tracker.d.ts @@ -0,0 +1,7 @@ +import type { StdinData } from './types.js'; +export type SpeedTrackerDeps = { + homeDir: () => string; + now: () => number; +}; +export declare function getOutputSpeed(stdin: StdinData, overrides?: Partial): number | null; +//# sourceMappingURL=speed-tracker.d.ts.map \ No newline at end of file diff --git a/dist/speed-tracker.d.ts.map b/dist/speed-tracker.d.ts.map new file mode 100644 index 0000000..2be6f1a --- /dev/null +++ b/dist/speed-tracker.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"speed-tracker.d.ts","sourceRoot":"","sources":["../src/speed-tracker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB,CAAC;AAuCF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,MAAM,GAAG,IAAI,CAsBzG"} \ No newline at end of file diff --git a/dist/speed-tracker.js b/dist/speed-tracker.js new file mode 100644 index 0000000..12a2b10 --- /dev/null +++ b/dist/speed-tracker.js @@ -0,0 +1,62 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import * as os from 'node:os'; +import { getHudPluginDir } from './claude-config-dir.js'; +const SPEED_WINDOW_MS = 2000; +const defaultDeps = { + homeDir: () => os.homedir(), + now: () => Date.now(), +}; +function getCachePath(homeDir) { + return path.join(getHudPluginDir(homeDir), '.speed-cache.json'); +} +function readCache(homeDir) { + try { + const cachePath = getCachePath(homeDir); + if (!fs.existsSync(cachePath)) + return null; + const content = fs.readFileSync(cachePath, 'utf8'); + const parsed = JSON.parse(content); + if (typeof parsed.outputTokens !== 'number' || typeof parsed.timestamp !== 'number') { + return null; + } + return parsed; + } + catch { + return null; + } +} +function writeCache(homeDir, cache) { + try { + const cachePath = getCachePath(homeDir); + const cacheDir = path.dirname(cachePath); + if (!fs.existsSync(cacheDir)) { + fs.mkdirSync(cacheDir, { recursive: true }); + } + fs.writeFileSync(cachePath, JSON.stringify(cache), 'utf8'); + } + catch { + // Ignore cache write failures + } +} +export function getOutputSpeed(stdin, overrides = {}) { + const outputTokens = stdin.context_window?.current_usage?.output_tokens; + if (typeof outputTokens !== 'number' || !Number.isFinite(outputTokens)) { + return null; + } + const deps = { ...defaultDeps, ...overrides }; + const now = deps.now(); + const homeDir = deps.homeDir(); + const previous = readCache(homeDir); + let speed = null; + if (previous && outputTokens >= previous.outputTokens) { + const deltaTokens = outputTokens - previous.outputTokens; + const deltaMs = now - previous.timestamp; + if (deltaTokens > 0 && deltaMs > 0 && deltaMs <= SPEED_WINDOW_MS) { + speed = deltaTokens / (deltaMs / 1000); + } + } + writeCache(homeDir, { outputTokens, timestamp: now }); + return speed; +} +//# sourceMappingURL=speed-tracker.js.map \ No newline at end of file diff --git a/dist/speed-tracker.js.map b/dist/speed-tracker.js.map new file mode 100644 index 0000000..afcb93e --- /dev/null +++ b/dist/speed-tracker.js.map @@ -0,0 +1 @@ +{"version":3,"file":"speed-tracker.js","sourceRoot":"","sources":["../src/speed-tracker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/stdin.d.ts b/dist/stdin.d.ts new file mode 100644 index 0000000..01679a1 --- /dev/null +++ b/dist/stdin.d.ts @@ -0,0 +1,9 @@ +import type { StdinData } from './types.js'; +export declare function readStdin(): Promise; +export declare function getTotalTokens(stdin: StdinData): number; +export declare function getContextPercent(stdin: StdinData): number; +export declare function getBufferedPercent(stdin: StdinData): number; +export declare function getModelName(stdin: StdinData): string; +export declare function isBedrockModelId(modelId?: string): boolean; +export declare function getProviderLabel(stdin: StdinData): string | null; +//# sourceMappingURL=stdin.d.ts.map \ No newline at end of file diff --git a/dist/stdin.d.ts.map b/dist/stdin.d.ts.map new file mode 100644 index 0000000..305a598 --- /dev/null +++ b/dist/stdin.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../src/stdin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAoB3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAOvD;AAcD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAe1D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAyB3D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAarD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAM1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAKhE"} \ No newline at end of file diff --git a/dist/stdin.js b/dist/stdin.js new file mode 100644 index 0000000..520c9f7 --- /dev/null +++ b/dist/stdin.js @@ -0,0 +1,142 @@ +import { AUTOCOMPACT_BUFFER_PERCENT } from './constants.js'; +export async function readStdin() { + if (process.stdin.isTTY) { + return null; + } + const chunks = []; + try { + process.stdin.setEncoding('utf8'); + for await (const chunk of process.stdin) { + chunks.push(chunk); + } + const raw = chunks.join(''); + if (!raw.trim()) { + return null; + } + return JSON.parse(raw); + } + catch { + return null; + } +} +export function getTotalTokens(stdin) { + 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) { + 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) { + // 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) { + // Prefer native percentage (v2.1.6+) so the HUD matches Claude Code's + // own context output. The buffered fallback only approximates older versions. + 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); + // Scale buffer by raw usage: no buffer at ≤5% (e.g. after /clear), + // full buffer at ≥50%. Autocompact doesn't kick in at very low usage. + const rawRatio = totalTokens / size; + const LOW = 0.05; + const HIGH = 0.50; + const scale = Math.min(1, Math.max(0, (rawRatio - LOW) / (HIGH - LOW))); + const buffer = size * AUTOCOMPACT_BUFFER_PERCENT * scale; + return Math.min(100, Math.round(((totalTokens + buffer) / size) * 100)); +} +export function getModelName(stdin) { + const displayName = stdin.model?.display_name?.trim(); + if (displayName) { + return displayName; + } + const modelId = stdin.model?.id?.trim(); + if (!modelId) { + return 'Unknown'; + } + const normalizedBedrockLabel = normalizeBedrockModelLabel(modelId); + return normalizedBedrockLabel ?? modelId; +} +export function isBedrockModelId(modelId) { + if (!modelId) { + return false; + } + const normalized = modelId.toLowerCase(); + return normalized.includes('anthropic.claude-'); +} +export function getProviderLabel(stdin) { + if (isBedrockModelId(stdin.model?.id)) { + return 'Bedrock'; + } + return null; +} +function normalizeBedrockModelLabel(modelId) { + if (!isBedrockModelId(modelId)) { + return null; + } + const lowercaseId = modelId.toLowerCase(); + const claudePrefix = 'anthropic.claude-'; + const claudeIndex = lowercaseId.indexOf(claudePrefix); + if (claudeIndex === -1) { + return null; + } + let suffix = lowercaseId.slice(claudeIndex + claudePrefix.length); + suffix = suffix.replace(/-v\d+:\d+$/, ''); + suffix = suffix.replace(/-\d{8}$/, ''); + const tokens = suffix.split('-').filter(Boolean); + if (tokens.length === 0) { + return null; + } + const familyIndex = tokens.findIndex((token) => token === 'haiku' || token === 'sonnet' || token === 'opus'); + if (familyIndex === -1) { + return null; + } + const family = tokens[familyIndex]; + const beforeVersion = readNumericVersion(tokens, familyIndex - 1, -1).reverse(); + const afterVersion = readNumericVersion(tokens, familyIndex + 1, 1); + const versionParts = beforeVersion.length >= afterVersion.length ? beforeVersion : afterVersion; + const version = versionParts.length ? versionParts.join('.') : null; + const familyLabel = family[0].toUpperCase() + family.slice(1); + return version ? `Claude ${familyLabel} ${version}` : `Claude ${familyLabel}`; +} +function readNumericVersion(tokens, startIndex, step) { + const parts = []; + for (let i = startIndex; i >= 0 && i < tokens.length; i += step) { + if (!/^\d+$/.test(tokens[i])) { + break; + } + parts.push(tokens[i]); + if (parts.length === 2) { + break; + } + } + return parts; +} +//# sourceMappingURL=stdin.js.map \ No newline at end of file diff --git a/dist/stdin.js.map b/dist/stdin.js.map new file mode 100644 index 0000000..098f55b --- /dev/null +++ b/dist/stdin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../src/stdin.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/transcript.d.ts b/dist/transcript.d.ts new file mode 100644 index 0000000..6b95ac4 --- /dev/null +++ b/dist/transcript.d.ts @@ -0,0 +1,3 @@ +import type { TranscriptData } from './types.js'; +export declare function parseTranscript(transcriptPath: string): Promise; +//# sourceMappingURL=transcript.d.ts.map \ No newline at end of file diff --git a/dist/transcript.d.ts.map b/dist/transcript.d.ts.map new file mode 100644 index 0000000..e53648f --- /dev/null +++ b/dist/transcript.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,YAAY,CAAC;AAqBlF,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAkDrF"} \ No newline at end of file diff --git a/dist/transcript.js b/dist/transcript.js new file mode 100644 index 0000000..6a50e59 --- /dev/null +++ b/dist/transcript.js @@ -0,0 +1,189 @@ +import * as fs from 'fs'; +import * as readline from 'readline'; +export async function parseTranscript(transcriptPath) { + const result = { + tools: [], + agents: [], + todos: [], + }; + if (!transcriptPath || !fs.existsSync(transcriptPath)) { + return result; + } + const toolMap = new Map(); + const agentMap = new Map(); + let latestTodos = []; + const taskIdToIndex = new Map(); + let latestSlug; + let customTitle; + try { + const fileStream = fs.createReadStream(transcriptPath); + const rl = readline.createInterface({ + input: fileStream, + crlfDelay: Infinity, + }); + for await (const line of rl) { + if (!line.trim()) + continue; + try { + const entry = JSON.parse(line); + if (entry.type === 'custom-title' && typeof entry.customTitle === 'string') { + customTitle = entry.customTitle; + } + else if (typeof entry.slug === 'string') { + latestSlug = entry.slug; + } + processEntry(entry, toolMap, agentMap, taskIdToIndex, latestTodos, result); + } + catch { + // Skip malformed lines + } + } + } + catch { + // Return partial results on error + } + result.tools = Array.from(toolMap.values()).slice(-20); + result.agents = Array.from(agentMap.values()).slice(-10); + result.todos = latestTodos; + result.sessionName = customTitle ?? latestSlug; + return result; +} +function processEntry(entry, toolMap, agentMap, taskIdToIndex, latestTodos, result) { + const timestamp = entry.timestamp ? new Date(entry.timestamp) : new Date(); + if (!result.sessionStart && entry.timestamp) { + result.sessionStart = timestamp; + } + const content = entry.message?.content; + if (!content || !Array.isArray(content)) + return; + for (const block of content) { + if (block.type === 'tool_use' && block.id && block.name) { + const toolEntry = { + id: block.id, + name: block.name, + target: extractTarget(block.name, block.input), + status: 'running', + startTime: timestamp, + }; + if (block.name === 'Task') { + const input = block.input; + const agentEntry = { + id: block.id, + type: input?.subagent_type ?? 'unknown', + model: input?.model ?? undefined, + description: input?.description ?? undefined, + status: 'running', + startTime: timestamp, + }; + agentMap.set(block.id, agentEntry); + } + else if (block.name === 'TodoWrite') { + const input = block.input; + if (input?.todos && Array.isArray(input.todos)) { + latestTodos.length = 0; + taskIdToIndex.clear(); + latestTodos.push(...input.todos); + } + } + else if (block.name === 'TaskCreate') { + const input = block.input; + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description || 'Untitled task'; + const status = normalizeTaskStatus(input?.status) ?? 'pending'; + latestTodos.push({ content, status }); + const rawTaskId = input?.taskId; + const taskId = typeof rawTaskId === 'string' || typeof rawTaskId === 'number' + ? String(rawTaskId) + : block.id; + if (taskId) { + taskIdToIndex.set(taskId, latestTodos.length - 1); + } + } + else if (block.name === 'TaskUpdate') { + const input = block.input; + const index = resolveTaskIndex(input?.taskId, taskIdToIndex, latestTodos); + if (index !== null) { + const status = normalizeTaskStatus(input?.status); + if (status) { + latestTodos[index].status = status; + } + const subject = typeof input?.subject === 'string' ? input.subject : ''; + const description = typeof input?.description === 'string' ? input.description : ''; + const content = subject || description; + if (content) { + latestTodos[index].content = content; + } + } + } + else { + toolMap.set(block.id, toolEntry); + } + } + if (block.type === 'tool_result' && block.tool_use_id) { + const tool = toolMap.get(block.tool_use_id); + if (tool) { + tool.status = block.is_error ? 'error' : 'completed'; + tool.endTime = timestamp; + } + const agent = agentMap.get(block.tool_use_id); + if (agent) { + agent.status = 'completed'; + agent.endTime = timestamp; + } + } + } +} +function extractTarget(toolName, input) { + if (!input) + return undefined; + switch (toolName) { + case 'Read': + case 'Write': + case 'Edit': + return input.file_path ?? input.path; + case 'Glob': + return input.pattern; + case 'Grep': + return input.pattern; + case 'Bash': + const cmd = input.command; + return cmd?.slice(0, 30) + (cmd?.length > 30 ? '...' : ''); + } + return undefined; +} +function resolveTaskIndex(taskId, taskIdToIndex, latestTodos) { + if (typeof taskId === 'string' || typeof taskId === 'number') { + const key = String(taskId); + const mapped = taskIdToIndex.get(key); + if (typeof mapped === 'number') { + return mapped; + } + if (/^\d+$/.test(key)) { + const numericIndex = Number.parseInt(key, 10) - 1; + if (numericIndex >= 0 && numericIndex < latestTodos.length) { + return numericIndex; + } + } + } + return null; +} +function normalizeTaskStatus(status) { + if (typeof status !== 'string') + return null; + switch (status) { + case 'pending': + case 'not_started': + return 'pending'; + case 'in_progress': + case 'running': + return 'in_progress'; + case 'completed': + case 'complete': + case 'done': + return 'completed'; + default: + return null; + } +} +//# sourceMappingURL=transcript.js.map \ No newline at end of file diff --git a/dist/transcript.js.map b/dist/transcript.js.map new file mode 100644 index 0000000..bdf0dba --- /dev/null +++ b/dist/transcript.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts new file mode 100644 index 0000000..98d653c --- /dev/null +++ b/dist/types.d.ts @@ -0,0 +1,79 @@ +import type { HudConfig } from './config.js'; +import type { GitStatus } from './git.js'; +export interface StdinData { + transcript_path?: string; + cwd?: string; + model?: { + id?: string; + display_name?: string; + }; + context_window?: { + context_window_size?: number; + current_usage?: { + input_tokens?: number; + output_tokens?: number; + cache_creation_input_tokens?: number; + cache_read_input_tokens?: number; + } | null; + used_percentage?: number | null; + remaining_percentage?: number | null; + }; +} +export interface ToolEntry { + id: string; + name: string; + target?: string; + status: 'running' | 'completed' | 'error'; + startTime: Date; + endTime?: Date; +} +export interface AgentEntry { + id: string; + type: string; + model?: string; + description?: string; + status: 'running' | 'completed'; + startTime: Date; + endTime?: Date; +} +export interface TodoItem { + content: string; + status: 'pending' | 'in_progress' | 'completed'; +} +/** Usage window data from the OAuth API */ +export interface UsageWindow { + utilization: number | null; + resetAt: Date | null; +} +export interface UsageData { + planName: string | null; + fiveHour: number | null; + sevenDay: number | null; + fiveHourResetAt: Date | null; + sevenDayResetAt: Date | null; + apiUnavailable?: boolean; + apiError?: string; +} +/** Check if usage limit is reached (either window at 100%) */ +export declare function isLimitReached(data: UsageData): boolean; +export interface TranscriptData { + tools: ToolEntry[]; + agents: AgentEntry[]; + todos: TodoItem[]; + sessionStart?: Date; + sessionName?: string; +} +export interface RenderContext { + stdin: StdinData; + transcript: TranscriptData; + claudeMdCount: number; + rulesCount: number; + mcpCount: number; + hooksCount: number; + sessionDuration: string; + gitStatus: GitStatus | null; + usageData: UsageData | null; + config: HudConfig; + extraLabel: string | null; +} +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/dist/types.d.ts.map b/dist/types.d.ts.map new file mode 100644 index 0000000..423e9c5 --- /dev/null +++ b/dist/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..6f773f9 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,5 @@ +/** Check if usage limit is reached (either window at 100%) */ +export function isLimitReached(data) { + return data.fiveHour === 100 || data.sevenDay === 100; +} +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/types.js.map b/dist/types.js.map new file mode 100644 index 0000000..e61dcfa --- /dev/null +++ b/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgEA,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,IAAe;IAC5C,OAAO,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC;AACxD,CAAC"} \ No newline at end of file diff --git a/dist/usage-api.d.ts b/dist/usage-api.d.ts new file mode 100644 index 0000000..9591a9b --- /dev/null +++ b/dist/usage-api.d.ts @@ -0,0 +1,62 @@ +import type { UsageData } from './types.js'; +export type { UsageData } from './types.js'; +interface UsageApiResponse { + five_hour?: { + utilization?: number; + resets_at?: string; + }; + seven_day?: { + utilization?: number; + resets_at?: string; + }; +} +interface UsageApiResult { + data: UsageApiResponse | null; + error?: string; + /** Retry-After header value in seconds (from 429 responses) */ + retryAfterSec?: number; +} +export declare const USAGE_API_USER_AGENT = "claude-code/2.1"; +type CacheTtls = { + cacheTtlMs: number; + failureCacheTtlMs: number; +}; +export type UsageApiDeps = { + homeDir: () => string; + fetchApi: (accessToken: string) => Promise; + now: () => number; + readKeychain: (now: number, homeDir: string) => { + accessToken: string; + subscriptionType: string; + } | null; + ttls: CacheTtls; +}; +/** + * Get OAuth usage data from Anthropic API. + * Returns null if user is an API user (no OAuth credentials) or credentials are expired. + * Returns { apiUnavailable: true, ... } if API call fails (to show warning in HUD). + * + * Uses file-based cache since HUD runs as a new process each render (~300ms). + * Cache TTL is configurable via usage.cacheTtlSeconds / usage.failureCacheTtlSeconds in config.json + * (defaults: 60s for success, 15s for failures). + */ +export declare function getUsage(overrides?: Partial): Promise; +/** + * Determine the macOS Keychain service name for Claude Code credentials. + * Claude Code uses the default service for ~/.claude and a hashed suffix for custom config directories. + */ +export declare function getKeychainServiceName(configDir: string, homeDir: string): string; +export declare function getKeychainServiceNames(configDir: string, homeDir: string, env?: NodeJS.ProcessEnv): string[]; +export declare function resolveKeychainCredentials(serviceNames: string[], now: number, loadService: (serviceName: string, accountName?: string) => string, accountName?: string | null): { + credentials: { + accessToken: string; + subscriptionType: string; + } | null; + shouldBackoff: boolean; +}; +export declare function getUsageApiTimeoutMs(env?: NodeJS.ProcessEnv): number; +export declare function isNoProxy(hostname: string, env?: NodeJS.ProcessEnv): boolean; +export declare function getProxyUrl(hostname: string, env?: NodeJS.ProcessEnv): URL | null; +export declare function parseRetryAfterSeconds(raw: string | string[] | undefined, nowMs?: number): number | undefined; +export declare function clearCache(homeDir?: string): void; +//# sourceMappingURL=usage-api.d.ts.map \ No newline at end of file diff --git a/dist/usage-api.d.ts.map b/dist/usage-api.d.ts.map new file mode 100644 index 0000000..ad42443 --- /dev/null +++ b/dist/usage-api.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"usage-api.d.ts","sourceRoot":"","sources":["../src/usage-api.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgB5C,UAAU,gBAAgB;IACxB,SAAS,CAAC,EAAE;QACV,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAaD,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AA4DtD,KAAK,SAAS,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC;AA6NnE,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3D,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzG,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAUF;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAqH/F;AAyCD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUjF;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAkBV;AAmBD,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,MAAM,EAAE,EACtB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,MAAM,EAClE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B;IAAE,WAAW,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAgDnG;AAkND,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAUjF;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAazF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,GAAG,GAAG,IAAI,CAyB9F;AA+JD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAClC,KAAK,GAAE,MAAmB,GACzB,MAAM,GAAG,SAAS,CAgBpB;AAGD,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAejD"} \ No newline at end of file diff --git a/dist/usage-api.js b/dist/usage-api.js new file mode 100644 index 0000000..a3eedce --- /dev/null +++ b/dist/usage-api.js @@ -0,0 +1,908 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import * as net from 'net'; +import * as tls from 'tls'; +import * as https from 'https'; +import { execFileSync } from 'child_process'; +import { createHash } from 'crypto'; +import { createDebug } from './debug.js'; +import { getClaudeConfigDir, getHudPluginDir } from './claude-config-dir.js'; +const debug = createDebug('usage'); +const LEGACY_KEYCHAIN_SERVICE_NAME = 'Claude Code-credentials'; +// File-based cache (HUD runs as new process each render, so in-memory cache won't persist) +const CACHE_TTL_MS = 5 * 60_000; // 5 minutes — matches Anthropic usage API rate limit window +const CACHE_FAILURE_TTL_MS = 15_000; // 15 seconds for failed requests +const CACHE_RATE_LIMITED_BASE_MS = 60_000; // 60s base for 429 backoff +const CACHE_RATE_LIMITED_MAX_MS = 5 * 60_000; // 5 min max backoff +const CACHE_LOCK_STALE_MS = 30_000; +const CACHE_LOCK_WAIT_MS = 2_000; +const CACHE_LOCK_POLL_MS = 50; +const KEYCHAIN_TIMEOUT_MS = 3000; +const KEYCHAIN_BACKOFF_MS = 60_000; // Backoff on keychain failures to avoid re-prompting +const USAGE_API_TIMEOUT_MS_DEFAULT = 15_000; +export const USAGE_API_USER_AGENT = 'claude-code/2.1'; +/** + * Check if user is using a custom API endpoint instead of the default Anthropic API. + * When using custom providers (e.g., via cc-switch), the OAuth usage API is not applicable. + */ +function isUsingCustomApiEndpoint(env = process.env) { + const baseUrl = env.ANTHROPIC_BASE_URL?.trim() || env.ANTHROPIC_API_BASE_URL?.trim(); + // No custom endpoint configured - using default Anthropic API + if (!baseUrl) { + return false; + } + try { + return new URL(baseUrl).origin !== 'https://api.anthropic.com'; + } + catch { + return true; + } +} +function getCachePath(homeDir) { + return path.join(getHudPluginDir(homeDir), '.usage-cache.json'); +} +function getCacheLockPath(homeDir) { + return path.join(getHudPluginDir(homeDir), '.usage-cache.lock'); +} +function hydrateCacheData(data) { + // JSON.stringify converts Date to ISO string, so we need to reconvert on read. + // new Date() handles both Date objects and ISO strings safely. + if (data.fiveHourResetAt) { + data.fiveHourResetAt = new Date(data.fiveHourResetAt); + } + if (data.sevenDayResetAt) { + data.sevenDayResetAt = new Date(data.sevenDayResetAt); + } + return data; +} +function getRateLimitedTtlMs(count) { + // Exponential backoff: 60s, 120s, 240s, capped at 5 min + return Math.min(CACHE_RATE_LIMITED_BASE_MS * Math.pow(2, Math.max(0, count - 1)), CACHE_RATE_LIMITED_MAX_MS); +} +function getRateLimitedRetryUntil(cache) { + if (cache.data.apiError !== 'rate-limited') { + return null; + } + if (cache.retryAfterUntil && cache.retryAfterUntil > cache.timestamp) { + return cache.retryAfterUntil; + } + if (cache.rateLimitedCount && cache.rateLimitedCount > 0) { + return cache.timestamp + getRateLimitedTtlMs(cache.rateLimitedCount); + } + return null; +} +function withRateLimitedSyncing(data) { + return { + ...data, + apiError: 'rate-limited', + }; +} +function readCacheState(homeDir, now, ttls) { + try { + const cachePath = getCachePath(homeDir); + if (!fs.existsSync(cachePath)) + return null; + const content = fs.readFileSync(cachePath, 'utf8'); + const cache = JSON.parse(content); + // Only serve lastGoodData during rate-limit backoff. Other failures should remain visible. + const displayData = (cache.data.apiError === 'rate-limited' && cache.lastGoodData) + ? withRateLimitedSyncing(cache.lastGoodData) + : cache.data; + const rateLimitedRetryUntil = getRateLimitedRetryUntil(cache); + if (rateLimitedRetryUntil && now < rateLimitedRetryUntil) { + return { data: hydrateCacheData(displayData), timestamp: cache.timestamp, isFresh: true }; + } + const ttl = cache.data.apiUnavailable ? ttls.failureCacheTtlMs : ttls.cacheTtlMs; + return { + data: hydrateCacheData(displayData), + timestamp: cache.timestamp, + isFresh: now - cache.timestamp < ttl, + }; + } + catch { + return null; + } +} +function readRateLimitedCount(homeDir) { + try { + const cachePath = getCachePath(homeDir); + if (!fs.existsSync(cachePath)) + return 0; + const content = fs.readFileSync(cachePath, 'utf8'); + const cache = JSON.parse(content); + return cache.rateLimitedCount ?? 0; + } + catch { + return 0; + } +} +function readLastGoodData(homeDir) { + try { + const cachePath = getCachePath(homeDir); + if (!fs.existsSync(cachePath)) + return null; + const content = fs.readFileSync(cachePath, 'utf8'); + const cache = JSON.parse(content); + return cache.lastGoodData ? hydrateCacheData(cache.lastGoodData) : null; + } + catch { + return null; + } +} +function readCache(homeDir, now, ttls) { + const cache = readCacheState(homeDir, now, ttls); + return cache?.isFresh ? cache.data : null; +} +function writeCache(homeDir, data, timestamp, opts) { + try { + const cachePath = getCachePath(homeDir); + const cacheDir = path.dirname(cachePath); + if (!fs.existsSync(cacheDir)) { + fs.mkdirSync(cacheDir, { recursive: true }); + } + const cache = { data, timestamp }; + if (opts?.rateLimitedCount && opts.rateLimitedCount > 0) { + cache.rateLimitedCount = opts.rateLimitedCount; + } + if (opts?.retryAfterUntil) { + cache.retryAfterUntil = opts.retryAfterUntil; + } + if (opts?.lastGoodData) { + cache.lastGoodData = opts.lastGoodData; + } + fs.writeFileSync(cachePath, JSON.stringify(cache), 'utf8'); + } + catch { + // Ignore cache write failures + } +} +function readLockTimestamp(lockPath) { + try { + if (!fs.existsSync(lockPath)) + return null; + const raw = fs.readFileSync(lockPath, 'utf8').trim(); + const parsed = Number.parseInt(raw, 10); + return Number.isFinite(parsed) ? parsed : null; + } + catch { + return null; + } +} +function tryAcquireCacheLock(homeDir) { + const lockPath = getCacheLockPath(homeDir); + const cacheDir = path.dirname(lockPath); + try { + if (!fs.existsSync(cacheDir)) { + fs.mkdirSync(cacheDir, { recursive: true }); + } + const fd = fs.openSync(lockPath, 'wx'); + try { + fs.writeFileSync(fd, String(Date.now()), 'utf8'); + } + finally { + fs.closeSync(fd); + } + return 'acquired'; + } + catch (error) { + const maybeError = error; + if (maybeError.code !== 'EEXIST') { + debug('Usage cache lock unavailable, continuing without coordination:', maybeError.message); + return 'unsupported'; + } + } + const lockTimestamp = readLockTimestamp(lockPath); + // Unparseable timestamp — use mtime to distinguish a crash leftover from an active writer. + if (lockTimestamp === null) { + try { + const lockStat = fs.statSync(lockPath); + if (Date.now() - lockStat.mtimeMs < CACHE_LOCK_STALE_MS) { + return 'busy'; + } + } + catch { + return tryAcquireCacheLock(homeDir); + } + try { + fs.unlinkSync(lockPath); + } + catch { + return 'busy'; + } + return tryAcquireCacheLock(homeDir); + } + if (lockTimestamp != null && Date.now() - lockTimestamp > CACHE_LOCK_STALE_MS) { + try { + fs.unlinkSync(lockPath); + } + catch { + return 'busy'; + } + return tryAcquireCacheLock(homeDir); + } + return 'busy'; +} +function releaseCacheLock(homeDir) { + try { + const lockPath = getCacheLockPath(homeDir); + if (fs.existsSync(lockPath)) { + fs.unlinkSync(lockPath); + } + } + catch { + // Ignore lock cleanup failures + } +} +async function waitForFreshCache(homeDir, now, ttls, timeoutMs = CACHE_LOCK_WAIT_MS) { + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + await new Promise((resolve) => setTimeout(resolve, CACHE_LOCK_POLL_MS)); + const cached = readCache(homeDir, now(), ttls); + if (cached) { + return cached; + } + if (!fs.existsSync(getCacheLockPath(homeDir))) { + break; + } + } + return readCache(homeDir, now(), ttls); +} +const defaultDeps = { + homeDir: () => os.homedir(), + fetchApi: fetchUsageApi, + now: () => Date.now(), + readKeychain: readKeychainCredentials, + ttls: { cacheTtlMs: CACHE_TTL_MS, failureCacheTtlMs: CACHE_FAILURE_TTL_MS }, +}; +/** + * Get OAuth usage data from Anthropic API. + * Returns null if user is an API user (no OAuth credentials) or credentials are expired. + * Returns { apiUnavailable: true, ... } if API call fails (to show warning in HUD). + * + * Uses file-based cache since HUD runs as a new process each render (~300ms). + * Cache TTL is configurable via usage.cacheTtlSeconds / usage.failureCacheTtlSeconds in config.json + * (defaults: 60s for success, 15s for failures). + */ +export async function getUsage(overrides = {}) { + const deps = { ...defaultDeps, ...overrides }; + const now = deps.now(); + const homeDir = deps.homeDir(); + // Skip usage API if user is using a custom provider + if (isUsingCustomApiEndpoint()) { + debug('Skipping usage API: custom API endpoint configured'); + return null; + } + // Check file-based cache first + const cacheState = readCacheState(homeDir, now, deps.ttls); + if (cacheState?.isFresh) { + return cacheState.data; + } + let holdsCacheLock = false; + const lockStatus = tryAcquireCacheLock(homeDir); + if (lockStatus === 'busy') { + if (cacheState) { + return cacheState.data; + } + return await waitForFreshCache(homeDir, deps.now, deps.ttls); + } + holdsCacheLock = lockStatus === 'acquired'; + try { + const refreshedCache = readCache(homeDir, deps.now(), deps.ttls); + if (refreshedCache) { + return refreshedCache; + } + const credentials = readCredentials(homeDir, now, deps.readKeychain); + if (!credentials) { + return null; + } + const { accessToken, subscriptionType } = credentials; + // Determine plan name from subscriptionType + const planName = getPlanName(subscriptionType); + if (!planName) { + // API user, no usage limits to show + return null; + } + // Fetch usage from API + const apiResult = await deps.fetchApi(accessToken); + if (!apiResult.data) { + const isRateLimited = apiResult.error === 'rate-limited'; + const prevCount = readRateLimitedCount(homeDir); + const rateLimitedCount = isRateLimited ? prevCount + 1 : 0; + const retryAfterUntil = isRateLimited && apiResult.retryAfterSec + ? now + apiResult.retryAfterSec * 1000 + : undefined; + const backoffOpts = { + rateLimitedCount: isRateLimited ? rateLimitedCount : undefined, + retryAfterUntil, + }; + const failureResult = { + planName, + fiveHour: null, + sevenDay: null, + fiveHourResetAt: null, + sevenDayResetAt: null, + apiUnavailable: true, + apiError: apiResult.error, + }; + if (isRateLimited) { + const staleCache = readCacheState(homeDir, now, deps.ttls); + const lastGood = readLastGoodData(homeDir); + const goodData = (staleCache && !staleCache.data.apiUnavailable) + ? staleCache.data + : lastGood; + if (goodData) { + // Preserve the backoff state in cache, but keep rendering the last successful values + // with a syncing hint so stale data is visible to the user. + writeCache(homeDir, failureResult, now, { ...backoffOpts, lastGoodData: goodData }); + return withRateLimitedSyncing(goodData); + } + } + writeCache(homeDir, failureResult, now, backoffOpts); + return failureResult; + } + // Parse response - API returns 0-100 percentage directly + // Clamp to 0-100 and handle NaN/Infinity + const fiveHour = parseUtilization(apiResult.data.five_hour?.utilization); + const sevenDay = parseUtilization(apiResult.data.seven_day?.utilization); + const fiveHourResetAt = parseDate(apiResult.data.five_hour?.resets_at); + const sevenDayResetAt = parseDate(apiResult.data.seven_day?.resets_at); + const result = { + planName, + fiveHour, + sevenDay, + fiveHourResetAt, + sevenDayResetAt, + }; + // Write to file cache — also store as lastGoodData for rate-limit resilience + writeCache(homeDir, result, now, { lastGoodData: result }); + return result; + } + catch (error) { + debug('getUsage failed:', error); + return null; + } + finally { + if (holdsCacheLock) { + releaseCacheLock(homeDir); + } + } +} +/** + * Get path for keychain failure backoff cache. + * Separate from usage cache to track keychain-specific failures. + */ +function getKeychainBackoffPath(homeDir) { + return path.join(getHudPluginDir(homeDir), '.keychain-backoff'); +} +/** + * Check if we're in keychain backoff period (recent failure/timeout). + * Prevents re-prompting user on every render cycle. + */ +function isKeychainBackoff(homeDir, now) { + try { + const backoffPath = getKeychainBackoffPath(homeDir); + if (!fs.existsSync(backoffPath)) + return false; + const timestamp = parseInt(fs.readFileSync(backoffPath, 'utf8'), 10); + return now - timestamp < KEYCHAIN_BACKOFF_MS; + } + catch { + return false; + } +} +/** + * Record keychain failure for backoff. + */ +function recordKeychainFailure(homeDir, now) { + try { + const backoffPath = getKeychainBackoffPath(homeDir); + const dir = path.dirname(backoffPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + fs.writeFileSync(backoffPath, String(now), 'utf8'); + } + catch { + // Ignore write failures + } +} +/** + * Determine the macOS Keychain service name for Claude Code credentials. + * Claude Code uses the default service for ~/.claude and a hashed suffix for custom config directories. + */ +export function getKeychainServiceName(configDir, homeDir) { + const normalizedConfigDir = path.normalize(path.resolve(configDir)); + const normalizedDefaultDir = path.normalize(path.resolve(path.join(homeDir, '.claude'))); + if (normalizedConfigDir === normalizedDefaultDir) { + return LEGACY_KEYCHAIN_SERVICE_NAME; + } + const hash = createHash('sha256').update(normalizedConfigDir).digest('hex').slice(0, 8); + return `${LEGACY_KEYCHAIN_SERVICE_NAME}-${hash}`; +} +export function getKeychainServiceNames(configDir, homeDir, env = process.env) { + const serviceNames = [getKeychainServiceName(configDir, homeDir)]; + const envConfigDir = env.CLAUDE_CONFIG_DIR?.trim(); + if (envConfigDir) { + const normalizedDefaultDir = path.normalize(path.resolve(path.join(homeDir, '.claude'))); + const normalizedEnvDir = path.normalize(path.resolve(envConfigDir)); + if (normalizedEnvDir === normalizedDefaultDir) { + serviceNames.push(LEGACY_KEYCHAIN_SERVICE_NAME); + } + else { + const envHash = createHash('sha256').update(envConfigDir).digest('hex').slice(0, 8); + serviceNames.push(`${LEGACY_KEYCHAIN_SERVICE_NAME}-${envHash}`); + } + } + serviceNames.push(LEGACY_KEYCHAIN_SERVICE_NAME); + return [...new Set(serviceNames)]; +} +function isMissingKeychainItemError(error) { + if (!error || typeof error !== 'object') + return false; + const maybeError = error; + if (maybeError.status === 44) + return true; + const message = typeof maybeError.message === 'string' ? maybeError.message.toLowerCase() : ''; + if (message.includes('could not be found in the keychain')) + return true; + const stderr = typeof maybeError.stderr === 'string' + ? maybeError.stderr.toLowerCase() + : Buffer.isBuffer(maybeError.stderr) + ? maybeError.stderr.toString('utf8').toLowerCase() + : ''; + return stderr.includes('could not be found in the keychain'); +} +export function resolveKeychainCredentials(serviceNames, now, loadService, accountName) { + let shouldBackoff = false; + let allowGenericFallback = Boolean(accountName); + for (const serviceName of serviceNames) { + try { + const keychainData = accountName + ? loadService(serviceName, accountName) + : loadService(serviceName); + if (accountName) + allowGenericFallback = false; + const trimmedKeychainData = keychainData.trim(); + if (!trimmedKeychainData) + continue; + const data = JSON.parse(trimmedKeychainData); + const credentials = parseCredentialsData(data, now); + if (credentials) { + return { credentials, shouldBackoff: false }; + } + } + catch (error) { + if (!isMissingKeychainItemError(error)) { + if (accountName) + allowGenericFallback = false; + shouldBackoff = true; + } + } + } + if (!accountName || !allowGenericFallback) { + return { credentials: null, shouldBackoff }; + } + for (const serviceName of serviceNames) { + try { + const keychainData = loadService(serviceName).trim(); + if (!keychainData) + continue; + const data = JSON.parse(keychainData); + const credentials = parseCredentialsData(data, now); + if (credentials) { + return { credentials, shouldBackoff: false }; + } + } + catch (error) { + if (!isMissingKeychainItemError(error)) { + shouldBackoff = true; + } + } + } + return { credentials: null, shouldBackoff }; +} +function getKeychainAccountName() { + try { + const username = os.userInfo().username.trim(); + return username || null; + } + catch { + return null; + } +} +/** + * Read credentials from macOS Keychain. + * Claude Code stores OAuth credentials in the macOS Keychain with profile-specific service names. + * Returns null if not on macOS or credentials not found. + * + * Security: Uses execFileSync with absolute path to avoid shell injection and PATH hijacking. + */ +function readKeychainCredentials(now, homeDir) { + // Only available on macOS + if (process.platform !== 'darwin') { + return null; + } + // Check backoff to avoid re-prompting on every render after a failure + if (isKeychainBackoff(homeDir, now)) { + debug('Keychain in backoff period, skipping'); + return null; + } + try { + const configDir = getClaudeConfigDir(homeDir); + const serviceNames = getKeychainServiceNames(configDir, homeDir); + const accountName = getKeychainAccountName(); + debug('Trying keychain service names:', serviceNames); + if (accountName) { + debug('Trying keychain account name:', accountName); + } + const resolved = resolveKeychainCredentials(serviceNames, now, (serviceName, lookupAccountName) => execFileSync('/usr/bin/security', lookupAccountName + ? ['find-generic-password', '-s', serviceName, '-a', lookupAccountName, '-w'] + : ['find-generic-password', '-s', serviceName, '-w'], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: KEYCHAIN_TIMEOUT_MS }), accountName); + if (resolved.credentials) { + return resolved.credentials; + } + if (resolved.shouldBackoff) { + recordKeychainFailure(homeDir, now); + } + return null; + } + catch (error) { + // Security: Only log error message, not full error object (may contain stdout/stderr with tokens) + const message = error instanceof Error ? error.message : 'unknown error'; + debug('Failed to read from macOS Keychain:', message); + // Record failure for backoff to avoid re-prompting + recordKeychainFailure(homeDir, now); + return null; + } +} +/** + * Read credentials from file (legacy method). + * Older versions of Claude Code stored credentials in {CLAUDE_CONFIG_DIR}/.credentials.json. + */ +function readFileCredentials(homeDir, now) { + const credentialsPath = path.join(getClaudeConfigDir(homeDir), '.credentials.json'); + if (!fs.existsSync(credentialsPath)) { + return null; + } + try { + const content = fs.readFileSync(credentialsPath, 'utf8'); + const data = JSON.parse(content); + return parseCredentialsData(data, now); + } + catch (error) { + debug('Failed to read credentials file:', error); + return null; + } +} +function readFileSubscriptionType(homeDir) { + const credentialsPath = path.join(getClaudeConfigDir(homeDir), '.credentials.json'); + if (!fs.existsSync(credentialsPath)) { + return null; + } + try { + const content = fs.readFileSync(credentialsPath, 'utf8'); + const data = JSON.parse(content); + const subscriptionType = data.claudeAiOauth?.subscriptionType; + const normalizedSubscriptionType = typeof subscriptionType === 'string' + ? subscriptionType.trim() + : ''; + if (!normalizedSubscriptionType) { + return null; + } + return normalizedSubscriptionType; + } + catch (error) { + debug('Failed to read file subscriptionType:', error); + return null; + } +} +/** + * Parse and validate credentials data from either Keychain or file. + */ +function parseCredentialsData(data, now) { + const accessToken = data.claudeAiOauth?.accessToken; + const subscriptionType = data.claudeAiOauth?.subscriptionType ?? ''; + if (!accessToken) { + return null; + } + // Check if token is expired (expiresAt is Unix ms timestamp) + // Use != null to handle expiresAt=0 correctly (would be expired) + const expiresAt = data.claudeAiOauth?.expiresAt; + if (expiresAt != null && expiresAt <= now) { + debug('OAuth token expired'); + return null; + } + return { accessToken, subscriptionType }; +} +/** + * Read OAuth credentials, trying macOS Keychain first (Claude Code 2.x), + * then falling back to file-based credentials (older versions). + * + * Token priority: Keychain token is authoritative (Claude Code 2.x stores current token there). + * SubscriptionType: Can be supplemented from file if keychain lacks it (display-only field). + */ +function readCredentials(homeDir, now, readKeychain) { + // Try macOS Keychain first (Claude Code 2.x) + const keychainCreds = readKeychain(now, homeDir); + if (keychainCreds) { + if (keychainCreds.subscriptionType) { + debug('Using credentials from macOS Keychain'); + return keychainCreds; + } + // Keychain has token but no subscriptionType - try to supplement from file + const fileSubscriptionType = readFileSubscriptionType(homeDir); + if (fileSubscriptionType) { + debug('Using keychain token with file subscriptionType'); + return { + accessToken: keychainCreds.accessToken, + subscriptionType: fileSubscriptionType, + }; + } + // No subscriptionType available - use keychain token anyway + debug('Using keychain token without subscriptionType'); + return keychainCreds; + } + // Fall back to file-based credentials (older versions or non-macOS) + const fileCreds = readFileCredentials(homeDir, now); + if (fileCreds) { + debug('Using credentials from file'); + return fileCreds; + } + return null; +} +function getPlanName(subscriptionType) { + const lower = subscriptionType.toLowerCase(); + if (lower.includes('max')) + return 'Max'; + if (lower.includes('pro')) + return 'Pro'; + if (lower.includes('team')) + return 'Team'; + // API users don't have subscriptionType or have 'api' + if (!subscriptionType || lower.includes('api')) + return null; + // Unknown subscription type - show it capitalized + return subscriptionType.charAt(0).toUpperCase() + subscriptionType.slice(1); +} +/** Parse utilization value, clamping to 0-100 and handling NaN/Infinity */ +function parseUtilization(value) { + if (value == null) + return null; + if (!Number.isFinite(value)) + return null; // Handles NaN and Infinity + return Math.round(Math.max(0, Math.min(100, value))); +} +/** Parse ISO date string safely, returning null for invalid dates */ +function parseDate(dateStr) { + if (!dateStr) + return null; + const date = new Date(dateStr); + // Check for Invalid Date + if (isNaN(date.getTime())) { + debug('Invalid date string:', dateStr); + return null; + } + return date; +} +export function getUsageApiTimeoutMs(env = process.env) { + const raw = env.CLAUDE_HUD_USAGE_TIMEOUT_MS?.trim(); + if (!raw) + return USAGE_API_TIMEOUT_MS_DEFAULT; + const parsed = Number(raw); + if (!Number.isInteger(parsed) || parsed <= 0) { + debug('Invalid CLAUDE_HUD_USAGE_TIMEOUT_MS value:', raw); + return USAGE_API_TIMEOUT_MS_DEFAULT; + } + return parsed; +} +export function isNoProxy(hostname, env = process.env) { + const noProxy = env.NO_PROXY ?? env.no_proxy; + if (!noProxy) + return false; + const host = hostname.toLowerCase(); + return noProxy.split(',').some((entry) => { + const pattern = entry.trim().toLowerCase(); + if (!pattern) + return false; + if (pattern === '*') + return true; + if (host === pattern) + return true; + const suffix = pattern.startsWith('.') ? pattern : `.${pattern}`; + return host.endsWith(suffix); + }); +} +export function getProxyUrl(hostname, env = process.env) { + if (isNoProxy(hostname, env)) { + debug('Proxy bypassed by NO_PROXY for host:', hostname); + return null; + } + const proxyEnv = env.HTTPS_PROXY + ?? env.https_proxy + ?? env.ALL_PROXY + ?? env.all_proxy + ?? env.HTTP_PROXY + ?? env.http_proxy; + if (!proxyEnv) + return null; + try { + const proxyUrl = new URL(proxyEnv); + if (proxyUrl.protocol !== 'http:' && proxyUrl.protocol !== 'https:') { + debug('Unsupported proxy protocol:', proxyUrl.protocol); + return null; + } + return proxyUrl; + } + catch { + debug('Invalid proxy URL:', proxyEnv); + return null; + } +} +function createProxyTunnelAgent(proxyUrl) { + const proxyHost = proxyUrl.hostname; + const proxyPort = Number.parseInt(proxyUrl.port || (proxyUrl.protocol === 'https:' ? '443' : '80'), 10); + const proxyAuth = proxyUrl.username + ? `Basic ${Buffer.from(`${decodeURIComponent(proxyUrl.username)}:${decodeURIComponent(proxyUrl.password || '')}`).toString('base64')}` + : null; + return new class extends https.Agent { + createConnection(options, callback) { + const targetHost = String(options.host ?? options.hostname ?? 'localhost'); + const targetPort = Number(options.port) || 443; + let settled = false; + const settle = (err, socket) => { + if (settled) + return; + settled = true; + callback?.(err, socket); + }; + const proxySocket = proxyUrl.protocol === 'https:' + ? tls.connect({ host: proxyHost, port: proxyPort, servername: proxyHost }) + : net.connect(proxyPort, proxyHost); + proxySocket.once('error', (error) => { + settle(error, proxySocket); + }); + proxySocket.once('connect', () => { + const connectHeaders = [ + `CONNECT ${targetHost}:${targetPort} HTTP/1.1`, + `Host: ${targetHost}:${targetPort}`, + ]; + if (proxyAuth) { + connectHeaders.push(`Proxy-Authorization: ${proxyAuth}`); + } + connectHeaders.push('', ''); + proxySocket.write(connectHeaders.join('\r\n')); + let responseBuffer = Buffer.alloc(0); + const onData = (chunk) => { + responseBuffer = Buffer.concat([responseBuffer, chunk]); + const headerEndIndex = responseBuffer.indexOf('\r\n\r\n'); + if (headerEndIndex === -1) + return; + proxySocket.removeListener('data', onData); + const headerText = responseBuffer.subarray(0, headerEndIndex).toString('utf8'); + const statusLine = headerText.split('\r\n')[0] ?? ''; + if (!/^HTTP\/1\.[01] 200 /.test(statusLine)) { + const error = new Error(`Proxy CONNECT rejected: ${statusLine || 'unknown status'}`); + proxySocket.destroy(error); + settle(error, proxySocket); + return; + } + const tlsSocket = tls.connect({ + socket: proxySocket, + servername: String(options.servername ?? targetHost), + rejectUnauthorized: options.rejectUnauthorized !== false, + }, () => { + settle(null, tlsSocket); + }); + tlsSocket.once('error', (error) => { + settle(error, tlsSocket); + }); + }; + proxySocket.on('data', onData); + }); + // Must not return the socket here. In Node.js _http_agent.js, createSocket() + // calls: `if (newSocket) oncreate(null, newSocket)` — returning a truthy value + // causes the HTTP request to be written to the raw proxy socket immediately, + // before the CONNECT tunnel is established. Only deliver the final TLS socket + // asynchronously via the callback after the CONNECT handshake succeeds. + return undefined; + } + }(); +} +function fetchUsageApi(accessToken) { + return new Promise((resolve) => { + const host = 'api.anthropic.com'; + const timeoutMs = getUsageApiTimeoutMs(); + const proxyUrl = getProxyUrl(host); + const options = { + hostname: host, + path: '/api/oauth/usage', + method: 'GET', + headers: { + 'Authorization': `Bearer ${accessToken}`, + 'anthropic-beta': 'oauth-2025-04-20', + 'User-Agent': USAGE_API_USER_AGENT, + }, + timeout: timeoutMs, + agent: proxyUrl ? createProxyTunnelAgent(proxyUrl) : undefined, + }; + if (proxyUrl) { + debug('Using proxy for usage API:', proxyUrl.origin); + } + const req = https.request(options, (res) => { + let data = ''; + res.on('data', (chunk) => { + data += chunk.toString(); + }); + res.on('end', () => { + if (res.statusCode !== 200) { + debug('API returned non-200 status:', res.statusCode); + // Use a distinct error key for 429 so cache/render can handle it specially + const error = res.statusCode === 429 + ? 'rate-limited' + : res.statusCode ? `http-${res.statusCode}` : 'http-error'; + const retryAfterSec = res.statusCode === 429 + ? parseRetryAfterSeconds(res.headers['retry-after']) + : undefined; + if (retryAfterSec) { + debug('Retry-After:', retryAfterSec, 'seconds'); + } + resolve({ data: null, error, retryAfterSec }); + return; + } + try { + const parsed = JSON.parse(data); + resolve({ data: parsed }); + } + catch (error) { + debug('Failed to parse API response:', error); + resolve({ data: null, error: 'parse' }); + } + }); + }); + req.on('error', (error) => { + debug('API request error:', error); + resolve({ data: null, error: 'network' }); + }); + req.on('timeout', () => { + debug('API request timeout'); + req.destroy(); + resolve({ data: null, error: 'timeout' }); + }); + req.end(); + }); +} +export function parseRetryAfterSeconds(raw, nowMs = Date.now()) { + const value = Array.isArray(raw) ? raw[0] : raw; + if (!value) + return undefined; + const parsedSeconds = Number.parseInt(value, 10); + if (Number.isFinite(parsedSeconds) && parsedSeconds > 0) { + return parsedSeconds; + } + const retryAtMs = Date.parse(value); + if (!Number.isFinite(retryAtMs)) { + return undefined; + } + const retryAfterSeconds = Math.ceil((retryAtMs - nowMs) / 1000); + return retryAfterSeconds > 0 ? retryAfterSeconds : undefined; +} +// Export for testing +export function clearCache(homeDir) { + if (homeDir) { + try { + const cachePath = getCachePath(homeDir); + if (fs.existsSync(cachePath)) { + fs.unlinkSync(cachePath); + } + const lockPath = getCacheLockPath(homeDir); + if (fs.existsSync(lockPath)) { + fs.unlinkSync(lockPath); + } + } + catch { + // Ignore + } + } +} +//# sourceMappingURL=usage-api.js.map \ No newline at end of file diff --git a/dist/usage-api.js.map b/dist/usage-api.js.map new file mode 100644 index 0000000..dfc8ac5 --- /dev/null +++ b/dist/usage-api.js.map @@ -0,0 +1 @@ +{"version":3,"file":"usage-api.js","sourceRoot":"","sources":["../src/usage-api.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/terminal.d.ts b/dist/utils/terminal.d.ts new file mode 100644 index 0000000..e80526c --- /dev/null +++ b/dist/utils/terminal.d.ts @@ -0,0 +1,2 @@ +export declare function getAdaptiveBarWidth(): number; +//# sourceMappingURL=terminal.d.ts.map \ No newline at end of file diff --git a/dist/utils/terminal.d.ts.map b/dist/utils/terminal.d.ts.map new file mode 100644 index 0000000..252048b --- /dev/null +++ b/dist/utils/terminal.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/utils/terminal.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,MAAM,CAY5C"} \ No newline at end of file diff --git a/dist/utils/terminal.js b/dist/utils/terminal.js new file mode 100644 index 0000000..96c4e36 --- /dev/null +++ b/dist/utils/terminal.js @@ -0,0 +1,17 @@ +// Returns a progress bar width scaled to the current terminal width. +// Wide (>=100): 10, Medium (60-99): 6, Narrow (<60): 4. Defaults to 10. +export function getAdaptiveBarWidth() { + const stdoutCols = process.stdout?.columns; + const cols = (typeof stdoutCols === 'number' && Number.isFinite(stdoutCols) && stdoutCols > 0) + ? Math.floor(stdoutCols) + : Number.parseInt(process.env.COLUMNS ?? '', 10); + if (Number.isFinite(cols) && cols > 0) { + if (cols >= 100) + return 10; + if (cols >= 60) + return 6; + return 4; + } + return 10; +} +//# sourceMappingURL=terminal.js.map \ No newline at end of file diff --git a/dist/utils/terminal.js.map b/dist/utils/terminal.js.map new file mode 100644 index 0000000..10c4df5 --- /dev/null +++ b/dist/utils/terminal.js.map @@ -0,0 +1 @@ +{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/utils/terminal.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,wEAAwE;AACxE,MAAM,UAAU,mBAAmB;IACjC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3C,MAAM,IAAI,GAAG,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;QAC5F,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QACxB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAEnD,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI,IAAI,GAAG;YAAE,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,IAAI,EAAE;YAAE,OAAO,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"} \ No newline at end of file