@neilurk12/pi-clean-footer 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +6 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import H from"path";import Se from"os";import me from"path";import{existsSync as se,readFileSync as ie}from"fs";var z=["model","directory","git","context","tokensFull","tokensNoCache","tokensTotal","toks","cost"],J=["default","minimal","compact","dense","focus","muted"],y=[{minWidth:100,left:["model","directory","git","toks"],right:["cost","context","tokensFull"]},{minWidth:80,left:["model","directory","git","toks"],right:["cost","context","tokensNoCache"]},{minWidth:60,left:["model","directory","git","toks"],right:["cost","context","tokensTotal"]},{minWidth:40,left:["model","directory","git"],right:["cost","context"]},{minWidth:0,left:["model"],right:["context"]}],q=[{minWidth:0,left:["model"],right:["context"]}],V=[{minWidth:80,left:["model","git"],right:["context","tokensTotal"]},{minWidth:0,left:["model"],right:["context"]}],X=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:60,left:["model","git"],right:["context","tokensNoCache"]},{minWidth:0,left:["model"],right:["context"]}],Y=[{minWidth:0,left:["model"],right:["context"]}],Q={default:{},minimal:{separator:" \xB7 ",showDirectory:!1,showGit:!1,showTokens:!1,layouts:q},compact:{separator:" \xB7 ",showDirectory:!1,showCacheRead:!1,showCacheWrites:!1,layouts:V},dense:{showCacheRead:!0,showCacheWrites:!0,layouts:X},focus:{showDirectory:!1,showGit:!1,showTokens:!1,layouts:Y},muted:{colors:{model:"muted",directory:"dim",git:"muted",gitDirty:"warning",contextNormal:"muted",contextWarning:"warning",contextDanger:"error",tokens:"dim",cost:"dim",separator:"dim"}}},m={preset:"default",enabled:!0,showGit:!0,showTokens:!0,showCacheRead:!0,showCacheWrites:!1,showContext:!0,showDirectory:!0,showEffort:!0,showCost:!0,separator:" | ",layouts:y,gitRefreshDebounceMs:500,contextWarningPercent:70,contextDangerPercent:85,modelAliases:{},colors:{model:"accent",directory:"dim",git:"success",gitDirty:"warning",contextNormal:"success",contextWarning:"warning",contextDanger:"error",tokens:"muted",cost:"muted",separator:"dim"}};function w(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function R(e){let t=[];"showCache"in e&&t.push("showCache is deprecated; use showCacheRead and showCacheWrites instead"),"showCache"in e&&!("showCacheRead"in e)&&(e={...e,showCacheRead:e.showCache});let n=Z(e.preset,t),o=Q[n],r=w(o,e),i=ee(r.layouts);return{config:{...m,...r,preset:n,separator:typeof r.separator=="string"?r.separator:m.separator,layouts:i.layouts,gitRefreshDebounceMs:re(r.gitRefreshDebounceMs,m.gitRefreshDebounceMs),contextWarningPercent:S(r.contextWarningPercent,m.contextWarningPercent),contextDangerPercent:S(r.contextDangerPercent,m.contextDangerPercent),modelAliases:{...m.modelAliases,...o.modelAliases??{},...e.modelAliases??{}},colors:{...m.colors,...o.colors??{},...e.colors??{}}},loadedPaths:[],warnings:[...t,...i.warnings]}}function Z(e,t){return e===void 0||e==="default"?"default":typeof e!="string"?(t.push("preset must be a string; using default preset"),"default"):J.includes(e)?e:(t.push(`unknown preset '${e}'; using default preset`),"default")}function ee(e){let t=[];if(e===void 0)return{layouts:y,warnings:t};if(!Array.isArray(e))return{layouts:y,warnings:["layouts must be an array; using default layouts"]};let n=e.flatMap((o,r)=>{if(!oe(o))return t.push(`layouts[${r}] must be an object; skipping`),[];let i=ne(o.minWidth);if(i===void 0)return t.push(`layouts[${r}].minWidth must be a non-negative number; skipping`),[];let d=v(o.left,`layouts[${r}].left`,t),u=v(o.right,`layouts[${r}].right`,t,new Set(d));return d.length===0&&u.length===0?(t.push(`layouts[${r}] has no visible segments; skipping`),[]):[{minWidth:i,left:d,right:u}]});return n.length===0?(t.push("no valid layouts configured; using default layouts"),{layouts:y,warnings:t}):{layouts:[...n].sort((o,r)=>r.minWidth-o.minWidth),warnings:t}}function v(e,t,n,o=new Set){if(!Array.isArray(e))return n.push(`${t} must be an array; using empty segment list`),[];let r=[];for(let i of e){if(!te(i)){n.push(`${t} contains unknown segment '${String(i)}'; omitting`);continue}if(o.has(i)){n.push(`${t} contains duplicate segment '${i}'; omitting`);continue}o.add(i),r.push(i)}return r}function te(e){return typeof e=="string"&&z.includes(e)}function oe(e){return typeof e=="object"&&e!==null}function ne(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function re(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:t}function S(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}function k(e,t){return ae([e,t])}function ae(e){let t=[],n={},o;for(let i of e)if(se(i))try{let d=JSON.parse(ie(i,"utf8"));n=w(n,d),t.push(i)}catch(d){o=`${i}: ${d instanceof Error?d.message:String(d)}`}let r=R(n);return{config:r.config,loadedPaths:t,warnings:r.warnings,error:o}}import{execFile as de}from"child_process";import{promisify as ue}from"util";var E=ue(de);function _(e){let t={inRepo:!1,dirtyCount:0},n,o=[];e.onChange&&o.push(e.onChange);async function r(){if(!e.enabled){t={inRepo:!1,dirtyCount:0};return}try{let[u,s]=await Promise.all([E("git",["branch","--show-current"],{cwd:e.cwd,timeout:2e3}),E("git",["status","--porcelain"],{cwd:e.cwd,timeout:2e3})]),a=u.stdout.trim()||"detached",c=s.stdout.split(`
2
- `).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:c}}catch{t={inRepo:!1,dirtyCount:0}}for(let u of o)u()}function i(){d(),n=setTimeout(()=>{n=void 0,r()},e.debounceMs)}function d(){n&&(clearTimeout(n),n=void 0)}return{get state(){return t},schedule:i,clear:d,refresh:r,onChange(u){return o.push(u),()=>{let s=o.indexOf(u);s>=0&&o.splice(s,1)}}}}function I(e){var n,o,r,i,d;let t={input:0,output:0,cacheRead:0,cacheWrite:0};for(let u of e){if(u.type!=="message"||((n=u.message)==null?void 0:n.role)!=="assistant")continue;let s=u.message;t.input+=((o=s.usage)==null?void 0:o.input)??0,t.output+=((r=s.usage)==null?void 0:r.output)??0,t.cacheRead+=((i=s.usage)==null?void 0:i.cacheRead)??0,t.cacheWrite+=((d=s.usage)==null?void 0:d.cacheWrite)??0}return t}function M(e){var n,o,r;let t=0;for(let i of e){if(i.type!=="message"||((n=i.message)==null?void 0:n.role)!=="assistant")continue;let u=(r=(o=i.message.usage)==null?void 0:o.cost)==null?void 0:r.total;typeof u=="number"&&Number.isFinite(u)&&u>0&&(t+=u)}return t}function C(e){if(typeof e!="string")return;let t=e.toLowerCase();if(t==="medium")return"med";if(t==="extra-high"||t==="extra_high"||t==="x-high")return"xhigh";if(["low","med","high","xhigh"].includes(t))return t}function g(e){return!Number.isFinite(e)||e<=0?"0":e<1e3?`${Math.round(e)}`:e<1e6?`${(e/1e3).toFixed(e<1e4?1:0)}k`:`${(e/1e6).toFixed(1)}m`}function P(e){let t=0;for(let n of e){let o=n.codePointAt(0)??0;o>=32&&o<=126?t+=.25:o>=19968&&o<=40959||o>=13312&&o<=19903||o>=63744&&o<=64255||o>=12352&&o<=12447||o>=12448&&o<=12543||o>=44032&&o<=55215||o>=11904&&o<=12255||o>=12544&&o<=12591||o>=12784&&o<=12799||o>=65281&&o<=65374||o>=65381&&o<=65439?t+=.67:o>=12288&&o<=12351?t+=.5:o>65535?t+=1:t+=.5}return Math.ceil(t)}var ce={edit:"edit",write:"write",bash:"bash",ctx_shell:"bash",read:"read",ctx_read:"read",Agent:"agent",agent_browser:"browser"},le=[["gitnexus_","nexus"],["context7_","docs"]],L=8;function W(e){if(!e)return"";let t=ce[e];if(t)return t;for(let[n,o]of le)if(e.startsWith(n))return o;return e.length>L?e.slice(0,L):e}var fe=300,ge=5e3,he=[". ",".. ","..."];function A(e){let t,n=0,o="",r=0,i,d;function u(){s(),i=setInterval(()=>{r=(r+1)%he.length,e.onRenderNeeded()},fe)}function s(){i&&(clearInterval(i),i=void 0)}function a(){c(),d=setTimeout(()=>{d=void 0,t&&(t=void 0,e.onRenderNeeded())},ge)}function c(){d&&(clearTimeout(d),d=void 0)}function h(l,f,b){return{state:"rate",value:(f&&f>0?f:l)/b,approximate:!(f&&f>0)}}return{onMessageStart(){c(),t={startTime:Date.now(),estimatedTokens:0,hasObservedOutput:!1,displayState:{state:"pending"}},e.onRenderNeeded()},onMessageUpdate(l,f,b){if(!t||!f||l!=="text_delta"&&l!=="thinking_delta"&&l!=="toolcall_delta")return;t.estimatedTokens+=P(f),t.hasObservedOutput=!0;let T=(Date.now()-t.startTime)/1e3;T>0&&(t.displayState=h(t.estimatedTokens,b,T)),e.onRenderNeeded()},onMessageEnd(l){if(n=0,s(),t){let f=(Date.now()-t.startTime)/1e3;l&&l>0&&f>0?(t.displayState={state:"rate",value:l/f,approximate:!1},a()):t.hasObservedOutput&&f>0?(t.displayState={state:"rate",value:t.estimatedTokens/f,approximate:!0},a()):t=void 0}e.onRenderNeeded()},onMessageAbort(){if(t)if(t.hasObservedOutput){let l=(Date.now()-t.startTime)/1e3;l>0&&(t.displayState={state:"rate",value:t.estimatedTokens/l,approximate:!0})}else t=void 0;e.onRenderNeeded()},onToolStart(l){n++,o=W(l)+"...",r=0,u(),e.onRenderNeeded()},onToolEnd(){n=Math.max(0,n-1),n===0&&s(),e.onRenderNeeded()},getState(){return n>0?{state:"activity",label:o}:(t==null?void 0:t.displayState)??{state:"hidden"}},shutdown(){t=void 0,n=0,o="",r=0,s(),c()}}}var x=class{#t;#r;#i;#e;#n;#o;#a;#l;#f;#g;#s;#d={input:0,output:0,cacheRead:0,cacheWrite:0};#u=0;#c=0;constructor(t){this.#l=t.globalConfigPath,this.#f=t.getProjectConfigPath,this.#g=t.getThinkingLevel,this.#s=t.onRenderNeeded,this.#t=m,this.#r={config:this.#t,loadedPaths:[],warnings:[]},this.#i=void 0,this.#e=void 0,this.#o=!0,this.#a="",this.#n=A({onRenderNeeded:()=>this.#s()})}async start(t){this.#d={input:0,output:0,cacheRead:0,cacheWrite:0},this.#u=0,this.#c=0,this.#a=t.cwd,this.#r=k(this.#l,this.#f(t.cwd)),this.#t=this.#r.config,this.#i=C(this.#g()),this.#o=this.#t.enabled,this.#o&&(this.#h(t.cwd),await this.#e.refresh())}shutdown(){var t;(t=this.#e)==null||t.clear(),this.#e=void 0,this.#m()}#h(t){this.#e=_({cwd:t,debounceMs:this.#t.gitRefreshDebounceMs,enabled:this.#t.showGit,onChange:()=>this.#s()})}onThinkingLevel(t){this.#i=C(t),this.#s()}onModelSelect(){this.#s()}onMessageStart(t){t==="assistant"&&this.#n.onMessageStart()}onToolExecutionStart(t){this.#n.onToolStart(t)}onToolExecutionUpdate(t){}onToolExecutionEnd(t){var n;this.#n.onToolEnd(),["bash","edit","write"].includes(t)&&((n=this.#e)==null||n.schedule())}onMessageUpdate(t,n,o){this.#n.onMessageUpdate(t,n,o)}onMessageEnd(t,n){t==="assistant"&&this.#n.onMessageEnd(n)}onMessageAbort(){this.#n.onMessageAbort()}onUserBash(){var t;(t=this.#e)==null||t.schedule()}async refresh(){var t;await((t=this.#e)==null?void 0:t.refresh())}async reload(t){var n;this.#m(),this.#r=k(this.#l,this.#f(t.cwd)),this.#t=this.#r.config,this.#o=this.#t.enabled,(n=this.#e)==null||n.clear(),this.#e=void 0,this.#o&&(this.#h(this.#a),await this.#e.refresh()),this.#s()}async toggle(){var t;return this.#m(),this.#o=!this.#o,this.#o?(this.#i=C(this.#g()),this.#h(this.#a),await this.#e.refresh()):((t=this.#e)==null||t.clear(),this.#e=void 0),this.#s(),this.#o}getFooterInput(t){var o,r,i,d,u,s;let n=t.sessionManager.getEntries();return n.length!==this.#c&&(this.#d=I(n),this.#u=M(n),this.#c=n.length),{modelId:((o=t.model)==null?void 0:o.id)??"no-model",thinkingLevel:this.#i,directory:me.basename(t.cwd),gitBranch:(r=this.#e)==null?void 0:r.state.branch,gitDirtyCount:((i=this.#e)==null?void 0:i.state.dirtyCount)??0,contextUsed:((u=(d=t.getContextUsage)==null?void 0:d.call(t))==null?void 0:u.tokens)??0,contextMax:(s=t.model)==null?void 0:s.contextWindow,totals:this.#d,sessionCost:this.#u,toksState:this.#n.getState(),config:this.#t}}#m(){this.#d={input:0,output:0,cacheRead:0,cacheWrite:0},this.#u=0,this.#c=0,this.#n.shutdown()}get isEnabled(){return this.#o}get loadedError(){return this.#r.error}get loadedWarnings(){return this.#r.warnings}get loadedPaths(){return this.#r.loadedPaths}get config(){return this.#t}};import{truncateToWidth as p,visibleWidth as N}from"@earendil-works/pi-tui";function D(e,t,n,o){let r=e.filter(Boolean).join(n),i=t.filter(Boolean).join(n);return pe(r,i,o)}function pe(e,t,n){if(!t)return p(e,n);if(!e)return p(t,n);let o=n-N(e)-N(t);if(o>=1)return p(e+" ".repeat(o)+t,n);let r=Math.max(1,Math.floor((n-1)/2));return p(e,r)+" "+p(t,n-r-1)}function $(e,t){if(t[e])return t[e];let n=e.toLowerCase(),o=n.includes("/")?n.split("/").pop():n;if(t[o])return t[o];if(o.includes("claude")&&o.includes("sonnet"))return o.includes("4-5")||o.includes("4.5")?"sonnet-4.5":o.includes("4")?"sonnet-4":"sonnet";if(o.includes("claude")&&o.includes("opus"))return"opus";if(o.includes("claude")&&o.includes("haiku"))return"haiku";let r=o.match(/gpt-5(?:[.-][a-z0-9]+)*/);if(r)return r[0];let i=o.match(/gpt-4(?:[.-][a-z0-9]+)*/);if(i)return i[0];let d=o.match(/gemini-[a-z0-9.-]+/);return d?d[0].replace(/-preview.*/,""):o.length>24?`${o.slice(0,21)}\u2026`:o}function O(e,t){let n=e.input+e.output,o=`\u2191${g(e.input)} \u2193${g(e.output)} \u03A3${g(n)}`,r=[t.showCacheRead?`\u21AF${g(e.cacheRead)}`:void 0,t.showCacheWrites?`\u21A5${g(e.cacheWrite)}`:void 0].filter(Boolean),i=r.length?`${o} ${r.join(" ")}`:o;return t.cf(t.color,i)}function U(e,t,n){let o=e.input+e.output,r=`\u2191${g(e.input)} \u2193${g(e.output)} \u03A3${g(o)}`;return t(n,r)}function j(e,t,n){let o=e.input+e.output;return t(n,`\u03A3${g(o)}`)}function B(e,t,n){let o=(d,u)=>t.fg(d,u),r=ye(e,o),i=o(e.config.colors.separator,e.config.separator);return[Fe(r,i,e.config.layouts,n)]}function ye(e,t){let n=e.config,o=n.showCacheRead,r=n.showCacheWrites;return{model:Ce(e,t),directory:n.showDirectory?xe(e,t):void 0,git:n.showGit?be(e,t):void 0,context:n.showContext?Te(e,t):void 0,tokensFull:n.showTokens?O(e.totals,{showCacheRead:o,showCacheWrites:r,cf:t,color:n.colors.tokens}):void 0,tokensNoCache:n.showTokens?U(e.totals,t,n.colors.tokens):void 0,tokensTotal:n.showTokens?j(e.totals,t,n.colors.tokens):void 0,toks:we(e,t),cost:ke(e,t)}}function Ce(e,t){let n=$(e.modelId,e.config.modelAliases),o=e.config.showEffort&&e.thinkingLevel?` \u2022 ${e.thinkingLevel}`:"";return t(e.config.colors.model,`${n}${o}`)}function xe(e,t){if(e.directory)return t(e.config.colors.directory,e.directory)}function be(e,t){if(!e.gitBranch)return;let n=t(e.config.colors.git,e.gitBranch);return e.gitDirtyCount<=0?n:`${n} ${t(e.config.colors.gitDirty,`\u25CF${e.gitDirtyCount}`)}`}function Te(e,t){let n=`ctx ${g(e.contextUsed)}/${e.contextMax?g(e.contextMax):"--"}`;if(!e.contextMax||e.contextMax<=0)return t("dim",n);let o=e.contextUsed/e.contextMax*100;return o>=e.config.contextDangerPercent?t(e.config.colors.contextDanger,n):o>=e.config.contextWarningPercent?t(e.config.colors.contextWarning,n):t(e.config.colors.contextNormal,n)}function we(e,t){let n=e.toksState;if(n.state==="hidden")return;if(n.state==="activity")return t(e.config.colors.tokens,n.label);if(n.state==="pending")return t(e.config.colors.tokens,"\u2026 tok/s");let o=Math.round(n.value);return n.approximate?t(e.config.colors.tokens,`\u2248${o} tok/s`):t(e.config.colors.tokens,`${o} tok/s`)}function ke(e,t){if(e.config.showCost&&!(e.sessionCost==null||e.sessionCost<=0))return t(e.config.colors.cost,`$${e.sessionCost.toFixed(2)}`)}function Fe(e,t,n,o){let r=ve(n,o),i=G(r.left,e),d=G(r.right,e);return D(i,d,t,o)}function ve(e,t){return e.find(n=>t>=n.minWidth)??e[e.length-1]}function G(e,t){return e.map(n=>t[n]).filter(n=>!!n)}function K(e){return e!==null&&typeof e=="object"&&"usage"in e&&e.usage!==null&&typeof e.usage=="object"}function F(e){if(e===null||typeof e!="object")return;let t=e,n=K(t)?t.usage.output:void 0;if(typeof n=="number"&&Number.isFinite(n)&&n>=0)return n;let o=t.message;if(o!==null&&typeof o=="object"&&K(o)){let r=o.usage.output;if(typeof r=="number"&&Number.isFinite(r)&&r>=0)return r}}function lt(e){let t=H.join(Se.homedir(),".pi","agent","clean-footer.json"),n=s=>H.join(s,".pi","clean-footer.json"),o=()=>{},r=new x({globalConfigPath:t,getProjectConfigPath:n,getThinkingLevel:()=>{var s;return(s=e.getThinkingLevel)==null?void 0:s.call(e)},onRenderNeeded:()=>o()});e.registerCommand("footer",{description:"Toggle, refresh, or configure the clean footer",handler:async(s,a)=>{let c=s.trim();if(c==="refresh"){await r.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(c==="reload"){await r.reload(a),a.hasUI&&r.isEnabled&&i(a),a.hasUI&&!r.isEnabled&&a.ui.setFooter(void 0),o(),d(a);return}if(c==="config"){u(a);return}let h=await r.toggle();a.hasUI&&(h?(i(a),a.ui.notify("Clean footer enabled","info")):(a.ui.setFooter(void 0),a.ui.notify("Default footer restored","info")))}}),e.on("session_start",async(s,a)=>{await r.start(a),a.hasUI&&r.loadedError&&r.isEnabled&&a.ui.notify(`Config error: ${r.loadedError}`,"error"),a.hasUI&&r.isEnabled&&i(a)}),e.on("session_shutdown",(s,a)=>{r.shutdown(),o=()=>{},a.hasUI&&a.ui.setFooter(void 0)}),e.on("thinking_level_select",s=>{r.onThinkingLevel(s.level)}),e.on("model_select",()=>{r.onModelSelect()}),e.on("message_start",s=>{r.onMessageStart(s.message.role)}),e.on("message_end",s=>{let a=s.message,c=a.role==="assistant"?F(a):void 0;r.onMessageEnd(a.role,c)}),e.on("message_update",s=>{let a=s.assistantMessageEvent;if(s.message.role==="assistant"){let c="delta"in a?a.delta:void 0,h=F(s.message);r.onMessageUpdate(a.type,c,h)}}),e.on("tool_execution_start",s=>{r.onToolExecutionStart(s.toolName)}),e.on("tool_execution_update",s=>{r.onToolExecutionUpdate(s.toolName)}),e.on("tool_execution_end",s=>{r.onToolExecutionEnd(s.toolName)}),e.on("user_bash",()=>{r.onUserBash()});function i(s){s.hasUI&&s.ui.setFooter((a,c)=>(o=()=>a.requestRender(),{invalidate(){},render(h){let l=r.getFooterInput(s);return B(l,c,h)}}))}function d(s){s.hasUI&&(r.loadedError?s.ui.notify(`Clean footer config error: ${r.loadedError}`,"error"):r.loadedWarnings.length>0?s.ui.notify(`Clean footer config loaded with warnings: ${r.loadedWarnings.join("; ")}`,"warning"):s.ui.notify("Clean footer config loaded","info"))}function u(s){if(!s.hasUI)return;let a=r.loadedPaths.length?r.loadedPaths.join(`
3
- `):"none",c=r.loadedWarnings.length?r.loadedWarnings.join(`
4
- `):"none",h=n(s.cwd);s.ui.notify(["Clean footer config",`global: ${t}`,`project: ${h}`,`loaded:
1
+ import z from"path";import Ee from"os";import W from"path";import{existsSync as ie,readFileSync as ae}from"fs";var J=["model","directory","git","context","tokensFull","tokensNoCache","tokensTotal","toks","cost"],X=["default","minimal","compact","dense","focus","muted"],y=[{minWidth:100,left:["model","directory","git","toks"],right:["cost","context","tokensFull"]},{minWidth:80,left:["model","directory","git","toks"],right:["cost","context","tokensNoCache"]},{minWidth:60,left:["model","directory","git","toks"],right:["cost","context","tokensTotal"]},{minWidth:40,left:["model","directory","git"],right:["cost","context"]},{minWidth:0,left:["model"],right:["context"]}],q=[{minWidth:0,left:["model"],right:["context"]}],V=[{minWidth:80,left:["model","git"],right:["context","tokensTotal"]},{minWidth:0,left:["model"],right:["context"]}],Y=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:60,left:["model","git"],right:["context","tokensNoCache"]},{minWidth:0,left:["model"],right:["context"]}],Q=[{minWidth:0,left:["model"],right:["context"]}],Z={default:{},minimal:{separator:" \xB7 ",showDirectory:!1,showGit:!1,showTokens:!1,layouts:q},compact:{separator:" \xB7 ",showDirectory:!1,showCacheRead:!1,showCacheWrites:!1,layouts:V},dense:{showCacheRead:!0,showCacheWrites:!0,layouts:Y},focus:{showDirectory:!1,showGit:!1,showTokens:!1,layouts:Q},muted:{colors:{model:"muted",directory:"dim",git:"muted",gitDirty:"warning",contextNormal:"muted",contextWarning:"warning",contextDanger:"error",tokens:"dim",cost:"dim",separator:"dim"}}},m={preset:"default",enabled:!0,showGit:!0,showTokens:!0,showCacheRead:!0,showCacheWrites:!1,showContext:!0,showDirectory:!0,showEffort:!0,showCost:!0,separator:" | ",layouts:y,gitRefreshDebounceMs:500,contextWarningPercent:70,contextDangerPercent:85,modelAliases:{},colors:{model:"accent",directory:"dim",git:"success",gitDirty:"warning",contextNormal:"success",contextWarning:"warning",contextDanger:"error",tokens:"muted",cost:"muted",separator:"dim"}};function w(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function E(e){let t=[];"showCache"in e&&t.push("showCache is deprecated; use showCacheRead and showCacheWrites instead"),"showCache"in e&&!("showCacheRead"in e)&&(e={...e,showCacheRead:e.showCache});let n=ee(e.preset,t),o=Z[n],r=w(o,e),s=te(r.layouts);return{config:{...m,...r,preset:n,separator:typeof r.separator=="string"?r.separator:m.separator,layouts:s.layouts,gitRefreshDebounceMs:se(r.gitRefreshDebounceMs,m.gitRefreshDebounceMs),contextWarningPercent:v(r.contextWarningPercent,m.contextWarningPercent),contextDangerPercent:v(r.contextDangerPercent,m.contextDangerPercent),modelAliases:{...m.modelAliases,...o.modelAliases??{},...e.modelAliases??{}},colors:{...m.colors,...o.colors??{},...e.colors??{}}},loadedPaths:[],warnings:[...t,...s.warnings]}}function ee(e,t){return e===void 0||e==="default"?"default":typeof e!="string"?(t.push("preset must be a string; using default preset"),"default"):X.includes(e)?e:(t.push(`unknown preset '${e}'; using default preset`),"default")}function te(e){let t=[];if(e===void 0)return{layouts:y,warnings:t};if(!Array.isArray(e))return{layouts:y,warnings:["layouts must be an array; using default layouts"]};let n=e.flatMap((o,r)=>{if(!ne(o))return t.push(`layouts[${r}] must be an object; skipping`),[];let s=re(o.minWidth);if(s===void 0)return t.push(`layouts[${r}].minWidth must be a non-negative number; skipping`),[];let d=S(o.left,`layouts[${r}].left`,t),f=S(o.right,`layouts[${r}].right`,t,new Set(d));return d.length===0&&f.length===0?(t.push(`layouts[${r}] has no visible segments; skipping`),[]):[{minWidth:s,left:d,right:f}]});return n.length===0?(t.push("no valid layouts configured; using default layouts"),{layouts:y,warnings:t}):{layouts:[...n].sort((o,r)=>r.minWidth-o.minWidth),warnings:t}}function S(e,t,n,o=new Set){if(!Array.isArray(e))return n.push(`${t} must be an array; using empty segment list`),[];let r=[];for(let s of e){if(!oe(s)){n.push(`${t} contains unknown segment '${String(s)}'; omitting`);continue}if(o.has(s)){n.push(`${t} contains duplicate segment '${s}'; omitting`);continue}o.add(s),r.push(s)}return r}function oe(e){return typeof e=="string"&&J.includes(e)}function ne(e){return typeof e=="object"&&e!==null}function re(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function se(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:t}function v(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}function k(e,t){return de([e,t])}function de(e){let t=[],n={},o;for(let s of e)if(ie(s))try{let d=JSON.parse(ae(s,"utf8"));if(typeof d!="object"||d===null||Array.isArray(d)){o=`${s}: config must be a JSON object`;continue}n=w(n,d),t.push(s)}catch(d){o=`${s}: ${d instanceof Error?d.message:String(d)}`}let r=E(n);return{config:r.config,loadedPaths:t,warnings:r.warnings,error:o}}import{execFile as ce}from"child_process";import{promisify as ue}from"util";var R=ue(ce),_=2e3;function M(e){let t={inRepo:!1,dirtyCount:0},n,o=[],r=0;e.onChange&&o.push(e.onChange);async function s(){if(!e.enabled){t={inRepo:!1,dirtyCount:0};return}let i=++r;try{let[a,u]=await Promise.all([R("git",["branch","--show-current"],{cwd:e.cwd,timeout:_}),R("git",["status","--porcelain"],{cwd:e.cwd,timeout:_})]);if(i!==r)return;let h=a.stdout.trim()||"detached",c=u.stdout.split(`
2
+ `).filter(Boolean).length;t={inRepo:!0,branch:h,dirtyCount:c}}catch(a){if(i!==r)return;let u=a.code;a instanceof Error&&u!=null&&u!=="ENOENT"&&typeof u!="number"&&console.error("[clean-footer] git refresh failed:",a.message),t={inRepo:!1,dirtyCount:0}}for(let a of[...o])try{a()}catch{}}function d(){f(),n=setTimeout(()=>{n=void 0,s()},e.debounceMs)}function f(){n&&(clearTimeout(n),n=void 0)}return{get state(){return t},schedule:d,clear:f,refresh:s,onChange(i){return o.push(i),()=>{let a=o.indexOf(i);a>=0&&o.splice(a,1)}}}}function*I(e){var t;for(let n of e)n.type==="message"&&((t=n.message)==null?void 0:t.role)==="assistant"&&(yield n.message)}function L(e){var n,o,r,s;let t={input:0,output:0,cacheRead:0,cacheWrite:0};for(let d of I(e))t.input+=((n=d.usage)==null?void 0:n.input)??0,t.output+=((o=d.usage)==null?void 0:o.output)??0,t.cacheRead+=((r=d.usage)==null?void 0:r.cacheRead)??0,t.cacheWrite+=((s=d.usage)==null?void 0:s.cacheWrite)??0;return t}function A(e){var n,o;let t=0;for(let r of I(e)){let s=(o=(n=r.usage)==null?void 0:n.cost)==null?void 0:o.total;typeof s=="number"&&Number.isFinite(s)&&s>0&&(t+=s)}return t}function C(e){if(typeof e!="string")return;let t=e.toLowerCase();if(t==="medium")return"med";if(t==="extra-high"||t==="extra_high"||t==="x-high")return"xhigh";if(["low","med","high","xhigh"].includes(t))return t}function g(e){return!Number.isFinite(e)||e<=0?"0":e<1e3?`${Math.round(e)}`:e<1e6?`${(e/1e3).toFixed(e<1e4?1:0)}k`:`${(e/1e6).toFixed(1)}m`}var fe=[". ",".. ","..."];function le(e){let t=0;for(let n of e){let o=n.codePointAt(0)??0;o>=32&&o<=126?t+=.25:o>=19968&&o<=40959||o>=13312&&o<=19903||o>=63744&&o<=64255||o>=12352&&o<=12447||o>=12448&&o<=12543||o>=44032&&o<=55215||o>=11904&&o<=12255||o>=12544&&o<=12591||o>=12784&&o<=12799||o>=65281&&o<=65374||o>=65381&&o<=65439?t+=.67:o>=12288&&o<=12351?t+=.5:o>65535?t+=1:t+=.5}return Math.ceil(t)}var ge={edit:"edit",write:"write",bash:"bash",ctx_shell:"bash",read:"read",ctx_read:"read",Agent:"agent",agent_browser:"browser"},he=[["gitnexus_","nexus"],["context7_","docs"]],N=8;function me(e){if(!e)return"";let t=ge[e];if(t)return t;for(let[n,o]of he)if(e.startsWith(n))return o;return e.length>N?e.slice(0,N):e}function P(e){let t,n=0,o="",r=0,s,d;function f(){i(),s=setInterval(()=>{r=(r+1)%fe.length,e.onRenderNeeded()},300)}function i(){s&&(clearInterval(s),s=void 0)}function a(){u(),d=setTimeout(()=>{d=void 0,t&&(t=void 0,e.onRenderNeeded())},5e3)}function u(){d&&(clearTimeout(d),d=void 0)}function h(c,l,x){return{state:"rate",value:(l&&l>0?l:c)/x,approximate:!(l&&l>0)}}return{onMessageStart(){u(),t={startTime:Date.now(),estimatedTokens:0,hasObservedOutput:!1,displayState:{state:"pending"}},e.onRenderNeeded()},onMessageUpdate(c,l,x){if(!t||!l||c!=="text_delta"&&c!=="thinking_delta"&&c!=="toolcall_delta")return;t.estimatedTokens+=le(l),t.hasObservedOutput=!0;let T=(Date.now()-t.startTime)/1e3;T>0&&(t.displayState=h(t.estimatedTokens,x,T)),e.onRenderNeeded()},onMessageEnd(c){if(n=0,i(),t){let l=(Date.now()-t.startTime)/1e3;c&&c>0&&l>0?(t.displayState={state:"rate",value:c/l,approximate:!1},a()):t.hasObservedOutput&&l>0?(t.displayState={state:"rate",value:t.estimatedTokens/l,approximate:!0},a()):t=void 0}e.onRenderNeeded()},onMessageAbort(){if(t)if(t.hasObservedOutput){let c=(Date.now()-t.startTime)/1e3;c>0&&(t.displayState={state:"rate",value:t.estimatedTokens/c,approximate:!0})}else t=void 0;e.onRenderNeeded()},onToolStart(c){n++,o=me(c)+"...",r=0,f(),e.onRenderNeeded()},onToolEnd(){n=Math.max(0,n-1),n===0&&i(),e.onRenderNeeded()},getState(){return n>0?{state:"activity",label:o}:(t==null?void 0:t.displayState)??{state:"hidden"}},shutdown(){t=void 0,n=0,o="",r=0,i(),u()}}}var pe=["bash","edit","write"],b=class{#t;#r;#i;#e;#n;#o;#a;#f;#l;#g;#h;#s;#d={input:0,output:0,cacheRead:0,cacheWrite:0};#c=0;#u=0;constructor(t){this.#l=t.globalConfigPath,this.#g=t.getProjectConfigPath,this.#h=t.getThinkingLevel,this.#s=t.onRenderNeeded,this.#t=m,this.#r={config:this.#t,loadedPaths:[],warnings:[]},this.#i=void 0,this.#e=void 0,this.#o=!0,this.#a="",this.#f="",this.#n=P({onRenderNeeded:()=>this.#s()})}async start(t){this.#d={input:0,output:0,cacheRead:0,cacheWrite:0},this.#c=0,this.#u=0,this.#a=t.cwd,this.#f=W.basename(t.cwd),this.#r=k(this.#l,this.#g(t.cwd)),this.#t=this.#r.config,this.#i=C(this.#h()),this.#o=this.#t.enabled,this.#o&&(this.#m(t.cwd),await this.#e.refresh())}shutdown(){var t;(t=this.#e)==null||t.clear(),this.#e=void 0,this.#p()}#m(t){this.#e=M({cwd:t,debounceMs:this.#t.gitRefreshDebounceMs,enabled:this.#t.showGit,onChange:()=>this.#s()})}onThinkingLevel(t){this.#i=C(t),this.#s()}onModelSelect(){this.#s()}onMessageStart(t){t==="assistant"&&this.#n.onMessageStart()}onToolExecutionStart(t){this.#n.onToolStart(t)}onToolExecutionEnd(t){var n;this.#n.onToolEnd(),pe.includes(t)&&((n=this.#e)==null||n.schedule())}onMessageUpdate(t,n,o){this.#n.onMessageUpdate(t,n,o)}onMessageEnd(t,n){t==="assistant"&&this.#n.onMessageEnd(n)}onMessageAbort(){this.#n.onMessageAbort()}onUserBash(){var t;(t=this.#e)==null||t.schedule()}async refresh(){var t;await((t=this.#e)==null?void 0:t.refresh())}async reload(t){var n;this.#p(),this.#r=k(this.#l,this.#g(t.cwd)),this.#t=this.#r.config,this.#o=this.#t.enabled,(n=this.#e)==null||n.clear(),this.#e=void 0,this.#o&&(this.#m(this.#a),await this.#e.refresh()),this.#s()}async toggle(){var t;return this.#p(),this.#o=!this.#o,this.#o?(this.#i=C(this.#h()),this.#m(this.#a),await this.#e.refresh()):((t=this.#e)==null||t.clear(),this.#e=void 0),this.#s(),this.#o}getFooterInput(t){var o,r,s,d,f,i;let n=t.sessionManager.getEntries();return n.length!==this.#u&&(this.#d=L(n),this.#c=A(n),this.#u=n.length),{modelId:((o=t.model)==null?void 0:o.id)??"no-model",thinkingLevel:this.#i,directory:this.#f||W.basename(t.cwd),gitBranch:(r=this.#e)==null?void 0:r.state.branch,gitDirtyCount:((s=this.#e)==null?void 0:s.state.dirtyCount)??0,contextUsed:((f=(d=t.getContextUsage)==null?void 0:d.call(t))==null?void 0:f.tokens)??0,contextMax:(i=t.model)==null?void 0:i.contextWindow,totals:this.#d,sessionCost:this.#c,toksState:this.#n.getState(),config:this.#t}}#p(){this.#d={input:0,output:0,cacheRead:0,cacheWrite:0},this.#c=0,this.#u=0,this.#n.shutdown()}get isEnabled(){return this.#o}get loadedError(){return this.#r.error}get loadedWarnings(){return this.#r.warnings}get loadedPaths(){return this.#r.loadedPaths}get config(){return this.#t}};import{truncateToWidth as p,visibleWidth as D}from"@earendil-works/pi-tui";function O(e,t,n,o){let r=e.filter(Boolean).join(n),s=t.filter(Boolean).join(n);return ye(r,s,o)}function ye(e,t,n){if(!t)return p(e,n);if(!e)return p(t,n);let o=n-D(e)-D(t);if(o>=1)return p(e+" ".repeat(o)+t,n);let r=Math.max(1,Math.floor((n-1)/2));return p(e,r)+" "+p(t,n-r-1)}function $(e,t){if(t[e])return t[e];let n=e.toLowerCase(),o=n.includes("/")?n.split("/").pop():n;if(t[o])return t[o];if(o.includes("claude")&&o.includes("sonnet"))return o.includes("4-5")||o.includes("4.5")?"sonnet-4.5":o.includes("4")?"sonnet-4":"sonnet";if(o.includes("claude")&&o.includes("opus"))return"opus";if(o.includes("claude")&&o.includes("haiku"))return"haiku";let r=o.match(/gpt-5(?:[.-][a-z0-9]+)*/);if(r)return r[0];let s=o.match(/gpt-4(?:[.-][a-z0-9]+)*/);if(s)return s[0];let d=o.match(/gemini-[a-z0-9.-]+/);return d?d[0].replace(/-preview.*/,""):o.length>24?`${o.slice(0,21)}\u2026`:o}function j(e,t){let n=e.input+e.output,o=`\u2191${g(e.input)} \u2193${g(e.output)} \u03A3${g(n)}`,r=[t.showCacheRead?`\u21AF${g(e.cacheRead)}`:void 0,t.showCacheWrites?`\u21A5${g(e.cacheWrite)}`:void 0].filter(Boolean),s=r.length?`${o} ${r.join(" ")}`:o;return t.cf(t.color,s)}function U(e,t,n){let o=e.input+e.output,r=`\u2191${g(e.input)} \u2193${g(e.output)} \u03A3${g(o)}`;return t(n,r)}function G(e,t,n){let o=e.input+e.output;return t(n,`\u03A3${g(o)}`)}function B(e,t,n){let o=(d,f)=>t.fg(d,f),r=Ce(e,o),s=o(e.config.colors.separator,e.config.separator);return[Se(r,s,e.config.layouts,n)]}function Ce(e,t){let n=e.config,o=n.showTokens?{tokensFull:()=>j(e.totals,{showCacheRead:n.showCacheRead,showCacheWrites:n.showCacheWrites,cf:t,color:n.colors.tokens}),tokensNoCache:()=>U(e.totals,t,n.colors.tokens),tokensTotal:()=>G(e.totals,t,n.colors.tokens)}:{};return{model:be(e,t),directory:n.showDirectory?xe(e,t):void 0,git:n.showGit?Te(e,t):void 0,context:n.showContext?we(e,t):void 0,...o,toks:ke(e,t),cost:Fe(e,t)}}function be(e,t){let n=$(e.modelId,e.config.modelAliases),o=e.config.showEffort&&e.thinkingLevel?` \u2022 ${e.thinkingLevel}`:"";return t(e.config.colors.model,`${n}${o}`)}function xe(e,t){if(e.directory)return t(e.config.colors.directory,e.directory)}function Te(e,t){if(!e.gitBranch)return;let n=t(e.config.colors.git,e.gitBranch);return e.gitDirtyCount<=0?n:`${n} ${t(e.config.colors.gitDirty,`\u25CF${e.gitDirtyCount}`)}`}function we(e,t){let n=`ctx ${g(e.contextUsed)}/${e.contextMax?g(e.contextMax):"--"}`;if(!e.contextMax||e.contextMax<=0)return t("dim",n);let o=e.contextUsed/e.contextMax*100;return o>=e.config.contextDangerPercent?t(e.config.colors.contextDanger,n):o>=e.config.contextWarningPercent?t(e.config.colors.contextWarning,n):t(e.config.colors.contextNormal,n)}function ke(e,t){let n=e.toksState;if(n.state==="hidden")return;if(n.state==="activity")return t(e.config.colors.tokens,n.label);if(n.state==="pending")return t(e.config.colors.tokens,"\u2026 tok/s");let o=Math.round(n.value);return n.approximate?t(e.config.colors.tokens,`\u2248${o} tok/s`):t(e.config.colors.tokens,`${o} tok/s`)}function Fe(e,t){if(e.config.showCost&&!(e.sessionCost==null||e.sessionCost<=0))return t(e.config.colors.cost,`$${e.sessionCost.toFixed(2)}`)}function Se(e,t,n,o){let r=ve(n,o),s=H(r.left,e),d=H(r.right,e);return O(s,d,t,o)}function ve(e,t){return e.find(n=>t>=n.minWidth)??e[e.length-1]}function H(e,t){return e.map(n=>{let o=t[n];return typeof o=="function"?o():o}).filter(n=>!!n)}function K(e){return e!==null&&typeof e=="object"&&"usage"in e&&e.usage!==null&&typeof e.usage=="object"}function F(e){if(e===null||typeof e!="object")return;let t=e,n=K(t)?t.usage.output:void 0;if(typeof n=="number"&&Number.isFinite(n)&&n>=0)return n;let o=t.message;if(o!==null&&typeof o=="object"&&K(o)){let r=o.usage.output;if(typeof r=="number"&&Number.isFinite(r)&&r>=0)return r}}function dt(e){let t=z.join(Ee.homedir(),".pi","agent","clean-footer.json"),n=i=>z.join(i,".pi","clean-footer.json"),o=()=>{},r=new b({globalConfigPath:t,getProjectConfigPath:n,getThinkingLevel:()=>{var i;return(i=e.getThinkingLevel)==null?void 0:i.call(e)},onRenderNeeded:()=>o()});e.registerCommand("footer",{description:"Toggle, refresh, or configure the clean footer",handler:async(i,a)=>{let u=i.trim();if(u==="refresh"){await r.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(u==="reload"){await r.reload(a),a.hasUI&&r.isEnabled&&s(a),a.hasUI&&!r.isEnabled&&a.ui.setFooter(void 0),o(),d(a);return}if(u==="config"){f(a);return}let h=await r.toggle();a.hasUI&&(h?(s(a),a.ui.notify("Clean footer enabled","info")):(a.ui.setFooter(void 0),a.ui.notify("Default footer restored","info")))}}),e.on("session_start",async(i,a)=>{await r.start(a),a.hasUI&&r.loadedError&&r.isEnabled&&a.ui.notify(`Config error: ${r.loadedError}`,"error"),a.hasUI&&r.isEnabled&&s(a)}),e.on("session_shutdown",(i,a)=>{r.shutdown(),o=()=>{},a.hasUI&&a.ui.setFooter(void 0)}),e.on("thinking_level_select",i=>{r.onThinkingLevel(i.level)}),e.on("model_select",()=>{r.onModelSelect()}),e.on("message_start",i=>{r.onMessageStart(i.message.role)}),e.on("message_end",i=>{let a=i.message,u=a.role==="assistant"?F(a):void 0;r.onMessageEnd(a.role,u)}),e.on("message_update",i=>{let a=i.assistantMessageEvent;if(i.message.role==="assistant"){let u="delta"in a?a.delta:void 0,h=F(i.message);r.onMessageUpdate(a.type,u,h)}}),e.on("tool_execution_start",i=>{r.onToolExecutionStart(i.toolName)}),e.on("tool_execution_end",i=>{r.onToolExecutionEnd(i.toolName)}),e.on("user_bash",()=>{r.onUserBash()});function s(i){i.hasUI&&i.ui.setFooter((a,u)=>(o=()=>a.requestRender(),{invalidate(){},render(h){try{let c=r.getFooterInput(i);return B(c,u,h)}catch(c){return console.error("[clean-footer] render failed:",c instanceof Error?c.message:c),[]}}}))}function d(i){i.hasUI&&(r.loadedError?i.ui.notify(`Clean footer config error: ${r.loadedError}`,"error"):r.loadedWarnings.length>0?i.ui.notify(`Clean footer config loaded with warnings: ${r.loadedWarnings.join("; ")}`,"warning"):i.ui.notify("Clean footer config loaded","info"))}function f(i){if(!i.hasUI)return;let a=r.loadedPaths.length?r.loadedPaths.join(`
3
+ `):"none",u=r.loadedWarnings.length?r.loadedWarnings.join(`
4
+ `):"none",h=n(i.cwd);i.ui.notify(["Clean footer config",`global: ${t}`,`project: ${h}`,`loaded:
5
5
  ${a}`,r.loadedError?`error: ${r.loadedError}`:"error: none",`warnings:
6
- ${c}`,`preset: ${r.config.preset}`,`resolved: ${JSON.stringify(r.config)}`].join(`
7
- `),"info")}}export{lt as default};
6
+ ${u}`,`preset: ${r.config.preset}`,`resolved: ${JSON.stringify(r.config)}`].join(`
7
+ `),"info")}}export{dt as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neilurk12/pi-clean-footer",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Clean, minimal, and lightweight powerline-style footer extension for pi coding agent.",
5
5
  "type": "module",
6
6
  "keywords": [