@owloops/claude-powerline
Version:
Beautiful vim-style powerline statusline for Claude Code with real-time usage tracking, git integration, and custom themes
7 lines • 59.6 kB
JavaScript
#!/usr/bin/env node
import _ from'process';import {json}from'stream/consumers';import I from'tty';import {exec}from'child_process';import {promisify}from'util';import C,{existsSync,readFileSync,createReadStream}from'fs';import y,{join,posix}from'path';import {get}from'https';import {URL}from'url';import Ie,{homedir}from'os';import {createHash}from'crypto';import {setTimeout}from'timers/promises';import {readdir,stat,readFile}from'fs/promises';import {createInterface}from'readline';function ne(o,e){if(e&&(o.toLowerCase()==="transparent"||o.toLowerCase()==="none"))return "\x1B[49m";let t=parseInt(o.slice(1,3),16),n=parseInt(o.slice(3,5),16),r=parseInt(o.slice(5,7),16);return `\x1B[${e?"48":"38"};2;${t};${n};${r}m`}function O(o,e=false){if(!o||o==="")return "";let t=o.match(/48;2;(\d+);(\d+);(\d+)/);if(t)return `\x1B[38;2;${t[1]};${t[2]};${t[3]}m`;if(e)return "\x1B[37m";if(o.includes("\x1B[")&&o.includes("m")){let n=o.match(/\[(\d+)m/);if(n&&n[1]){let r=parseInt(n[1],10);if(r>=40&&r<=47)return `\x1B[${r-10}m`;if(r>=100&&r<=107)return `\x1B[${r-10}m`}}return o.replace("48","38")}function N(){let{env:o}=_,e=true;o.NO_COLOR&&o.NO_COLOR!==""&&(e=false);let t=o.FORCE_COLOR;if(t&&t!=="")return t==="false"||t==="0"?"none":t==="true"||t==="1"?"ansi":t==="2"?"ansi256":t==="3"?"truecolor":"ansi";if(!e||o.TERM==="dumb")return "none";if(o.CI)return ["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(r=>r in o)?"truecolor":"ansi";if(o.COLORTERM==="truecolor"||["xterm-kitty","xterm-ghostty","wezterm","alacritty","foot","contour"].includes(o.TERM||""))return "truecolor";if(o.TERM_PROGRAM)switch(o.TERM_PROGRAM){case "iTerm.app":return "truecolor";case "Apple_Terminal":return "ansi256";case "vscode":return "truecolor";case "Tabby":return "truecolor"}if(/-256(color)?$/i.test(o.TERM||""))return "ansi256";if(/-truecolor$/i.test(o.TERM||""))return "truecolor";if(/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(o.TERM||"")||o.COLORTERM)return "ansi";if(I?.WriteStream?.prototype?.hasColors)try{if(!I.WriteStream.prototype.hasColors())return "none";let s=I.WriteStream.prototype.hasColors(256);return I.WriteStream.prototype.hasColors(16777216)?"truecolor":s?"ansi256":"ansi"}catch{}return "ansi"}function re(o,e){if(e&&(o.toLowerCase()==="transparent"||o.toLowerCase()==="none"))return "\x1B[49m";let t=parseInt(o.slice(1,3),16),n=parseInt(o.slice(3,5),16),r=parseInt(o.slice(5,7),16),i=((a,c,u)=>a===c&&c===u?a<8?16:a>248?231:Math.round((a-8)/247*24)+232:16+36*Math.round(a/255*5)+6*Math.round(c/255*5)+Math.round(u/255*5))(t,n,r);return `\x1B[${e?"48":"38"};5;${i}m`}function se(o,e){if(e&&(o.toLowerCase()==="transparent"||o.toLowerCase()==="none"))return "\x1B[49m";if(e)return "";let t=parseInt(o.slice(1,3),16),n=parseInt(o.slice(3,5),16),r=parseInt(o.slice(5,7),16);return n>t&&n>r&&n>120?"\x1B[32m":t>n&&t>r&&t>120?"\x1B[31m":r>t&&r>n&&r>120?"\x1B[34m":(t+n+r)/3>150?"\x1B[37m":"\x1B[90m"}var de={directory:{bg:"#8b4513",fg:"#ffffff"},git:{bg:"#404040",fg:"#ffffff"},model:{bg:"#2d2d2d",fg:"#ffffff"},session:{bg:"#202020",fg:"#00ffff"},block:{bg:"#2a2a2a",fg:"#87ceeb"},today:{bg:"#1a1a1a",fg:"#98fb98"},tmux:{bg:"#2f4f2f",fg:"#90ee90"},context:{bg:"#4a5568",fg:"#cbd5e0"},metrics:{bg:"#374151",fg:"#d1d5db"},version:{bg:"#3a3a4a",fg:"#b8b8d0"}},he={directory:{bg:"#af5f00",fg:"#ffffff"},git:{bg:"#444444",fg:"#ffffff"},model:{bg:"#3a3a3a",fg:"#ffffff"},session:{bg:"#262626",fg:"#00ffff"},block:{bg:"#303030",fg:"#87ceeb"},today:{bg:"#1c1c1c",fg:"#87ff87"},tmux:{bg:"#444444",fg:"#87ff87"},context:{bg:"#585858",fg:"#d0d0d0"},metrics:{bg:"#4e4e4e",fg:"#d0d0d0"},version:{bg:"#444444",fg:"#d7afff"}},pe={directory:{bg:"#d75f00",fg:"#ffffff"},git:{bg:"#585858",fg:"#ffffff"},model:{bg:"#444444",fg:"#ffffff"},session:{bg:"#303030",fg:"#00ffff"},block:{bg:"#3a3a3a",fg:"#5fafff"},today:{bg:"#262626",fg:"#00ff00"},tmux:{bg:"#585858",fg:"#00ff00"},context:{bg:"#808080",fg:"#ffffff"},metrics:{bg:"#666666",fg:"#ffffff"},version:{bg:"#585858",fg:"#af87ff"}};var be={directory:{bg:"#ff6b47",fg:"#ffffff"},git:{bg:"#4fb3d9",fg:"#ffffff"},model:{bg:"#87ceeb",fg:"#000000"},session:{bg:"#da70d6",fg:"#ffffff"},block:{bg:"#6366f1",fg:"#ffffff"},today:{bg:"#10b981",fg:"#ffffff"},tmux:{bg:"#32cd32",fg:"#ffffff"},context:{bg:"#718096",fg:"#ffffff"},metrics:{bg:"#6b7280",fg:"#ffffff"},version:{bg:"#8b7dd8",fg:"#ffffff"}},ye={directory:{bg:"#ff5f5f",fg:"#ffffff"},git:{bg:"#5fafff",fg:"#ffffff"},model:{bg:"#87d7ff",fg:"#000000"},session:{bg:"#ff5fff",fg:"#ffffff"},block:{bg:"#5f5fff",fg:"#ffffff"},today:{bg:"#00d787",fg:"#ffffff"},tmux:{bg:"#00ff5f",fg:"#ffffff"},context:{bg:"#808080",fg:"#ffffff"},metrics:{bg:"#767676",fg:"#ffffff"},version:{bg:"#af87ff",fg:"#ffffff"}},Ce={directory:{bg:"#ff5f5f",fg:"#ffffff"},git:{bg:"#5fafff",fg:"#ffffff"},model:{bg:"#87d7ff",fg:"#000000"},session:{bg:"#ff5fff",fg:"#ffffff"},block:{bg:"#5f5fff",fg:"#ffffff"},today:{bg:"#00d787",fg:"#ffffff"},tmux:{bg:"#00ff5f",fg:"#ffffff"},context:{bg:"#808080",fg:"#ffffff"},metrics:{bg:"#767676",fg:"#ffffff"},version:{bg:"#af87ff",fg:"#ffffff"}};var _e={directory:{bg:"#434c5e",fg:"#d8dee9"},git:{bg:"#3b4252",fg:"#a3be8c"},model:{bg:"#4c566a",fg:"#81a1c1"},session:{bg:"#2e3440",fg:"#88c0d0"},block:{bg:"#3b4252",fg:"#81a1c1"},today:{bg:"#2e3440",fg:"#8fbcbb"},tmux:{bg:"#2e3440",fg:"#8fbcbb"},context:{bg:"#5e81ac",fg:"#eceff4"},metrics:{bg:"#b48ead",fg:"#2e3440"},version:{bg:"#434c5e",fg:"#88c0d0"}},we={directory:{bg:"#5f87af",fg:"#e4e4e4"},git:{bg:"#4e4e4e",fg:"#87d787"},model:{bg:"#6c6c6c",fg:"#87afd7"},session:{bg:"#3a3a3a",fg:"#5fafaf"},block:{bg:"#4e4e4e",fg:"#87afd7"},today:{bg:"#3a3a3a",fg:"#5fd7d7"},tmux:{bg:"#3a3a3a",fg:"#5fd7d7"},context:{bg:"#5f87d7",fg:"#ffffff"},metrics:{bg:"#d787af",fg:"#3a3a3a"},version:{bg:"#5f87af",fg:"#5fafaf"}},ke={directory:{bg:"#0087af",fg:"#ffffff"},git:{bg:"#585858",fg:"#87d700"},model:{bg:"#808080",fg:"#87afff"},session:{bg:"#444444",fg:"#00d7d7"},block:{bg:"#585858",fg:"#87afff"},today:{bg:"#444444",fg:"#00ffff"},tmux:{bg:"#444444",fg:"#00ffff"},context:{bg:"#0087ff",fg:"#ffffff"},metrics:{bg:"#ff87d7",fg:"#444444"},version:{bg:"#0087af",fg:"#00d7d7"}};var Te={directory:{bg:"#2f334d",fg:"#82aaff"},git:{bg:"#1e2030",fg:"#c3e88d"},model:{bg:"#191b29",fg:"#fca7ea"},session:{bg:"#222436",fg:"#86e1fc"},block:{bg:"#2d3748",fg:"#7aa2f7"},today:{bg:"#1a202c",fg:"#4fd6be"},tmux:{bg:"#191b29",fg:"#4fd6be"},context:{bg:"#414868",fg:"#c0caf5"},metrics:{bg:"#3d59a1",fg:"#c0caf5"},version:{bg:"#292e42",fg:"#bb9af7"}},Se={directory:{bg:"#444478",fg:"#87afff"},git:{bg:"#262640",fg:"#afff87"},model:{bg:"#1c1c30",fg:"#ff87ff"},session:{bg:"#3a3a50",fg:"#5fd7ff"},block:{bg:"#4e4e68",fg:"#5f87ff"},today:{bg:"#262640",fg:"#00d7af"},tmux:{bg:"#1c1c30",fg:"#00d7af"},context:{bg:"#5f5f87",fg:"#d7d7ff"},metrics:{bg:"#5f5faf",fg:"#d7d7ff"},version:{bg:"#444460",fg:"#d787ff"}},xe={directory:{bg:"#5f5faf",fg:"#87afff"},git:{bg:"#303050",fg:"#87ff87"},model:{bg:"#262640",fg:"#ff87ff"},session:{bg:"#444470",fg:"#00d7ff"},block:{bg:"#666680",fg:"#5f87ff"},today:{bg:"#303050",fg:"#00d787"},tmux:{bg:"#262640",fg:"#00d787"},context:{bg:"#808080",fg:"#ffffff"},metrics:{bg:"#8787d7",fg:"#ffffff"},version:{bg:"#585870",fg:"#d787ff"}};var ve={directory:{bg:"#26233a",fg:"#c4a7e7"},git:{bg:"#1f1d2e",fg:"#9ccfd8"},model:{bg:"#191724",fg:"#ebbcba"},session:{bg:"#26233a",fg:"#f6c177"},block:{bg:"#2a273f",fg:"#eb6f92"},today:{bg:"#232136",fg:"#9ccfd8"},tmux:{bg:"#26233a",fg:"#908caa"},context:{bg:"#393552",fg:"#e0def4"},metrics:{bg:"#524f67",fg:"#e0def4"},version:{bg:"#2a273f",fg:"#c4a7e7"}},Ee={directory:{bg:"#444444",fg:"#d787d7"},git:{bg:"#262626",fg:"#87d7d7"},model:{bg:"#1c1c1c",fg:"#ffaf87"},session:{bg:"#444444",fg:"#d7af5f"},block:{bg:"#4e4e4e",fg:"#ff5f87"},today:{bg:"#3a3a3a",fg:"#87d7d7"},tmux:{bg:"#444444",fg:"#9e9e9e"},context:{bg:"#585858",fg:"#e4e4e4"},metrics:{bg:"#767676",fg:"#e4e4e4"},version:{bg:"#4e4e4e",fg:"#d787d7"}},Pe={directory:{bg:"#585858",fg:"#ff87ff"},git:{bg:"#303030",fg:"#00d7d7"},model:{bg:"#262626",fg:"#ffaf87"},session:{bg:"#585858",fg:"#d7af00"},block:{bg:"#666666",fg:"#ff5f87"},today:{bg:"#444444",fg:"#00d7d7"},tmux:{bg:"#585858",fg:"#bcbcbc"},context:{bg:"#808080",fg:"#ffffff"},metrics:{bg:"#a8a8a8",fg:"#000000"},version:{bg:"#666666",fg:"#ff87ff"}};var oe={dark:de,"dark-ansi256":he,"dark-ansi":pe,light:be,"light-ansi256":ye,"light-ansi":Ce,nord:_e,"nord-ansi256":we,"nord-ansi":ke,"tokyo-night":Te,"tokyo-night-ansi256":Se,"tokyo-night-ansi":xe,"rose-pine":ve,"rose-pine-ansi256":Ee,"rose-pine-ansi":Pe};function j(o,e){let t=oe[o];if(!t)return null;if(e==="none"||e==="ansi"){let n=oe[`${o}-ansi`];if(n)return n}if(e==="ansi256"){let n=oe[`${o}-ansi256`];if(n)return n}return t}var l=(o,...e)=>{process.env.CLAUDE_POWERLINE_DEBUG&&console.error(`[DEBUG] ${o}`,...e);};var Ye=promisify(exec),R=class{isGitRepo(e){try{return C.existsSync(y.join(e,".git"))}catch{return false}}async execGitAsync(e,t){return Ye(e,{...t,env:{...process.env,GIT_OPTIONAL_LOCKS:"0"}})}async findGitRoot(e){try{return (await this.execGitAsync("git rev-parse --show-toplevel",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}async getGitInfo(e,t={},n){let r;if(n&&this.isGitRepo(n))r=n;else if(this.isGitRepo(e))r=e;else {let s=await this.findGitRoot(e);if(!s)return null;r=s;}try{let s=await this.getStatusWithBranchAsync(r),i=await this.getAheadBehindAsync(r),a={branch:s.branch||"detached",status:s.status,ahead:i.ahead,behind:i.behind};t.showWorkingTree&&s.workingTree&&(a.staged=s.workingTree.staged,a.unstaged=s.workingTree.unstaged,a.untracked=s.workingTree.untracked,a.conflicts=s.workingTree.conflicts);let c={},u={};t.showSha&&(c.sha=this.getShaAsync(r)),t.showTag&&(c.tag=this.getNearestTagAsync(r)),t.showTimeSinceCommit&&(c.timeSinceCommit=this.getTimeSinceLastCommitAsync(r)),t.showStashCount&&(u.stashCount=this.getStashCountAsync(r)),t.showUpstream&&(u.upstream=this.getUpstreamAsync(r)),t.showRepoName&&(u.repoName=this.getRepoNameAsync(r));let g=new Map;for(let[m,f]of Object.entries(c))try{let d=await f;g.set(m,d);}catch{}return Object.keys(u).length>0&&(await Promise.allSettled(Object.entries(u).map(async([f,d])=>({key:f,value:await d})))).forEach(f=>{f.status==="fulfilled"&&g.set(f.value.key,f.value.value);}),t.showSha&&(a.sha=g.get("sha")||void 0),t.showOperation&&(a.operation=this.getOngoingOperation(r)||void 0),t.showTag&&(a.tag=g.get("tag")||void 0),t.showTimeSinceCommit&&(a.timeSinceCommit=g.get("timeSinceCommit")||void 0),t.showStashCount&&(a.stashCount=g.get("stashCount")||0),t.showUpstream&&(a.upstream=g.get("upstream")||void 0),t.showRepoName&&(a.repoName=g.get("repoName")||void 0,a.isWorktree=this.isWorktree(r)),a}catch{return null}}async getShaAsync(e){try{return (await this.execGitAsync("git rev-parse --short=7 HEAD",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}getOngoingOperation(e){try{let t=y.join(e,".git");return C.existsSync(y.join(t,"MERGE_HEAD"))?"MERGE":C.existsSync(y.join(t,"CHERRY_PICK_HEAD"))?"CHERRY-PICK":C.existsSync(y.join(t,"REVERT_HEAD"))?"REVERT":C.existsSync(y.join(t,"BISECT_LOG"))?"BISECT":C.existsSync(y.join(t,"rebase-merge"))||C.existsSync(y.join(t,"rebase-apply"))?"REBASE":null}catch{return null}}async getNearestTagAsync(e){try{return (await this.execGitAsync("git describe --tags --abbrev=0",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}async getTimeSinceLastCommitAsync(e){try{let n=(await this.execGitAsync("git log -1 --format=%ct",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(!n)return null;let r=parseInt(n)*1e3,s=Date.now();return Math.floor((s-r)/1e3)}catch{return null}}async getStashCountAsync(e){try{let n=(await this.execGitAsync("git stash list",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.split(`
`).length:0}catch{return 0}}async getUpstreamAsync(e){try{return (await this.execGitAsync("git rev-parse --abbrev-ref @{u}",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim()||null}catch{return null}}async getRepoNameAsync(e){try{let n=(await this.execGitAsync("git config --get remote.origin.url",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();return n?n.match(/\/([^/]+?)(\.git)?$/)?.[1]||y.basename(e):y.basename(e)}catch{return y.basename(e)}}isWorktree(e){try{let t=y.join(e,".git");return !!(C.existsSync(t)&&C.statSync(t).isFile())}catch{return false}}async getStatusWithBranchAsync(e){try{l(`[GIT-EXEC] Running git status in ${e}`);let r=(await this.execGitAsync("git status --porcelain -b",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.split(`
`),s=null,i="clean",a=0,c=0,u=0,g=0;for(let m of r)if(m){if(m.startsWith("## ")){let d=m.substring(3).split("...")[0];d&&d!=="HEAD (no branch)"&&(s=d);continue}if(m.length>=2){let f=m.charAt(0),d=m.charAt(1);if(f==="?"&&d==="?"){u++,i==="clean"&&(i="dirty");continue}let h=f+d;if(["DD","AU","UD","UA","DU","AA","UU"].includes(h)){g++,i="conflicts";continue}f!==" "&&f!=="?"&&(a++,i==="clean"&&(i="dirty")),d!==" "&&d!=="?"&&(c++,i==="clean"&&(i="dirty"));}}return {branch:s||await this.getFallbackBranch(e),status:i,workingTree:{staged:a,unstaged:c,untracked:u,conflicts:g}}}catch(t){return l(`Git status with branch command failed in ${e}:`,t),{branch:await this.getFallbackBranch(e),status:"clean"}}}async getFallbackBranch(e){try{let n=(await this.execGitAsync("git branch --show-current",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{try{let n=(await this.execGitAsync("git symbolic-ref --short HEAD",{cwd:e,encoding:"utf8",timeout:2e3})).stdout.trim();if(n)return n}catch{return null}}return null}async getAheadBehindAsync(e){try{l(`[GIT-EXEC] Running git ahead/behind in ${e}`);let[t,n]=await Promise.all([this.execGitAsync("git rev-list --count @{u}..HEAD",{cwd:e,encoding:"utf8",timeout:2e3}),this.execGitAsync("git rev-list --count HEAD..@{u}",{cwd:e,encoding:"utf8",timeout:2e3})]);return {ahead:parseInt(t.stdout.trim())||0,behind:parseInt(n.stdout.trim())||0}}catch(t){return l(`Git ahead/behind command failed in ${e}:`,t),{ahead:0,behind:0}}}};var Xe=promisify(exec),B=class{async getSessionId(){try{if(!process.env.TMUX_PANE)return l("TMUX_PANE not set, not in tmux session"),null;l(`Getting tmux session ID, TMUX_PANE: ${process.env.TMUX_PANE}`);let t=(await Xe("tmux display-message -p '#S'",{encoding:"utf8",timeout:1e3})).stdout.trim();return l(`Tmux session ID: ${t||"empty"}`),t||null}catch(e){return l("Error getting tmux session ID:",e),null}}isInTmux(){return !!process.env.TMUX_PANE}};function H(){let o=[],e=process.env.CLAUDE_CONFIG_DIR;if(e&&e.split(",").forEach(t=>{let n=t.trim();existsSync(n)&&o.push(n);}),o.length===0){let t=homedir(),n=join(t,".config","claude"),r=join(t,".claude");existsSync(n)?o.push(n):existsSync(r)&&o.push(r);}return o}async function G(o){let e=[];for(let t of o){let n=join(t,"projects");if(existsSync(n))try{let r=await readdir(n,{withFileTypes:!0});for(let s of r)if(s.isDirectory()){let i=posix.join(n,s.name);e.push(i);}}catch(r){l(`Failed to read projects directory ${n}:`,r);}}return e}async function W(o){let e=H(),t=await G(e);for(let n of t){let r=posix.join(n,`${o}.jsonl`);if(existsSync(r))return r}return null}async function ce(o){try{return (await stat(o)).mtime}catch{return null}}function et(o){let e=o.message?.id||(typeof o.raw.message=="object"&&o.raw.message!==null&&"id"in o.raw.message?o.raw.message.id:void 0),t="requestId"in o.raw?o.raw.requestId:void 0;return !e||!t?null:`${e}:${t}`}var tt=1024*1024;async function D(o){try{let t=(await stat(o)).size,n;return t>tt?(l(`Using streaming parser for large file ${o} (${Math.round(t/1024)}KB)`),n=await rt(o)):n=await nt(o),l(`Parsed ${n.length} entries from ${o}`),n}catch(e){return l(`Failed to read file ${o}:`,e),[]}}async function nt(o){let t=(await readFile(o,"utf-8")).trim().split(`
`).filter(r=>r.trim()),n=[];for(let r of t)try{let s=JSON.parse(r);if(!s.timestamp)continue;let i={timestamp:new Date(s.timestamp),message:s.message,costUSD:typeof s.costUSD=="number"?s.costUSD:void 0,isSidechain:s.isSidechain===!0,raw:s};n.push(i);}catch(s){l(`Failed to parse JSONL line: ${s}`);continue}return n}async function rt(o){return new Promise((e,t)=>{let n=[],r=createReadStream(o,{encoding:"utf8"}),s=createInterface({input:r,crlfDelay:1/0});s.on("line",i=>{let a=i.trim();if(a)try{let c=JSON.parse(a);if(!c.timestamp)return;let u={timestamp:new Date(c.timestamp),message:c.message,costUSD:typeof c.costUSD=="number"?c.costUSD:void 0,isSidechain:c.isSidechain===!0,raw:c};n.push(u);}catch(c){l(`Failed to parse JSONL line: ${c}`);}}),s.on("close",()=>{e(n);}),s.on("error",i=>{l(`Streaming parser error for ${o}:`,i),t(i);}),r.on("error",i=>{l(`File stream error for ${o}:`,i),t(i);});})}async function V(o,e,t=false){let n=H(),r=await G(n),s=new Set,i=r.map(async h=>{try{let k=(await readdir(h)).filter(b=>b.endsWith(".jsonl")).map(async b=>{let te=posix.join(h,b);if(existsSync(te)){let He=await ce(te);return {filePath:te,mtime:He}}return null});return (await Promise.all(k)).filter(b=>b?.mtime&&(!e||e(b.filePath,b.mtime)))}catch(p){return l(`Failed to read project directory ${h}:`,p),[]}}),c=(await Promise.all(i)).flat().filter(h=>h!==null);t&&c.sort((h,p)=>p.mtime.getTime()-h.mtime.getTime());let u=c.map(h=>h.filePath),g=[],m=u.map(async h=>(await D(h)).filter(w=>!o||o(w))),f=await Promise.all(m);for(let h of f)g.push(...h);g.sort((h,p)=>h.timestamp.getTime()-p.timestamp.getTime());let d=[];for(let h of g){let p=et(h);p&&s.has(p)||(p&&s.add(p),d.push(h));}return d}var v=class{static CACHE_DIR=y.join(homedir(),".claude","powerline");static USAGE_CACHE_DIR=y.join(this.CACHE_DIR,"usage");static LOCKS_DIR=y.join(this.CACHE_DIR,"locks");static isLocked(e){let t=y.join(this.LOCKS_DIR,e);if(!C.existsSync(t))return false;try{let n=C.readFileSync(t,"utf-8"),r=parseInt(n.trim(),10);if(isNaN(r))return l(`Invalid PID in lock file ${e}, removing stale lock`),C.unlinkSync(t),!1;try{return process.kill(r,0),!0}catch(s){return s.code==="ESRCH"?(l(`Removing stale lock file ${e} for dead process ${r}`),C.unlinkSync(t),!1):(l(`Error checking process ${r} for lock ${e}:`,s),!0)}}catch(n){return l(`Error reading lock file ${e}:`,n),true}}static async acquireLock(e,t=5e3){await this.ensureCacheDirectories();let s=y.join(this.LOCKS_DIR,e),i=Date.now(),a=String(process.pid);for(;Date.now()-i<t;)try{return await C.promises.writeFile(s,a,{flag:"wx"}),l(`Lock acquired for ${e}`),!0}catch(c){if(c.code==="EEXIST")await setTimeout(50);else throw c}return l(`Failed to acquire lock for ${e} within ${t}ms`),false}static async releaseLock(e){let t=y.join(this.LOCKS_DIR,e);try{await C.promises.unlink(t),l(`Lock released for ${e}`);}catch(n){n.code!=="ENOENT"&&l(`Error releasing lock for ${e}:`,n);}}static async ensureCacheDirectories(){try{await Promise.all([C.promises.mkdir(this.CACHE_DIR,{recursive:!0}),C.promises.mkdir(this.USAGE_CACHE_DIR,{recursive:!0}),C.promises.mkdir(this.LOCKS_DIR,{recursive:!0})]);}catch(e){l("Failed to create cache directories:",e);}}static createProjectHash(e){return createHash("md5").update(e).digest("hex").substring(0,8)}static async getUsageCache(e,t){let s="utf-8";await this.ensureCacheDirectories();let i=y.join(this.USAGE_CACHE_DIR,`${e}.json`),a=`${e}.usage.lock`;for(let c=0;c<3;c++){if(this.isLocked(a)){l(`Cache for ${e} is locked, waiting...`),await setTimeout(75);continue}try{let g=await C.promises.readFile(i,s),m=JSON.parse(g);return !t||m.timestamp>=t?(l(`[CACHE-HIT] ${e} disk cache: found`),this.deserializeDates(m.data)):(l(`${e} cache outdated: cache=${m.timestamp}, latest=${t}`),null)}catch(g){if(g.code==="ENOENT")return l(`No shared ${e} usage cache found`),null;let m=c+1;l(`Attempt ${m} failed to read ${e} cache: ${g.message}. Retrying...`),await setTimeout(75);}}return l(`Failed to read ${e} cache after 3 attempts.`),null}static deserializeDates(e){return Array.isArray(e)?e.map(t=>({...t,timestamp:new Date(t.timestamp)})):e}static async setUsageCache(e,t,n){let r=`${e}.usage.lock`;if(!await this.acquireLock(r)){l(`Could not acquire lock to set usage cache for ${e}`);return}try{await this.ensureCacheDirectories();let i=y.join(this.USAGE_CACHE_DIR,`${e}.json`),a=n||Date.now(),u=JSON.stringify({data:t,timestamp:a});await C.promises.writeFile(i,u,"utf-8"),l(`[CACHE-SET] ${e} disk cache stored`);}catch(i){l(`Failed to save ${e} usage cache:`,i);}finally{await this.releaseLock(r);}}static async getLatestTranscriptMtime(){try{let e=H(),t=await G(e),n=0;for(let r of t)try{let i=(await C.promises.readdir(r)).filter(a=>a.endsWith(".jsonl"));for(let a of i){let c=y.join(r,a),u=await ce(c);u&&u.getTime()>n&&(n=u.getTime());}}catch(s){l(`Failed to read project directory ${r}:`,s);continue}return n}catch(e){return l("Failed to get latest transcript mtime:",e),Date.now()}}};var Y={"claude-3-haiku-20240307":{name:"Claude 3 Haiku",input:.25,output:1.25,cache_write_5m:.3,cache_write_1h:.5,cache_read:.03},"claude-3-5-haiku-20241022":{name:"Claude 3.5 Haiku",input:.8,output:4,cache_write_5m:1,cache_write_1h:1.6,cache_read:.08},"claude-3-5-haiku-latest":{name:"Claude 3.5 Haiku Latest",input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"claude-haiku-4-5-20251001":{name:"Claude Haiku 4.5",input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"claude-haiku-4-5":{name:"Claude Haiku 4.5",input:1,output:5,cache_write_5m:1.25,cache_write_1h:2,cache_read:.1},"claude-3-opus-latest":{name:"Claude 3 Opus Latest",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-3-opus-20240229":{name:"Claude 3 Opus",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-3-5-sonnet-latest":{name:"Claude 3.5 Sonnet Latest",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-5-sonnet-20240620":{name:"Claude 3.5 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-5-sonnet-20241022":{name:"Claude 3.5 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-opus-4-20250514":{name:"Claude Opus 4",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-opus-4-1":{name:"Claude Opus 4.1",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-opus-4-1-20250805":{name:"Claude Opus 4.1",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-sonnet-4-20250514":{name:"Claude Sonnet 4",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-4-opus-20250514":{name:"Claude 4 Opus",input:15,output:75,cache_write_5m:18.75,cache_write_1h:30,cache_read:1.5},"claude-4-sonnet-20250514":{name:"Claude 4 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-sonnet-4-5":{name:"Claude Sonnet 4.5",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-sonnet-4-5-20250929":{name:"Claude Sonnet 4.5",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-7-sonnet-latest":{name:"Claude 3.7 Sonnet Latest",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3},"claude-3-7-sonnet-20250219":{name:"Claude 3.7 Sonnet",input:3,output:15,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3}},P=class{static executionCache=null;static modelPricingCache=new Map;static GITHUB_PRICING_URL="https://raw.githubusercontent.com/Owloops/claude-powerline/main/pricing.json";static async loadDiskCache(){let t=Date.now()-864e5;return await v.getUsageCache("pricing",t)}static async saveDiskCache(e){await v.setUsageCache("pricing",e);}static async fetchPricingData(){return new Promise(e=>{let t=new URL(this.GITHUB_PRICING_URL),n=get({hostname:t.hostname,path:t.pathname,headers:{"User-Agent":"claude-powerline","Cache-Control":"no-cache"},timeout:5e3},r=>{if(r.statusCode!==200){l(`HTTP ${r.statusCode}: ${r.statusMessage}`),e(null);return}let s="",i=0,a=1024*1024;r.on("data",c=>{if(i+=c.length,i>a){l("Response too large"),n.destroy(),e(null);return}s+=c;}),r.on("end",()=>{try{let u=JSON.parse(s),g=u._meta,m={};for(let[f,d]of Object.entries(u))f!=="_meta"&&(m[f]=d);this.validatePricingData(m)?(l(`Fetched fresh pricing from GitHub for ${Object.keys(m).length} models`),l(`Pricing last updated: ${g?.updated||"unknown"}`),e(m)):(l("Invalid pricing data structure"),e(null));}catch(c){l("Failed to parse JSON:",c),e(null);}}),r.on("error",c=>{l("Response error:",c),e(null);});});n.on("error",r=>{l("Request error:",r),e(null);}),n.on("timeout",()=>{l("Request timeout"),n.destroy(),e(null);}),n.end();})}static async getCurrentPricing(){if(this.executionCache!==null)return l(`[CACHE-HIT] Pricing execution cache: ${Object.keys(this.executionCache).length} models`),this.executionCache;let e=await this.loadDiskCache();if(e)return l(`[CACHE-HIT] Pricing disk cache: ${Object.keys(e).length} models`),this.executionCache=e,l(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(e).length} models`),e;let t=await this.fetchPricingData();return t?(await this.saveDiskCache(t),l(`[CACHE-SET] Pricing disk cache stored: ${Object.keys(t).length} models`),this.executionCache=t,l(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(t).length} models`),t):(l(`[CACHE-FALLBACK] Using offline pricing data: ${Object.keys(Y).length} models`),this.executionCache=Y,l(`[CACHE-SET] Pricing execution cache stored: ${Object.keys(Y).length} models`),Y)}static validatePricingData(e){if(!e||typeof e!="object")return false;for(let[,t]of Object.entries(e)){if(!t||typeof t!="object")return false;let n=t;if(typeof n.input!="number"||typeof n.output!="number"||typeof n.cache_read!="number")return false}return true}static async getModelPricing(e){if(this.modelPricingCache.has(e))return l(`[CACHE-HIT] Model pricing cache: ${e}`),this.modelPricingCache.get(e);let t=await this.getCurrentPricing(),n;return t[e]?n=t[e]:n=this.fuzzyMatchModel(e,t),this.modelPricingCache.set(e,n),l(`[CACHE-SET] Model pricing cache: ${e}`),n}static fuzzyMatchModel(e,t){let n=e.toLowerCase();for(let[s,i]of Object.entries(t))if(s.toLowerCase()===n)return i;let r=[{pattern:["opus-4-1","claude-opus-4-1"],fallback:"claude-opus-4-1-20250805"},{pattern:["opus-4","claude-opus-4"],fallback:"claude-opus-4-20250514"},{pattern:["sonnet-4.5","4-5-sonnet","sonnet-4-5"],fallback:"claude-sonnet-4-5-20250929"},{pattern:["sonnet-4","claude-sonnet-4"],fallback:"claude-sonnet-4-20250514"},{pattern:["sonnet-3.7","3-7-sonnet"],fallback:"claude-3-7-sonnet-20250219"},{pattern:["3-5-sonnet","sonnet-3.5"],fallback:"claude-3-5-sonnet-20241022"},{pattern:["haiku-4.5","4-5-haiku","haiku-4-5"],fallback:"claude-haiku-4-5-20251001"},{pattern:["3-5-haiku","haiku-3.5"],fallback:"claude-3-5-haiku-20241022"},{pattern:["haiku","3-haiku"],fallback:"claude-3-haiku-20240307"},{pattern:["opus"],fallback:"claude-opus-4-20250514"},{pattern:["sonnet"],fallback:"claude-3-5-sonnet-20241022"}];for(let{pattern:s,fallback:i}of r)if(s.some(a=>n.includes(a))&&t[i])return t[i];return t["claude-3-5-sonnet-20241022"]||{name:`${e} (Unknown Model)`,input:3,cache_write_5m:3.75,cache_write_1h:6,cache_read:.3,output:15}}static async calculateCostForEntry(e){let n=e.message?.usage;if(!n)return 0;let r=this.extractModelId(e),s=await this.getModelPricing(r),i=n.input_tokens||0,a=n.output_tokens||0,c=n.cache_creation_input_tokens||0,u=n.cache_read_input_tokens||0,g=i/1e6*s.input,m=a/1e6*s.output,f=u/1e6*s.cache_read,d=c/1e6*s.cache_write_5m;return g+m+d+f}static extractModelId(e){if(e.model&&typeof e.model=="string")return e.model;let t=e.message;if(t?.model){let n=t.model;return typeof n=="string"?n:n?.id||"claude-3-5-sonnet-20241022"}return e.model_id&&typeof e.model_id=="string"?e.model_id:"claude-3-5-sonnet-20241022"}};function ct(o){return {timestamp:o.timestamp.toISOString(),message:{usage:{input_tokens:o.message?.usage?.input_tokens||0,output_tokens:o.message?.usage?.output_tokens||0,cache_creation_input_tokens:o.message?.usage?.cache_creation_input_tokens,cache_read_input_tokens:o.message?.usage?.cache_read_input_tokens}},costUSD:o.costUSD}}var J=class{async getSessionUsage(e){try{let t=await W(e);if(!t)return l(`No transcript found for session: ${e}`),null;l(`Found transcript at: ${t}`);let n=await D(t);if(n.length===0)return {totalCost:0,entries:[]};let r=[],s=0;for(let i of n)if(i.message?.usage){let a=ct(i);if(a.costUSD!==void 0)s+=a.costUSD;else {let c=await P.calculateCostForEntry(i.raw);a.costUSD=c,s+=c;}r.push(a);}return l(`Parsed ${r.length} usage entries, total cost: $${s.toFixed(4)}`),{totalCost:s,entries:r}}catch(t){return l(`Error reading session usage for ${e}:`,t),null}}calculateTokenBreakdown(e){return e.reduce((t,n)=>({input:t.input+(n.message.usage.input_tokens||0),output:t.output+(n.message.usage.output_tokens||0),cacheCreation:t.cacheCreation+(n.message.usage.cache_creation_input_tokens||0),cacheRead:t.cacheRead+(n.message.usage.cache_read_input_tokens||0)}),{input:0,output:0,cacheCreation:0,cacheRead:0})}async getSessionInfo(e,t){let n=await this.getSessionUsage(e);if(!n||n.entries.length===0)return {cost:null,calculatedCost:null,officialCost:null,tokens:null,tokenBreakdown:null};let r=this.calculateTokenBreakdown(n.entries),s=r.input+r.output+r.cacheCreation+r.cacheRead,i=n.totalCost,a=t?.cost?.total_cost_usd??null;return {cost:i??a,calculatedCost:i,officialCost:a,tokens:s,tokenBreakdown:r}}},A=class{sessionProvider=new J;async getUsageInfo(e,t){try{return l(`Starting usage info retrieval for session: ${e}`),{session:await this.sessionProvider.getSessionInfo(e,t)}}catch(n){return l(`Error getting usage info for session ${e}:`,n),{session:{cost:null,calculatedCost:null,officialCost:null,tokens:null,tokenBreakdown:null}}}}};var U=class{thresholds={LOW:50,MEDIUM:80};config;constructor(e){this.config=e;}getContextUsageThresholds(){return this.thresholds}getContextLimit(e){let t=this.config.modelContextLimits||{default:2e5},n=this.getModelType(e);return t[n]||t.default||2e5}getModelType(e){let t=e.toLowerCase();return t.includes("sonnet")?"sonnet":t.includes("opus")?"opus":"default"}async calculateContextTokens(e,t){try{l(`Calculating context tokens from transcript: ${e}`);try{if(!readFileSync(e,"utf-8"))return l("Transcript file is empty"),null}catch{return l("Could not read transcript file"),null}let n=await D(e);if(n.length===0)return l("No entries in transcript"),null;let r=null;for(let s=n.length-1;s>=0;s--){let i=n[s];if(i&&i.message?.usage?.input_tokens&&i.isSidechain!==!0){r=i,l(`Context segment: Found most recent entry at ${i.timestamp.toISOString()}, stopping search`);break}}if(r?.message?.usage){let s=r.message.usage,i=(s.input_tokens||0)+(s.cache_read_input_tokens||0)+(s.cache_creation_input_tokens||0),a=t?this.getContextLimit(t):2e5;l(`Most recent main chain context: ${i} tokens (limit: ${a})`);let c=Math.min(100,Math.max(0,Math.round(i/a*100))),u=Math.round(a*.75),g=Math.min(100,Math.max(0,Math.round(i/u*100))),m=Math.max(0,100-g);return {inputTokens:i,percentage:c,usablePercentage:g,contextLeftPercentage:m,maxTokens:a,usableTokens:u}}return l("No main chain entries with usage data found"),null}catch(n){return l(`Error reading transcript: ${n instanceof Error?n.message:String(n)}`),null}}};var M=class{async loadTranscriptEntries(e){try{let t=await W(e);if(!t)return l(`No transcript found for session: ${e}`),[];l(`Loading transcript from: ${t}`);let r=(await readFile(t,"utf-8")).trim().split(`
`).filter(i=>i.trim()),s=[];for(let i of r)try{let a=JSON.parse(i);if(a.isSidechain===!0)continue;s.push(a);}catch(a){l(`Failed to parse JSONL line: ${a}`);continue}return l(`Loaded ${s.length} transcript entries`),s}catch(t){return l(`Error loading transcript for ${e}:`,t),[]}}calculateMessageCount(e){return e.filter(t=>{let n=t.type||t.message?.role||t.message?.type,r=t.type==="user"&&t.message?.content?.[0]?.type==="tool_result";return n==="user"&&!r}).length}calculateLastResponseTime(e){if(e.length===0)return null;let t=e.slice(-20),n=null,r=null;for(let s of t)if(s.timestamp)try{let i=new Date(s.timestamp),a=s.type||s.message?.role||s.message?.type,c=s.type==="user"&&s.message?.content?.[0]?.type==="tool_result";if(a==="user"&&!c)n=i;else if(a==="assistant"&&n){let g=(i.getTime()-n.getTime())/1e3;g>.1&&g<300&&(r=g);}}catch{continue}return r}async getMetricsInfo(e,t){try{if(l(`Getting metrics from hook data for session: ${e}`),!t.cost)return l("No cost data available in hook data"),{responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null,linesAdded:null,linesRemoved:null};let n=await this.loadTranscriptEntries(e),r=this.calculateMessageCount(n),s=this.calculateLastResponseTime(n);return {responseTime:t.cost.total_api_duration_ms/1e3,lastResponseTime:s,sessionDuration:t.cost.total_duration_ms/1e3,messageCount:r,linesAdded:t.cost.total_lines_added,linesRemoved:t.cost.total_lines_removed}}catch(n){return l(`Error getting metrics from hook data for session ${e}:`,n),{responseTime:null,lastResponseTime:null,sessionDuration:null,messageCount:null,linesAdded:null,linesRemoved:null}}}};function q(o){return o===null?"$0.00":o<.01?"<$0.01":`$${o.toFixed(2)}`}function E(o){return o===null||o===0?"0 tokens":o>=1e6?`${(o/1e6).toFixed(1)}M tokens`:o>=1e3?`${(o/1e3).toFixed(1)}K tokens`:`${o} tokens`}function Be(o){if(!o)return "0 tokens";let e=[];if(o.input>0&&e.push(`${E(o.input).replace(" tokens","")}in`),o.output>0&&e.push(`${E(o.output).replace(" tokens","")}out`),o.cacheCreation>0||o.cacheRead>0){let t=o.cacheCreation+o.cacheRead;e.push(`${E(t).replace(" tokens","")}cached`);}return e.length>0?e.join(" + "):"0 tokens"}function De(o){return o<60?`${o}s`:o<3600?`${Math.floor(o/60)}m`:o<86400?`${Math.floor(o/3600)}h`:o<604800?`${Math.floor(o/86400)}d`:`${Math.floor(o/604800)}w`}function Ae(o){return o<60?`${o.toFixed(0)}s`:o<3600?`${(o/60).toFixed(0)}m`:o<86400?`${(o/3600).toFixed(1)}h`:`${(o/86400).toFixed(1)}d`}function gt(o,e){return !e||e<=0||o<0?null:Math.min(100,o/e*100)}function ue(o,e,t=80){let n=gt(o,e);if(n===null)return {percentage:null,isWarning:false,displayText:""};let r=`${n.toFixed(0)}%`,s=n>=t,i="";return s?i=` !${r}`:n>=50?i=` +${r}`:i=` ${r}`,{percentage:n,isWarning:s,displayText:i}}var F=class{constructor(e,t){this.config=e;this.symbols=t;}renderDirectory(e,t,n){let r=e.workspace?.current_dir||e.cwd||"/",s=e.workspace?.project_dir;if(n?.showBasename)return {text:y.basename(r)||"root",bgColor:t.modeBg,fgColor:t.modeFg};let i=process.env.HOME||process.env.USERPROFILE,a=r,c=s;return i&&(r.startsWith(i)&&(a=r.replace(i,"~")),s&&s.startsWith(i)&&(c=s.replace(i,"~"))),{text:this.getDisplayDirectoryName(a,c),bgColor:t.modeBg,fgColor:t.modeFg}}renderGit(e,t,n){if(!e)return null;let r=[];if(n?.showRepoName&&e.repoName&&(r.push(e.repoName),e.isWorktree&&r.push(this.symbols.git_worktree)),n?.showOperation&&e.operation&&r.push(`[${e.operation}]`),r.push(`${this.symbols.branch} ${e.branch}`),n?.showTag&&e.tag&&r.push(`${this.symbols.git_tag} ${e.tag}`),n?.showSha&&e.sha&&r.push(`${this.symbols.git_sha} ${e.sha}`),n?.showAheadBehind!==false&&(e.ahead>0&&e.behind>0?r.push(`${this.symbols.git_ahead}${e.ahead}${this.symbols.git_behind}${e.behind}`):e.ahead>0?r.push(`${this.symbols.git_ahead}${e.ahead}`):e.behind>0&&r.push(`${this.symbols.git_behind}${e.behind}`)),n?.showWorkingTree){let i=[];e.staged&&e.staged>0&&i.push(`+${e.staged}`),e.unstaged&&e.unstaged>0&&i.push(`~${e.unstaged}`),e.untracked&&e.untracked>0&&i.push(`?${e.untracked}`),e.conflicts&&e.conflicts>0&&i.push(`!${e.conflicts}`),i.length>0&&r.push(`(${i.join(" ")})`);}if(n?.showUpstream&&e.upstream&&r.push(`${this.symbols.git_upstream}${e.upstream}`),n?.showStashCount&&e.stashCount&&e.stashCount>0&&r.push(`${this.symbols.git_stash} ${e.stashCount}`),n?.showTimeSinceCommit&&e.timeSinceCommit!==void 0){let i=De(e.timeSinceCommit);r.push(`${this.symbols.git_time} ${i}`);}let s=this.symbols.git_clean;return e.status==="conflicts"?s=this.symbols.git_conflicts:e.status==="dirty"&&(s=this.symbols.git_dirty),r.push(s),{text:r.join(" "),bgColor:t.gitBg,fgColor:t.gitFg}}renderModel(e,t){let n=e.model?.display_name||"Claude";return {text:`${this.symbols.model} ${n}`,bgColor:t.modelBg,fgColor:t.modelFg}}renderSession(e,t,n){let r=n?.type||"cost",s=n?.costSource,i=this.config.budget?.session,a=()=>s==="calculated"?e.session.calculatedCost:s==="official"?e.session.officialCost:e.session.cost,c=this.formatUsageWithBudget(a(),e.session.tokens,e.session.tokenBreakdown,r,i?.amount,i?.warningThreshold||80,i?.type);return {text:`${this.symbols.session_cost} ${c}`,bgColor:t.sessionBg,fgColor:t.sessionFg}}renderTmux(e,t){return e?{text:`tmux:${e}`,bgColor:t.tmuxBg,fgColor:t.tmuxFg}:{text:"tmux:none",bgColor:t.tmuxBg,fgColor:t.tmuxFg}}renderContext(e,t,n){if(!e)return {text:`${this.symbols.context_time} 0 (100%)`,bgColor:t.contextBg,fgColor:t.contextFg};let r=`${e.contextLeftPercentage}%`;return {text:n?.showPercentageOnly?`${this.symbols.context_time} ${r}`:`${this.symbols.context_time} ${e.inputTokens.toLocaleString()} (${r})`,bgColor:t.contextBg,fgColor:t.contextFg}}renderMetrics(e,t,n,r){if(!e)return {text:`${this.symbols.metrics_response} new`,bgColor:t.metricsBg,fgColor:t.metricsFg};let s=[];if(r?.showLastResponseTime&&e.lastResponseTime!==null){let i=e.lastResponseTime<60?`${e.lastResponseTime.toFixed(1)}s`:`${(e.lastResponseTime/60).toFixed(1)}m`;s.push(`${this.symbols.metrics_last_response} ${i}`);}if(r?.showResponseTime!==false&&e.responseTime!==null){let i=e.responseTime<60?`${e.responseTime.toFixed(1)}s`:`${(e.responseTime/60).toFixed(1)}m`;s.push(`${this.symbols.metrics_response} ${i}`);}if(r?.showDuration!==false&&e.sessionDuration!==null){let i=Ae(e.sessionDuration);s.push(`${this.symbols.metrics_duration} ${i}`);}return r?.showMessageCount!==false&&e.messageCount!==null&&s.push(`${this.symbols.metrics_messages} ${e.messageCount}`),r?.showLinesAdded!==false&&e.linesAdded!==null&&e.linesAdded>0&&s.push(`${this.symbols.metrics_lines_added} ${e.linesAdded}`),r?.showLinesRemoved!==false&&e.linesRemoved!==null&&e.linesRemoved>0&&s.push(`${this.symbols.metrics_lines_removed} ${e.linesRemoved}`),s.length===0?{text:`${this.symbols.metrics_response} active`,bgColor:t.metricsBg,fgColor:t.metricsFg}:{text:s.join(" "),bgColor:t.metricsBg,fgColor:t.metricsFg}}renderBlock(e,t,n){let r;if(e.cost===null&&e.tokens===null)r="No active block";else {let s=n?.type||"cost",i=n?.burnType,a=this.config.budget?.block,c=e.timeRemaining!==null?(()=>{let m=Math.floor(e.timeRemaining/60),f=e.timeRemaining%60;return m>0?`${m}h ${f}m`:`${f}m`})():null,u;switch(s){case "cost":u=this.formatUsageWithBudget(e.cost,null,null,"cost",a?.amount,a?.warningThreshold,a?.type);break;case "tokens":u=this.formatUsageWithBudget(null,e.tokens,null,"tokens",a?.amount,a?.warningThreshold,a?.type);break;case "weighted":let m=a?.type==="tokens"?a.amount:void 0,f=E(e.weightedTokens);if(m&&e.weightedTokens!==null){let d=ue(e.weightedTokens,m,a?.warningThreshold||80);u=`${f}${d.displayText}`;}else u=`${f} (weighted)`;break;case "both":u=this.formatUsageWithBudget(e.cost,e.tokens,null,"both",a?.amount,a?.warningThreshold,a?.type);break;case "time":u=c||"N/A";break;default:u=this.formatUsageWithBudget(e.cost,null,null,"cost",a?.amount,a?.warningThreshold,a?.type);}let g="";if(i&&i!=="none")switch(i){case "cost":g=` | ${e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A"}`;break;case "tokens":g=` | ${e.tokenBurnRate!==null?`${E(Math.round(e.tokenBurnRate))}/h`:"N/A"}`;break;case "both":let d=e.burnRate!==null?e.burnRate<1?`${(e.burnRate*100).toFixed(0)}\xA2/h`:`$${e.burnRate.toFixed(2)}/h`:"N/A",h=e.tokenBurnRate!==null?`${E(Math.round(e.tokenBurnRate))}/h`:"N/A";g=` | ${d} / ${h}`;break}s==="time"?r=u:r=c?`${u}${g} (${c} left)`:`${u}${g}`;}return {text:`${this.symbols.block_cost} ${r}`,bgColor:t.blockBg,fgColor:t.blockFg}}renderToday(e,t,n="cost"){let r=this.config.budget?.today;return {text:`${this.symbols.today_cost} ${this.formatUsageWithBudget(e.cost,e.tokens,e.tokenBreakdown,n,r?.amount,r?.warningThreshold,r?.type)}`,bgColor:t.todayBg,fgColor:t.todayFg}}getDisplayDirectoryName(e,t){return e.startsWith("~")?e:t&&t!==e?e.startsWith(t)?e.slice(t.length+1)||y.basename(t)||"project":y.basename(e)||"root":y.basename(e)||"root"}formatUsageDisplay(e,t,n,r){switch(r){case "cost":return q(e);case "tokens":return E(t);case "both":return `${q(e)} (${E(t)})`;case "breakdown":return Be(n);default:return q(e)}}formatUsageWithBudget(e,t,n,r,s,i=80,a){let c=this.formatUsageDisplay(e,t,n,r);if(s&&s>0){let u=null;if(a==="tokens"&&t!==null?u=t:(a==="cost"&&e!==null||!a&&e!==null)&&(u=e),u!==null){let g=ue(u,s,i);return c+g.displayText}}return c}renderVersion(e,t,n){return e.version?{text:`${this.symbols.version} v${e.version}`,bgColor:t.versionBg,fgColor:t.versionFg}:null}};function ft(o){return o.includes("opus")?5:(o.includes("sonnet")||o.includes("haiku"),1)}function mt(o){return {timestamp:o.timestamp,usage:{inputTokens:o.message?.usage?.input_tokens||0,outputTokens:o.message?.usage?.output_tokens||0,cacheCreationInputTokens:o.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:o.message?.usage?.cache_read_input_tokens||0},costUSD:o.costUSD||0,model:o.message?.model||"unknown"}}var z=class{sessionDurationHours=5;floorToHour(e){let t=new Date(e);return t.setUTCMinutes(0,0,0),t}identifySessionBlocks(e){if(e.length===0)return [];let t=this.sessionDurationHours*60*60*1e3,n=[],r=[...e].sort((a,c)=>a.timestamp.getTime()-c.timestamp.getTime()),s=null,i=[];for(let a of r){let c=a.timestamp;if(s==null)s=this.floorToHour(c),i=[a];else {let u=c.getTime()-s.getTime(),g=i[i.length-1];if(g==null)continue;let m=g.timestamp,f=c.getTime()-m.getTime();u>t||f>t?(n.push(i),s=this.floorToHour(c),i=[a]):i.push(a);}}return s!=null&&i.length>0&&n.push(i),n}createBlockInfo(e,t){let n=new Date,r=this.sessionDurationHours*60*60*1e3,s=new Date(e.getTime()+r),i=t[t.length-1],a=i!=null?i.timestamp:e,c=n.getTime()-a.getTime()<r&&n<s;return {block:t,isActive:c}}findActiveBlock(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(!n||n.length===0)continue;let r=n[0];if(!r)continue;let s=this.floorToHour(r.timestamp),i=this.createBlockInfo(s,n);if(i.isActive)return i.block}return null}async loadUsageEntries(){try{l("Block segment: Loading entries for dynamic session blocks");let e=new Date;e.setDate(e.getDate()-1);let n=await V(void 0,(c,u)=>u>=e,!0),r=[];for(let c of n)if(c.message?.usage){let u=mt(c);!u.costUSD&&c.raw&&(u.costUSD=await P.calculateCostForEntry(c.raw)),r.push(u);}let s=this.identifySessionBlocks(r);l(`Block segment: Found ${s.length} session blocks`);let i=this.findActiveBlock(s),a=[];if(i&&i.length>0){l(`Block segment: Found active block with ${i.length} entries`);let c=i[0],u=i[i.length-1];c&&u&&l(`Block segment: Active block from ${c.timestamp.toISOString()} to ${u.timestamp.toISOString()}`),a=i;}else l("Block segment: No active block found"),a=[];return a}catch(e){return l("Error loading block entries:",e),[]}}async getActiveBlockInfo(){try{let e=await this.loadUsageEntries();if(e.length===0)return l("Block segment: No entries in current block"),{cost:null,tokens:null,weightedTokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null};let t=e.reduce((u,g)=>u+g.costUSD,0),n=e.reduce((u,g)=>u+g.usage.inputTokens+g.usage.outputTokens+g.usage.cacheCreationInputTokens+g.usage.cacheReadInputTokens,0),r=e.reduce((u,g)=>{let m=g.usage.inputTokens+g.usage.outputTokens+g.usage.cacheCreationInputTokens+g.usage.cacheReadInputTokens,f=ft(g.model);return u+m*f},0),s=new Date,i=null;if(e.length>0){let u=e[0];if(u){let g=this.sessionDurationHours*60*60*1e3,m=this.floorToHour(u.timestamp),f=new Date(m.getTime()+g);i=Math.max(0,Math.round((f.getTime()-s.getTime())/(1e3*60)));}}let a=null,c=null;if(e.length>=1&&(t>0||n>0)){let u=e.map(f=>f.timestamp).sort((f,d)=>f.getTime()-d.getTime()),g=u[0],m=u[u.length-1];if(g&&m){let f=(m.getTime()-g.getTime())/6e4;f>0&&(t>0&&(a=t/f*60),n>0&&(c=n/f*60));}}return l(`Block segment: $${t.toFixed(2)}, ${n} tokens, ${i}m remaining, burn rate: ${a?"$"+a.toFixed(2)+"/hr":"N/A"}`),{cost:t,tokens:n,weightedTokens:r,timeRemaining:i,burnRate:a,tokenBurnRate:c}}catch(e){return l("Error getting active block info:",e),{cost:null,tokens:null,weightedTokens:null,timeRemaining:null,burnRate:null,tokenBurnRate:null}}}};function L(o){let e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),n=String(o.getDate()).padStart(2,"0");return `${e}-${t}-${n}`}function dt(o){return o.inputTokens+o.outputTokens+o.cacheCreationInputTokens+o.cacheReadInputTokens}function ht(o){return {timestamp:o.timestamp,usage:{inputTokens:o.message?.usage?.input_tokens||0,outputTokens:o.message?.usage?.output_tokens||0,cacheCreationInputTokens:o.message?.usage?.cache_creation_input_tokens||0,cacheReadInputTokens:o.message?.usage?.cache_read_input_tokens||0},costUSD:o.costUSD||0,model:o.message?.model||"unknown"}}var K=class{async loadTodayEntries(){let t=L(new Date);l(`Today segment: Loading entries for date ${t}`);let n=await v.getLatestTranscriptMtime(),r=await v.getUsageCache("today",n);if(r)return l("Using shared today usage cache"),r;let s=new Date;s.setDate(s.getDate()-1),s.setHours(0,0,0,0);let i=(f,d)=>d>=s,a=new Date;a.setHours(0,0,0,0);let u=await V(f=>f.timestamp>=a,i,true),g=[],m=0;for(let f of u)if(L(f.timestamp)===t&&f.message?.usage){let h=ht(f);!h.costUSD&&f.raw&&(h.costUSD=await P.calculateCostForEntry(f.raw)),g.push(h),m++;}return l(`Today segment: Found ${m} entries for today (${t})`),await v.setUsageCache("today",g,n),g}async getTodayEntries(){try{return await this.loadTodayEntries()}catch(e){return l("Error loading today's entries:",e),[]}}async getTodayInfo(){try{let e=await this.getTodayEntries();if(e.length===0)return {cost:null,tokens:null,tokenBreakdown:null,date:L(new Date)};let t=e.reduce((s,i)=>s+i.costUSD,0),n=e.reduce((s,i)=>s+dt(i.usage),0),r=e.reduce((s,i)=>({input:s.input+i.usage.inputTokens,output:s.output+i.usage.outputTokens,cacheCreation:s.cacheCreation+i.usage.cacheCreationInputTokens,cacheRead:s.cacheRead+i.usage.cacheReadInputTokens}),{input:0,output:0,cacheCreation:0,cacheRead:0});return l(`Today segment: $${t.toFixed(2)}, ${n} tokens total`),{cost:t,tokens:n,tokenBreakdown:r,date:L(new Date)}}catch(e){return l("Error getting today's info:",e),{cost:null,tokens:null,tokenBreakdown:null,date:L(new Date)}}}};var Ue="\x1B[0m",Me={right:"\uE0B0",left_rounded:"\uE0B6",right_rounded:"\uE0B4",branch:"\u2387",model:"\u2731",git_clean:"\u2713",git_dirty:"\u25CF",git_conflicts:"\u26A0",git_ahead:"\u2191",git_behind:"\u2193",git_worktree:"\u29C9",git_tag:"\u2302",git_sha:"\u266F",git_upstream:"\u2192",git_stash:"\u29C7",git_time:"\u25F7",session_cost:"\xA7",block_cost:"\u25F1",today_cost:"\u2609",context_time:"\u25D4",metrics_response:"\u29D6",metrics_last_response:"\u0394",metrics_duration:"\u29D7",metrics_messages:"\u27D0",metrics_lines_added:"+",metrics_lines_removed:"-",metrics_burn:"\u27E2",version:"\u25C8"},Fe={right:"\uE0B0",left_rounded:"\uE0B6",right_rounded:"\uE0B4",branch:"~",model:"M",git_clean:"=",git_dirty:"*",git_conflicts:"!",git_ahead:"^",git_behind:"v",git_worktree:"W",git_tag:"T",git_sha:"#",git_upstream:">>",git_stash:"S",git_time:"@",session_cost:"$",block_cost:"B",today_cost:"D",context_time:"C",metrics_response:"R",metrics_last_response:"L",metrics_duration:"T",metrics_messages:"#",metrics_lines_added:"+",metrics_lines_removed:"-",metrics_burn:"~/h",version:"v"};var Z=class{constructor(e){this.config=e;this.symbols=this.initializeSymbols();}symbols;_usageProvider;_blockProvider;_todayProvider;_contextProvider;_gitService;_tmuxService;_metricsProvider;_segmentRenderer;get usageProvider(){return this._usageProvider||(this._usageProvider=new A),this._usageProvider}get blockProvider(){return this._blockProvider||(this._blockProvider=new z),this._blockProvider}get todayProvider(){return this._todayProvider||(this._todayProvider=new K),this._todayProvider}get contextProvider(){return this._contextProvider||(this._contextProvider=new U(this.config)),this._contextProvider}get gitService(){return this._gitService||(this._gitService=new R),this._gitService}get tmuxService(){return this._tmuxService||(this._tmuxService=new B),this._tmuxService}get metricsProvider(){return this._metricsProvider||(this._metricsProvider=new M),this._metricsProvider}get segmentRenderer(){return this._segmentRenderer||(this._segmentRenderer=new F(this.config,this.symbols)),this._segmentRenderer}needsSegmentInfo(e){return this.config.display.lines.some(t=>t.segments[e]?.enabled)}async generateStatusline(e){let t=this.needsSegmentInfo("session")?await this.usageProvider.getUsageInfo(e.session_id,e):null,n=this.needsSegmentInfo("block")?await this.blockProvider.getActiveBlockInfo():null,r=this.needsSegmentInfo("today")?await this.todayProvider.getTodayInfo():null,s=this.needsSegmentInfo("context")?await this.contextProvider.calculateContextTokens(e.transcript_path,e.model?.id):null,i=this.needsSegmentInfo("metrics")?await this.metricsProvider.getMetricsInfo(e.session_id,e):null;return (await Promise.all(this.config.display.lines.map(c=>this.renderLine(c,e,t,n,r,s,i)))).filter(c=>c.length>0).join(`
`)}async renderLine(e,t,n,r,s,i,a){let c=this.getThemeColors(),u=t.workspace?.current_dir||t.cwd||"/",g=Object.entries(e.segments).filter(([d,h])=>h?.enabled).map(([d,h])=>({type:d,config:h})),m=this.config.display.style==="capsule",f=c.reset;for(let d=0;d<g.length;d++){let h=g[d];if(!h)continue;let p=d===0,w=d===g.length-1,k=w?null:g[d+1],T=k?this.getSegmentBgColor(k.type,c):"",b=await this.renderSegment(h,t,n,r,s,i,a,c,u);b&&(m&&!p&&(f+=" "),f+=this.formatSegment(b.bgColor,b.fgColor,b.text,w?void 0:T,c));}return f}async renderSegment(e,t,n,r,s,i,a,c,u){return e.type==="directory"?this.segmentRenderer.renderDirectory(t,c,e.config):e.type==="model"?this.segmentRenderer.renderModel(t,c):e.type==="git"?await this.renderGitSegment(e.config,t,c,u):e.type==="session"?this.renderSessionSegment(e.config,n,c)