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..dc0149b --- /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":"AAIA,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AA4DD,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAqEtE"} \ No newline at end of file diff --git a/dist/config-reader.js b/dist/config-reader.js new file mode 100644 index 0000000..a238f2e --- /dev/null +++ b/dist/config-reader.js @@ -0,0 +1,119 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +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 { + // Ignore errors + } + 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 { + // Ignore errors + } + 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 { + // Ignore errors + } + return count; +} +export async function countConfigs(cwd) { + let claudeMdCount = 0; + let rulesCount = 0; + let mcpCount = 0; + let hooksCount = 0; + const homeDir = os.homedir(); + const claudeDir = path.join(homeDir, '.claude'); + // === 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'); + mcpCount += countMcpServersInFile(userSettings); + hooksCount += countHooksInFile(userSettings); + // ~/.claude.json (additional user-scope MCPs, dedupe by counting unique) + const userClaudeJson = path.join(homeDir, '.claude.json'); + mcpCount += countMcpServersInFile(userClaudeJson, userSettings); + // === PROJECT SCOPE === + 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) + if (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) + rulesCount += countRulesInDir(path.join(cwd, '.claude', 'rules')); + // {cwd}/.mcp.json (project MCP config) + mcpCount += countMcpServersInFile(path.join(cwd, '.mcp.json')); + // {cwd}/.claude/settings.json (project settings) + const projectSettings = path.join(cwd, '.claude', 'settings.json'); + mcpCount += countMcpServersInFile(projectSettings); + hooksCount += countHooksInFile(projectSettings); + // {cwd}/.claude/settings.local.json (local project settings) + const localSettings = path.join(cwd, '.claude', 'settings.local.json'); + mcpCount += countMcpServersInFile(localSettings); + hooksCount += countHooksInFile(localSettings); + } + 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..325c6b9 --- /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":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AASzB,SAAS,iBAAiB,CAAC,QAAgB;IACzC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC/D,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IACD,OAAO,IAAI,GAAG,EAAE,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB,EAAE,WAAoB;IACnE,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAgB;IACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,KAAK,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY;IAC7C,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEhD,qBAAqB;IAErB,sBAAsB;IACtB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QACrD,aAAa,EAAE,CAAC;IAClB,CAAC;IAED,uBAAuB;IACvB,UAAU,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAE7D,2CAA2C;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC3D,QAAQ,IAAI,qBAAqB,CAAC,YAAY,CAAC,CAAC;IAChD,UAAU,IAAI,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAE7C,yEAAyE;IACzE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC1D,QAAQ,IAAI,qBAAqB,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAEhE,wBAAwB;IAExB,IAAI,GAAG,EAAE,CAAC;QACR,kBAAkB;QAClB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YAC/C,aAAa,EAAE,CAAC;QAClB,CAAC;QAED,wBAAwB;QACxB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC;YACrD,aAAa,EAAE,CAAC;QAClB,CAAC;QAED,iDAAiD;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YAC1D,aAAa,EAAE,CAAC;QAClB,CAAC;QAED,gCAAgC;QAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC;YAChE,aAAa,EAAE,CAAC;QAClB,CAAC;QAED,uCAAuC;QACvC,UAAU,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAElE,uCAAuC;QACvC,QAAQ,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;QAE/D,iDAAiD;QACjD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACnE,QAAQ,IAAI,qBAAqB,CAAC,eAAe,CAAC,CAAC;QACnD,UAAU,IAAI,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAEhD,6DAA6D;QAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;QACvE,QAAQ,IAAI,qBAAqB,CAAC,aAAa,CAAC,CAAC;QACjD,UAAU,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAC7D,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..3e15573 --- /dev/null +++ b/dist/constants.d.ts @@ -0,0 +1,6 @@ +/** + * Autocompact buffer: reserved space that /context includes in its calculation. + * This is fixed at 45k tokens (22.5% of 200k) - must be added to match /context output. + */ +export declare const AUTOCOMPACT_BUFFER = 45000; +//# 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..2cf00ce --- /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;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAQ,CAAC"} \ No newline at end of file diff --git a/dist/constants.js b/dist/constants.js new file mode 100644 index 0000000..80d7abd --- /dev/null +++ b/dist/constants.js @@ -0,0 +1,6 @@ +/** + * Autocompact buffer: reserved space that /context includes in its calculation. + * This is fixed at 45k tokens (22.5% of 200k) - must be added to match /context output. + */ +export const AUTOCOMPACT_BUFFER = 45000; +//# 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..a51debf --- /dev/null +++ b/dist/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,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..6778952 --- /dev/null +++ b/dist/git.d.ts @@ -0,0 +1,2 @@ +export declare function getGitBranch(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..bb65f05 --- /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,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAavE"} \ No newline at end of file diff --git a/dist/git.js b/dist/git.js new file mode 100644 index 0000000..58dc752 --- /dev/null +++ b/dist/git.js @@ -0,0 +1,15 @@ +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; + } +} +//# 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..a57fda2 --- /dev/null +++ b/dist/git.js.map @@ -0,0 +1 @@ +{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,KAAK,EACL,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EACrC,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CACzC,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..d33cb60 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,17 @@ +import { readStdin } from './stdin.js'; +import { parseTranscript } from './transcript.js'; +import { render } from './render/index.js'; +import { countConfigs } from './config-reader.js'; +import { getGitBranch } from './git.js'; +export type MainDeps = { + readStdin: typeof readStdin; + parseTranscript: typeof parseTranscript; + countConfigs: typeof countConfigs; + getGitBranch: typeof getGitBranch; + 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..b4297f6 --- /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;AAIxC,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,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,CA4C3E;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..ffcc620 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,62 @@ +import { readStdin } from './stdin.js'; +import { parseTranscript } from './transcript.js'; +import { render } from './render/index.js'; +import { countConfigs } from './config-reader.js'; +import { getGitBranch } from './git.js'; +import { fileURLToPath } from 'node:url'; +export async function main(overrides = {}) { + const deps = { + readStdin, + parseTranscript, + countConfigs, + getGitBranch, + 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 gitBranch = await deps.getGitBranch(stdin.cwd); + const sessionDuration = formatSessionDuration(transcript.sessionStart, deps.now); + const ctx = { + stdin, + transcript, + claudeMdCount, + rulesCount, + mcpCount, + hooksCount, + sessionDuration, + gitBranch, + }; + 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`; +} +if (process.argv[1] === fileURLToPath(import.meta.url)) { + 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..83de12d --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","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;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAYzC,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,YAA+B,EAAE;IAC1D,MAAM,IAAI,GAAa;QACrB,SAAS;QACT,eAAe;QACf,YAAY;QACZ,YAAY;QACZ,MAAM;QACN,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACrB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,GAAG,SAAS;KACb,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAErC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;QACnD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAE9D,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE/F,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAErD,MAAM,eAAe,GAAG,qBAAqB,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjF,MAAM,GAAG,GAAkB;YACzB,KAAK;YACL,UAAU;YACV,aAAa;YACb,UAAU;YACV,QAAQ;YACR,UAAU;YACV,eAAe;YACf,SAAS;SACV,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAAmB,EAAE,MAAoB,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IAC7F,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,IAAI,GAAG,EAAE;QAAE,OAAO,GAAG,IAAI,GAAG,CAAC;IAEjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,OAAO,GAAG,KAAK,KAAK,aAAa,GAAG,CAAC;AACvC,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACvD,KAAK,IAAI,EAAE,CAAC;AACd,CAAC"} \ 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":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,UAAU,gBAAgB,CAAC,GAAkB;IACjD,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;IAElC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACnE,MAAM,eAAe,GAAG,MAAM;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;SACvC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEb,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB;IACpC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAErC,OAAO,GAAG,UAAU,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,IAAI,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB,EAAE;IACrD,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC;IAC5C,MAAM,EAAE,GAAG,GAAG,GAAG,KAAK,CAAC;IAEvB,IAAI,EAAE,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,EAAE,GAAG,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;IAEnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,CAAC;AAC7B,CAAC"} \ 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..1754801 --- /dev/null +++ b/dist/render/colors.d.ts @@ -0,0 +1,10 @@ +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 getContextColor(percent: number): string; +export declare function coloredBar(percent: number, width?: number): 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..fb696b2 --- /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,eAAO,MAAM,KAAK,cAAY,CAAC;AAS/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,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,MAAM,CAKtE"} \ No newline at end of file diff --git a/dist/render/colors.js b/dist/render/colors.js new file mode 100644 index 0000000..474cc1d --- /dev/null +++ b/dist/render/colors.js @@ -0,0 +1,39 @@ +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'; +export function green(text) { + return `${GREEN}${text}${RESET}`; +} +export function yellow(text) { + return `${YELLOW}${text}${RESET}`; +} +export function red(text) { + return `${RED}${text}${RESET}`; +} +export function cyan(text) { + return `${CYAN}${text}${RESET}`; +} +export function magenta(text) { + return `${MAGENTA}${text}${RESET}`; +} +export function dim(text) { + return `${DIM}${text}${RESET}`; +} +export function getContextColor(percent) { + if (percent >= 85) + return RED; + if (percent >= 70) + return YELLOW; + return GREEN; +} +export function coloredBar(percent, width = 10) { + const filled = Math.round((percent / 100) * width); + const empty = width - filled; + const color = getContextColor(percent); + 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..4f4943a --- /dev/null +++ b/dist/render/colors.js.map @@ -0,0 +1 @@ +{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/render/colors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAE/B,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,GAAG,GAAG,UAAU,CAAC;AACvB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,OAAO,GAAG,UAAU,CAAC;AAC3B,MAAM,IAAI,GAAG,UAAU,CAAC;AAExB,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,OAAO,IAAI,EAAE;QAAE,OAAO,GAAG,CAAC;IAC9B,IAAI,OAAO,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IACjC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,QAAgB,EAAE;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC;AAC3E,CAAC"} \ 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..01cb109 --- /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":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAOjD,wBAAgB,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CA2B/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..dbfc913 --- /dev/null +++ b/dist/render/index.js @@ -0,0 +1,29 @@ +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 { RESET } from './colors.js'; +export function render(ctx) { + const lines = []; + const sessionLine = renderSessionLine(ctx); + if (sessionLine) { + lines.push(sessionLine); + } + const toolsLine = renderToolsLine(ctx); + if (toolsLine) { + lines.push(toolsLine); + } + const agentsLine = renderAgentsLine(ctx); + if (agentsLine) { + lines.push(agentsLine); + } + const todosLine = renderTodosLine(ctx); + if (todosLine) { + lines.push(todosLine); + } + for (const line of lines) { + const outputLine = `${RESET}${line.replace(/ /g, '\u00A0')}`; + 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..b3c369c --- /dev/null +++ b/dist/render/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,UAAU,MAAM,CAAC,GAAkB;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"} \ 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..ab6f7d0 --- /dev/null +++ b/dist/render/session-line.d.ts @@ -0,0 +1,3 @@ +import type { RenderContext } from '../types.js'; +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..2c93eb3 --- /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":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAmD5D"} \ 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..751bda4 --- /dev/null +++ b/dist/render/session-line.js @@ -0,0 +1,53 @@ +import path from 'node:path'; +import { getContextPercent, getModelName } from '../stdin.js'; +import { coloredBar, cyan, dim, magenta, red, yellow, getContextColor, RESET } from './colors.js'; +export function renderSessionLine(ctx) { + const model = getModelName(ctx.stdin); + const percent = getContextPercent(ctx.stdin); + const bar = coloredBar(percent); + const parts = []; + parts.push(`${cyan(`[${model}]`)} ${bar} ${getContextColor(percent)}${percent}%${RESET}`); + if (ctx.stdin.cwd) { + const projectName = path.basename(ctx.stdin.cwd) || ctx.stdin.cwd; + const branchPart = ctx.gitBranch ? ` ${magenta('git:(')}${cyan(ctx.gitBranch)}${magenta(')')}` : ''; + parts.push(`${yellow(projectName)}${branchPart}`); + } + 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`)); + } + if (ctx.sessionDuration) { + parts.push(dim(`⏱️ ${ctx.sessionDuration}`)); + } + let line = parts.join(' | '); + if (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})`); + } + } + if (percent >= 95) { + line += ` ${red('⚠️ COMPACT')}`; + } + 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(); +} +//# 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..30d14d0 --- /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":"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"} \ 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..3d12226 --- /dev/null +++ b/dist/render/tools-line.js @@ -0,0 +1,40 @@ +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) { + if (path.length <= maxLen) + return path; + const parts = path.split('/'); + const filename = parts.pop() || path; + 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..99c024a --- /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":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,GAAkB;IAChD,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;IAEjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IAE7F,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;SACjD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEf,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB,EAAE;IACrD,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;IAErC,IAAI,QAAQ,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAC/C,CAAC;IAED,OAAO,MAAM,GAAG,QAAQ,CAAC;AAC3B,CAAC"} \ No newline at end of file diff --git a/dist/stdin.d.ts b/dist/stdin.d.ts new file mode 100644 index 0000000..098682a --- /dev/null +++ b/dist/stdin.d.ts @@ -0,0 +1,5 @@ +import type { StdinData } from './types.js'; +export declare function readStdin(): Promise; +export declare function getContextPercent(stdin: StdinData): number; +export declare function getModelName(stdin: StdinData): string; +//# 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..da78bd4 --- /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,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAe1D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAErD"} \ No newline at end of file diff --git a/dist/stdin.js b/dist/stdin.js new file mode 100644 index 0000000..e978956 --- /dev/null +++ b/dist/stdin.js @@ -0,0 +1,37 @@ +import { AUTOCOMPACT_BUFFER } 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 getContextPercent(stdin) { + const usage = stdin.context_window?.current_usage; + const size = stdin.context_window?.context_window_size; + // Guard against missing data or invalid context window size + if (!usage || !size || size <= AUTOCOMPACT_BUFFER) { + return 0; + } + const totalTokens = (usage.input_tokens ?? 0) + + (usage.cache_creation_input_tokens ?? 0) + + (usage.cache_read_input_tokens ?? 0); + return Math.min(100, Math.round(((totalTokens + AUTOCOMPACT_BUFFER) / size) * 100)); +} +export function getModelName(stdin) { + return stdin.model?.display_name ?? stdin.model?.id ?? 'Unknown'; +} +//# 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..6be2e9f --- /dev/null +++ b/dist/stdin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../src/stdin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IAChD,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,aAAa,CAAC;IAClD,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,EAAE,mBAAmB,CAAC;IAEvD,4DAA4D;IAC5D,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,kBAAkB,EAAE,CAAC;QAClD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,WAAW,GACf,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;QACzB,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;QACxC,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC;IAEvC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,GAAG,kBAAkB,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAgB;IAC3C,OAAO,KAAK,CAAC,KAAK,EAAE,YAAY,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,SAAS,CAAC;AACnE,CAAC"} \ 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..a626ddc --- /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;AAkBlF,wBAAsB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyCrF"} \ No newline at end of file diff --git a/dist/transcript.js b/dist/transcript.js new file mode 100644 index 0000000..82e67d6 --- /dev/null +++ b/dist/transcript.js @@ -0,0 +1,113 @@ +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 = []; + 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); + processEntry(entry, toolMap, agentMap, 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; + return result; +} +function processEntry(entry, toolMap, agentMap, 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; + latestTodos.push(...input.todos); + } + } + 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; +} +//# 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..fd12862 --- /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..d5d7b46 --- /dev/null +++ b/dist/types.d.ts @@ -0,0 +1,54 @@ +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; + cache_creation_input_tokens?: number; + cache_read_input_tokens?: number; + }; + }; +} +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'; +} +export interface TranscriptData { + tools: ToolEntry[]; + agents: AgentEntry[]; + todos: TodoItem[]; + sessionStart?: Date; +} +export interface RenderContext { + stdin: StdinData; + transcript: TranscriptData; + claudeMdCount: number; + rulesCount: number; + mcpCount: number; + hooksCount: number; + sessionDuration: string; + gitBranch: 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..a5169c3 --- /dev/null +++ b/dist/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE;QACN,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,cAAc,CAAC,EAAE;QACf,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,aAAa,CAAC,EAAE;YACd,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,2BAA2B,CAAC,EAAE,MAAM,CAAC;YACrC,uBAAuB,CAAC,EAAE,MAAM,CAAC;SAClC,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IAC1C,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAChC,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;CACjD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"} \ No newline at end of file diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..718fd38 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,2 @@ +export {}; +//# 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..c768b79 --- /dev/null +++ b/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""} \ No newline at end of file