@neilurk12/pi-clean-footer 0.2.7 → 0.3.0

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 +4 -4
  2. package/package.json +5 -2
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import T from"path";import de from"os";import Z from"path";import{existsSync as E,readFileSync as M}from"fs";var D=500,j=["model","directory","git","context","tokensFull","tokensNoCache","tokensTotal"],_=["default","minimal","compact","dense","focus","muted"],m=[{minWidth:100,left:["model","directory","git"],right:["context","tokensFull"]},{minWidth:80,left:["model","directory","git"],right:["context","tokensNoCache"]},{minWidth:60,left:["model","directory","git"],right:["context","tokensTotal"]},{minWidth:40,left:["model","directory","git"],right:["context"]},{minWidth:0,left:["model"],right:["context"]}],N=[{minWidth:0,left:["model"],right:["context"]}],A=[{minWidth:80,left:["model","git"],right:["context","tokensTotal"]},{minWidth:0,left:["model"],right:["context"]}],U=[{minWidth:100,left:["model","directory","git"],right:["context","tokensFull"]},{minWidth:60,left:["model","git"],right:["context","tokensNoCache"]},{minWidth:0,left:["model"],right:["context"]}],G=[{minWidth:0,left:["model"],right:["context"]}],B={default:{},minimal:{separator:" \xB7 ",showDirectory:!1,showGit:!1,showTokens:!1,layouts:N},compact:{separator:" \xB7 ",showDirectory:!1,showCacheRead:!1,showCacheWrites:!1,layouts:A},dense:{showCacheRead:!0,showCacheWrites:!0,layouts:U},focus:{showDirectory:!1,showGit:!1,showTokens:!1,layouts:G},muted:{colors:{model:"muted",directory:"dim",git:"muted",gitDirty:"warning",contextNormal:"muted",contextWarning:"warning",contextDanger:"error",tokens:"dim",separator:"dim"}}},c={preset:"default",enabled:!0,showGit:!0,showTokens:!0,showCache:!0,showCacheRead:!0,showCacheWrites:!1,showContext:!0,showDirectory:!0,showEffort:!0,separator:" | ",layouts:m,gitRefreshDebounceMs:D,contextWarningPercent:70,contextDangerPercent:85,modelAliases:{},colors:{model:"accent",directory:"dim",git:"success",gitDirty:"warning",contextNormal:"success",contextWarning:"warning",contextDanger:"error",tokens:"muted",separator:"dim"}};function C(e,t){return O([e,t])}function O(e){let t=[],o={},r;for(let s of e)if(E(s))try{let d=JSON.parse(M(s,"utf8"));o=x(o,d),t.push(s)}catch(d){r=`${s}: ${d instanceof Error?d.message:String(d)}`}let n=H(o);return{config:n.config,loadedPaths:t,warnings:n.warnings,error:r}}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"):_.includes(e)?e:(t.push(`unknown preset '${e}'; using default preset`),"default")}function x(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function H(e){let t=[],o=z(e.preset,t),r=B[o],n=x(r,e),s=q(n.layouts);return{config:{...c,...n,preset:o,separator:typeof n.separator=="string"?n.separator:c.separator,layouts:s.layouts,gitRefreshDebounceMs:V(n.gitRefreshDebounceMs,c.gitRefreshDebounceMs),contextWarningPercent:F(n.contextWarningPercent,c.contextWarningPercent),contextDangerPercent:F(n.contextDangerPercent,c.contextDangerPercent),modelAliases:{...c.modelAliases,...r.modelAliases??{},...e.modelAliases??{}},colors:{...c.colors,...r.colors??{},...e.colors??{}}},loadedPaths:[],warnings:[...t,...s.warnings]}}function q(e){let t=[];if(e===void 0)return{layouts:m,warnings:t};if(!Array.isArray(e))return{layouts:m,warnings:["layouts must be an array; using default layouts"]};let o=e.flatMap((r,n)=>{if(!K(r))return t.push(`layouts[${n}] must be an object; skipping`),[];let s=Q(r.minWidth);if(s===void 0)return t.push(`layouts[${n}].minWidth must be a non-negative number; skipping`),[];let d=b(r.left,`layouts[${n}].left`,t),l=b(r.right,`layouts[${n}].right`,t,new Set(d));return d.length===0&&l.length===0?(t.push(`layouts[${n}] has no visible segments; skipping`),[]):[{minWidth:s,left:d,right:l}]});return o.length===0?(t.push("no valid layouts configured; using default layouts"),{layouts:m,warnings:t}):{layouts:[...o].sort((r,n)=>n.minWidth-r.minWidth),warnings:t}}function b(e,t,o,r=new Set){if(!Array.isArray(e))return o.push(`${t} must be an array; using empty segment list`),[];let n=[];for(let s of e){if(!J(s)){o.push(`${t} contains unknown segment '${String(s)}'; omitting`);continue}if(r.has(s)){o.push(`${t} contains duplicate segment '${s}'; omitting`);continue}r.add(s),n.push(s)}return n}function J(e){return typeof e=="string"&&j.includes(e)}function K(e){return typeof e=="object"&&e!==null}function Q(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function V(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:t}function F(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}import{execFile as X}from"child_process";import{promisify as Y}from"util";var k=Y(X);function P(e){let t={inRepo:!1,dirtyCount:0},o,r=[];e.onChange&&r.push(e.onChange);async function n(){if(!e.enabled){t={inRepo:!1,dirtyCount:0};return}try{let[l,i]=await Promise.all([k("git",["branch","--show-current"],{cwd:e.cwd,timeout:2e3}),k("git",["status","--porcelain"],{cwd:e.cwd,timeout:2e3})]),a=l.stdout.trim()||"detached",g=i.stdout.split(`
2
- `).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:g}}catch{t={inRepo:!1,dirtyCount:0}}for(let l of r)l()}function s(){d(),o=setTimeout(()=>{o=void 0,n()},e.debounceMs)}function d(){o&&(clearTimeout(o),o=void 0)}return{get state(){return t},schedule:s,clear:d,refresh:n,onChange(l){return r.push(l),()=>{let i=r.indexOf(l);i>=0&&r.splice(i,1)}}}}function R(e){var o,r,n,s,d;let t={input:0,output:0,cacheRead:0,cacheWrite:0};for(let l of e){if(l.type!=="message"||((o=l.message)==null?void 0:o.role)!=="assistant")continue;let i=l.message;t.input+=((r=i.usage)==null?void 0:r.input)??0,t.output+=((n=i.usage)==null?void 0:n.output)??0,t.cacheRead+=((s=i.usage)==null?void 0:s.cacheRead)??0,t.cacheWrite+=((d=i.usage)==null?void 0:d.cacheWrite)??0}return t}function y(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}var p=class{#t;#n;#i;#e;#o;#s;#a;#d;#l;#r;constructor(t){this.#a=t.globalConfigPath,this.#d=t.getProjectConfigPath,this.#l=t.getThinkingLevel,this.#r=t.onRenderNeeded,this.#t=c,this.#n={config:this.#t,loadedPaths:[],warnings:[]},this.#i=void 0,this.#e=void 0,this.#o=!0,this.#s=""}async start(t){this.#s=t.cwd,this.#n=C(this.#a,this.#d(t.cwd)),this.#t=this.#n.config,this.#i=y(this.#l()),this.#o=this.#t.enabled,this.#o&&(this.#g(t.cwd),await this.#e.refresh())}shutdown(){var t;(t=this.#e)==null||t.clear(),this.#e=void 0}#g(t){this.#e=P({cwd:t,debounceMs:this.#t.gitRefreshDebounceMs,enabled:this.#t.showGit,onChange:()=>this.#r()})}onThinkingLevel(t){this.#i=y(t),this.#r()}onModelSelect(){this.#r()}onMessageEnd(t){t==="assistant"&&this.#r()}onToolEnd(t){var o;["bash","edit","write"].includes(t)&&((o=this.#e)==null||o.schedule()),this.#r()}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 o;this.#n=C(this.#a,this.#d(t.cwd)),this.#t=this.#n.config,this.#o=this.#t.enabled,(o=this.#e)==null||o.clear(),this.#e=void 0,this.#o&&(this.#g(this.#s),await this.#e.refresh()),this.#r()}async toggle(){var t;return this.#o=!this.#o,this.#o?(this.#i=y(this.#l()),this.#g(this.#s),await this.#e.refresh()):((t=this.#e)==null||t.clear(),this.#e=void 0),this.#r(),this.#o}getFooterInput(t){var o,r,n,s,d,l;return{modelId:((o=t.model)==null?void 0:o.id)??"no-model",thinkingLevel:this.#i,directory:Z.basename(t.cwd),gitBranch:(r=this.#e)==null?void 0:r.state.branch,gitDirtyCount:((n=this.#e)==null?void 0:n.state.dirtyCount)??0,contextUsed:((d=(s=t.getContextUsage)==null?void 0:s.call(t))==null?void 0:d.tokens)??0,contextMax:(l=t.model)==null?void 0:l.contextWindow,totals:R(t.sessionManager.getBranch()),config:this.#t}}get isEnabled(){return this.#o}get loadedError(){return this.#n.error}get loadedWarnings(){return this.#n.warnings}get loadedPaths(){return this.#n.loadedPaths}get config(){return this.#t}};import{truncateToWidth as h,visibleWidth as L}from"@earendil-works/pi-tui";function S(e,t,o,r){let n=e.filter(Boolean).join(o),s=t.filter(Boolean).join(o);return ee(n,s,r)}function ee(e,t,o){if(!t)return h(e,o);if(!e)return h(t,o);let r=o-L(e)-L(t);if(r>=1)return h(e+" ".repeat(r)+t,o);let n=Math.max(1,Math.floor((o-1)/2));return h(e,n)+" "+h(t,o-n-1)}function W(e,t){if(t[e])return t[e];let o=e.toLowerCase(),r=o.includes("/")?o.split("/").pop():o;if(t[r])return t[r];if(r.includes("claude")&&r.includes("sonnet"))return r.includes("4-5")||r.includes("4.5")?"sonnet-4.5":r.includes("4")?"sonnet-4":"sonnet";if(r.includes("claude")&&r.includes("opus"))return"opus";if(r.includes("claude")&&r.includes("haiku"))return"haiku";let n=r.match(/gpt-5(?:[.-][a-z0-9]+)*/);if(n)return n[0];let s=r.match(/gpt-4(?:[.-][a-z0-9]+)*/);if(s)return s[0];let d=r.match(/gemini-[a-z0-9.-]+/);return d?d[0].replace(/-preview.*/,""):r.length>24?`${r.slice(0,21)}\u2026`:r}function I(e,t,o){let r=(d,l)=>t.fg(d,l),n=te(e,r),s=r(e.config.colors.separator,e.config.separator);return[se(n,s,e.config.layouts,o)]}function te(e,t){let o=e.config,r=o.showCache&&o.showCacheRead,n=o.showCache&&o.showCacheWrites;return{model:oe(e,t),directory:o.showDirectory?ne(e,t):void 0,git:o.showGit?re(e,t):void 0,context:o.showContext?ie(e,t):void 0,tokensFull:o.showTokens?w(e.totals,"full",r,n,t,o.colors.tokens):void 0,tokensNoCache:o.showTokens?w(e.totals,"no-cache",r,n,t,o.colors.tokens):void 0,tokensTotal:o.showTokens?w(e.totals,"total-only",r,n,t,o.colors.tokens):void 0}}function f(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 oe(e,t){let o=W(e.modelId,e.config.modelAliases),r=e.config.showEffort&&e.thinkingLevel?` \u2022 ${e.thinkingLevel}`:"";return t(e.config.colors.model,`${o}${r}`)}function ne(e,t){if(e.directory)return t(e.config.colors.directory,e.directory)}function re(e,t){if(!e.gitBranch)return;let o=t(e.config.colors.git,e.gitBranch);return e.gitDirtyCount<=0?o:`${o} ${t(e.config.colors.gitDirty,`\u25CF${e.gitDirtyCount}`)}`}function w(e,t,o,r,n,s){let d=e.input+e.output,l;if(t==="total-only")l=`\u03A3${f(d)}`;else{let i=`\u2191${f(e.input)} \u2193${f(e.output)} \u03A3${f(d)}`;if(t==="full"){let a=[o?`\u21AF${f(e.cacheRead)}`:void 0,r?`\u21A5${f(e.cacheWrite)}`:void 0].filter(Boolean);l=a.length?`${i} ${a.join(" ")}`:i}else l=i}return n(s,l)}function ie(e,t){let o=`ctx ${f(e.contextUsed)}/${e.contextMax?f(e.contextMax):"--"}`;if(!e.contextMax||e.contextMax<=0)return t("dim",o);let r=e.contextUsed/e.contextMax*100;return r>=e.config.contextDangerPercent?t(e.config.colors.contextDanger,o):r>=e.config.contextWarningPercent?t(e.config.colors.contextWarning,o):t(e.config.colors.contextNormal,o)}function se(e,t,o,r){let n=ae(o,r),s=v(n.left,e),d=v(n.right,e);return S(s,d,t,r)}function ae(e,t){return e.find(o=>t>=o.minWidth)??e[e.length-1]}function v(e,t){return e.map(o=>t[o]).filter(o=>!!o)}function $e(e){let t=T.join(de.homedir(),".pi","agent","clean-footer.json"),o=i=>T.join(i,".pi","clean-footer.json"),r=()=>{},n=new p({globalConfigPath:t,getProjectConfigPath:o,getThinkingLevel:()=>{var i;return(i=e.getThinkingLevel)==null?void 0:i.call(e)},onRenderNeeded:()=>r()});e.registerCommand("footer",{description:"Toggle, refresh, or configure the clean footer",handler:async(i,a)=>{let g=i.trim();if(g==="refresh"){await n.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(g==="reload"){await n.reload(a),a.hasUI&&n.isEnabled&&s(a),a.hasUI&&!n.isEnabled&&a.ui.setFooter(void 0),r(),d(a);return}if(g==="config"){l(a);return}let u=await n.toggle();a.hasUI&&(u?(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 n.start(a),a.hasUI&&n.loadedError&&n.isEnabled&&a.ui.notify(`Config error: ${n.loadedError}`,"error"),a.hasUI&&n.isEnabled&&s(a)}),e.on("session_shutdown",(i,a)=>{n.shutdown(),r=()=>{},a.hasUI&&a.ui.setFooter(void 0)}),e.on("thinking_level_select",i=>{n.onThinkingLevel(i.level)}),e.on("model_select",()=>{n.onModelSelect()}),e.on("message_end",i=>{n.onMessageEnd(i.message.role)}),e.on("tool_execution_end",i=>{n.onToolEnd(i.toolName)}),e.on("user_bash",()=>{n.onUserBash()});function s(i){i.hasUI&&i.ui.setFooter((a,g)=>(r=()=>a.requestRender(),{invalidate(){},render(u){let $=n.getFooterInput(i);return I($,g,u)}}))}function d(i){i.hasUI&&(n.loadedError?i.ui.notify(`Clean footer config error: ${n.loadedError}`,"error"):n.loadedWarnings.length>0?i.ui.notify(`Clean footer config loaded with warnings: ${n.loadedWarnings.join("; ")}`,"warning"):i.ui.notify("Clean footer config loaded","info"))}function l(i){if(!i.hasUI)return;let a=n.loadedPaths.length?n.loadedPaths.join(`
1
+ import _ from"path";import ge from"os";import te from"path";import{existsSync as V,readFileSync as X}from"fs";var j=["model","directory","git","context","tokensFull","tokensNoCache","tokensTotal","toks"],N=["default","minimal","compact","dense","focus","muted"],p=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:80,left:["model","directory","git"],right:["context","tokensNoCache"]},{minWidth:60,left:["model","directory","git"],right:["context","tokensTotal"]},{minWidth:40,left:["model","directory","git"],right:["context"]},{minWidth:0,left:["model"],right:["context"]}],A=[{minWidth:0,left:["model"],right:["context"]}],U=[{minWidth:80,left:["model","git"],right:["context","tokensTotal"]},{minWidth:0,left:["model"],right:["context"]}],G=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:60,left:["model","git"],right:["context","tokensNoCache"]},{minWidth:0,left:["model"],right:["context"]}],B=[{minWidth:0,left:["model"],right:["context"]}],O={default:{},minimal:{separator:" \xB7 ",showDirectory:!1,showGit:!1,showTokens:!1,layouts:A},compact:{separator:" \xB7 ",showDirectory:!1,showCacheRead:!1,showCacheWrites:!1,layouts:U},dense:{showCacheRead:!0,showCacheWrites:!0,layouts:G},focus:{showDirectory:!1,showGit:!1,showTokens:!1,layouts:B},muted:{colors:{model:"muted",directory:"dim",git:"muted",gitDirty:"warning",contextNormal:"muted",contextWarning:"warning",contextDanger:"error",tokens:"dim",separator:"dim"}}},f={preset:"default",enabled:!0,showGit:!0,showTokens:!0,showCache:!0,showCacheRead:!0,showCacheWrites:!1,showContext:!0,showDirectory:!0,showEffort:!0,showToks:!0,separator:" | ",layouts:p,gitRefreshDebounceMs:500,contextWarningPercent:70,contextDangerPercent:85,modelAliases:{},colors:{model:"accent",directory:"dim",git:"success",gitDirty:"warning",contextNormal:"success",contextWarning:"warning",contextDanger:"error",tokens:"muted",separator:"dim"}};function b(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function T(e){let t=[],o=z(e.preset,t),r=O[o],n=b(r,e),s=H(n.layouts);return{config:{...f,...n,preset:o,separator:typeof n.separator=="string"?n.separator:f.separator,layouts:s.layouts,gitRefreshDebounceMs:Q(n.gitRefreshDebounceMs,f.gitRefreshDebounceMs),contextWarningPercent:k(n.contextWarningPercent,f.contextWarningPercent),contextDangerPercent:k(n.contextDangerPercent,f.contextDangerPercent),modelAliases:{...f.modelAliases,...r.modelAliases??{},...e.modelAliases??{}},colors:{...f.colors,...r.colors??{},...e.colors??{}}},loadedPaths:[],warnings:[...t,...s.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"):N.includes(e)?e:(t.push(`unknown preset '${e}'; using default preset`),"default")}function H(e){let t=[];if(e===void 0)return{layouts:p,warnings:t};if(!Array.isArray(e))return{layouts:p,warnings:["layouts must be an array; using default layouts"]};let o=e.flatMap((r,n)=>{if(!J(r))return t.push(`layouts[${n}] must be an object; skipping`),[];let s=K(r.minWidth);if(s===void 0)return t.push(`layouts[${n}].minWidth must be a non-negative number; skipping`),[];let d=x(r.left,`layouts[${n}].left`,t),u=x(r.right,`layouts[${n}].right`,t,new Set(d));return d.length===0&&u.length===0?(t.push(`layouts[${n}] has no visible segments; skipping`),[]):[{minWidth:s,left:d,right:u}]});return o.length===0?(t.push("no valid layouts configured; using default layouts"),{layouts:p,warnings:t}):{layouts:[...o].sort((r,n)=>n.minWidth-r.minWidth),warnings:t}}function x(e,t,o,r=new Set){if(!Array.isArray(e))return o.push(`${t} must be an array; using empty segment list`),[];let n=[];for(let s of e){if(!q(s)){o.push(`${t} contains unknown segment '${String(s)}'; omitting`);continue}if(r.has(s)){o.push(`${t} contains duplicate segment '${s}'; omitting`);continue}r.add(s),n.push(s)}return n}function q(e){return typeof e=="string"&&j.includes(e)}function J(e){return typeof e=="object"&&e!==null}function K(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Q(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:t}function k(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}function F(e,t){return Y([e,t])}function Y(e){let t=[],o={},r;for(let s of e)if(V(s))try{let d=JSON.parse(X(s,"utf8"));o=b(o,d),t.push(s)}catch(d){r=`${s}: ${d instanceof Error?d.message:String(d)}`}let n=T(o);return{config:n.config,loadedPaths:t,warnings:n.warnings,error:r}}import{execFile as Z}from"child_process";import{promisify as ee}from"util";var R=ee(Z);function S(e){let t={inRepo:!1,dirtyCount:0},o,r=[];e.onChange&&r.push(e.onChange);async function n(){if(!e.enabled){t={inRepo:!1,dirtyCount:0};return}try{let[u,i]=await Promise.all([R("git",["branch","--show-current"],{cwd:e.cwd,timeout:2e3}),R("git",["status","--porcelain"],{cwd:e.cwd,timeout:2e3})]),a=u.stdout.trim()||"detached",g=i.stdout.split(`
2
+ `).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:g}}catch{t={inRepo:!1,dirtyCount:0}}for(let u of r)u()}function s(){d(),o=setTimeout(()=>{o=void 0,n()},e.debounceMs)}function d(){o&&(clearTimeout(o),o=void 0)}return{get state(){return t},schedule:s,clear:d,refresh:n,onChange(u){return r.push(u),()=>{let i=r.indexOf(u);i>=0&&r.splice(i,1)}}}}function P(e){var o,r,n,s,d;let t={input:0,output:0,cacheRead:0,cacheWrite:0};for(let u of e){if(u.type!=="message"||((o=u.message)==null?void 0:o.role)!=="assistant")continue;let i=u.message;t.input+=((r=i.usage)==null?void 0:r.input)??0,t.output+=((n=i.usage)==null?void 0:n.output)??0,t.cacheRead+=((s=i.usage)==null?void 0:s.cacheRead)??0,t.cacheWrite+=((d=i.usage)==null?void 0:d.cacheWrite)??0}return t}function y(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 c(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 C=class{#t;#n;#d;#e;#o;#c;#g;#f;#l;#r;#s={input:0,output:0,cacheRead:0,cacheWrite:0};#a=0;#i=void 0;#u=void 0;constructor(t){this.#g=t.globalConfigPath,this.#f=t.getProjectConfigPath,this.#l=t.getThinkingLevel,this.#r=t.onRenderNeeded,this.#t=f,this.#n={config:this.#t,loadedPaths:[],warnings:[]},this.#d=void 0,this.#e=void 0,this.#o=!0,this.#c=""}async start(t){this.#s={input:0,output:0,cacheRead:0,cacheWrite:0},this.#a=0,this.#c=t.cwd,this.#n=F(this.#g,this.#f(t.cwd)),this.#t=this.#n.config,this.#d=y(this.#l()),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.#s={input:0,output:0,cacheRead:0,cacheWrite:0},this.#a=0,this.#i=void 0,this.#u=void 0}#h(t){this.#e=S({cwd:t,debounceMs:this.#t.gitRefreshDebounceMs,enabled:this.#t.showGit,onChange:()=>this.#r()})}onThinkingLevel(t){this.#d=y(t),this.#r()}onModelSelect(){this.#r()}onMessageStart(t){t==="assistant"&&(this.#i=Date.now())}onMessageEnd(t,o){if(t==="assistant"){if(this.#i!==void 0&&o&&o>0){let r=Date.now()-this.#i;r>0&&(this.#u=o/(r/1e3))}this.#i=void 0,this.#r()}}onToolEnd(t){var o;["bash","edit","write"].includes(t)&&((o=this.#e)==null||o.schedule()),this.#r()}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 o;this.#s={input:0,output:0,cacheRead:0,cacheWrite:0},this.#a=0,this.#i=void 0,this.#u=void 0,this.#n=F(this.#g,this.#f(t.cwd)),this.#t=this.#n.config,this.#o=this.#t.enabled,(o=this.#e)==null||o.clear(),this.#e=void 0,this.#o&&(this.#h(this.#c),await this.#e.refresh()),this.#r()}async toggle(){var t;return this.#s={input:0,output:0,cacheRead:0,cacheWrite:0},this.#a=0,this.#i=void 0,this.#u=void 0,this.#o=!this.#o,this.#o?(this.#d=y(this.#l()),this.#h(this.#c),await this.#e.refresh()):((t=this.#e)==null||t.clear(),this.#e=void 0),this.#r(),this.#o}getFooterInput(t){var r,n,s,d,u,i;let o=t.sessionManager.getBranch();return o.length!==this.#a&&(this.#s=P(o),this.#a=o.length),{modelId:((r=t.model)==null?void 0:r.id)??"no-model",thinkingLevel:this.#d,directory:te.basename(t.cwd),gitBranch:(n=this.#e)==null?void 0:n.state.branch,gitDirtyCount:((s=this.#e)==null?void 0:s.state.dirtyCount)??0,contextUsed:((u=(d=t.getContextUsage)==null?void 0:d.call(t))==null?void 0:u.tokens)??0,contextMax:(i=t.model)==null?void 0:i.contextWindow,totals:this.#s,lastTokPerSec:this.#u,config:this.#t}}get isEnabled(){return this.#o}get loadedError(){return this.#n.error}get loadedWarnings(){return this.#n.warnings}get loadedPaths(){return this.#n.loadedPaths}get config(){return this.#t}};import{truncateToWidth as h,visibleWidth as W}from"@earendil-works/pi-tui";function L(e,t,o,r){let n=e.filter(Boolean).join(o),s=t.filter(Boolean).join(o);return oe(n,s,r)}function oe(e,t,o){if(!t)return h(e,o);if(!e)return h(t,o);let r=o-W(e)-W(t);if(r>=1)return h(e+" ".repeat(r)+t,o);let n=Math.max(1,Math.floor((o-1)/2));return h(e,n)+" "+h(t,o-n-1)}function v(e,t){if(t[e])return t[e];let o=e.toLowerCase(),r=o.includes("/")?o.split("/").pop():o;if(t[r])return t[r];if(r.includes("claude")&&r.includes("sonnet"))return r.includes("4-5")||r.includes("4.5")?"sonnet-4.5":r.includes("4")?"sonnet-4":"sonnet";if(r.includes("claude")&&r.includes("opus"))return"opus";if(r.includes("claude")&&r.includes("haiku"))return"haiku";let n=r.match(/gpt-5(?:[.-][a-z0-9]+)*/);if(n)return n[0];let s=r.match(/gpt-4(?:[.-][a-z0-9]+)*/);if(s)return s[0];let d=r.match(/gemini-[a-z0-9.-]+/);return d?d[0].replace(/-preview.*/,""):r.length>24?`${r.slice(0,21)}\u2026`:r}function I(e,t){let o=e.input+e.output,r=`\u2191${c(e.input)} \u2193${c(e.output)} \u03A3${c(o)}`,n=[t.showCacheRead?`\u21AF${c(e.cacheRead)}`:void 0,t.showCacheWrites?`\u21A5${c(e.cacheWrite)}`:void 0].filter(Boolean),s=n.length?`${r} ${n.join(" ")}`:r;return t.cf(t.color,s)}function $(e,t,o){let r=e.input+e.output,n=`\u2191${c(e.input)} \u2193${c(e.output)} \u03A3${c(r)}`;return t(o,n)}function M(e,t,o){let r=e.input+e.output;return t(o,`\u03A3${c(r)}`)}function D(e,t,o){let r=(d,u)=>t.fg(d,u),n=ne(e,r),s=r(e.config.colors.separator,e.config.separator);return[ue(n,s,e.config.layouts,o)]}function ne(e,t){let o=e.config,r=o.showCache&&o.showCacheRead,n=o.showCache&&o.showCacheWrites;return{model:re(e,t),directory:o.showDirectory?ie(e,t):void 0,git:o.showGit?se(e,t):void 0,context:o.showContext?ae(e,t):void 0,tokensFull:o.showTokens?I(e.totals,{showCacheRead:r,showCacheWrites:n,cf:t,color:o.colors.tokens}):void 0,tokensNoCache:o.showTokens?$(e.totals,t,o.colors.tokens):void 0,tokensTotal:o.showTokens?M(e.totals,t,o.colors.tokens):void 0,toks:o.showToks?de(e,t):void 0}}function re(e,t){let o=v(e.modelId,e.config.modelAliases),r=e.config.showEffort&&e.thinkingLevel?` \u2022 ${e.thinkingLevel}`:"";return t(e.config.colors.model,`${o}${r}`)}function ie(e,t){if(e.directory)return t(e.config.colors.directory,e.directory)}function se(e,t){if(!e.gitBranch)return;let o=t(e.config.colors.git,e.gitBranch);return e.gitDirtyCount<=0?o:`${o} ${t(e.config.colors.gitDirty,`\u25CF${e.gitDirtyCount}`)}`}function ae(e,t){let o=`ctx ${c(e.contextUsed)}/${e.contextMax?c(e.contextMax):"--"}`;if(!e.contextMax||e.contextMax<=0)return t("dim",o);let r=e.contextUsed/e.contextMax*100;return r>=e.config.contextDangerPercent?t(e.config.colors.contextDanger,o):r>=e.config.contextWarningPercent?t(e.config.colors.contextWarning,o):t(e.config.colors.contextNormal,o)}function de(e,t){if(!(e.lastTokPerSec===void 0||e.lastTokPerSec<=0))return t(e.config.colors.tokens,`${Math.round(e.lastTokPerSec)} tok/s`)}function ue(e,t,o,r){let n=ce(o,r),s=E(n.left,e),d=E(n.right,e);return L(s,d,t,r)}function ce(e,t){return e.find(o=>t>=o.minWidth)??e[e.length-1]}function E(e,t){return e.map(o=>t[o]).filter(o=>!!o)}function Be(e){let t=_.join(ge.homedir(),".pi","agent","clean-footer.json"),o=i=>_.join(i,".pi","clean-footer.json"),r=()=>{},n=new C({globalConfigPath:t,getProjectConfigPath:o,getThinkingLevel:()=>{var i;return(i=e.getThinkingLevel)==null?void 0:i.call(e)},onRenderNeeded:()=>r()});e.registerCommand("footer",{description:"Toggle, refresh, or configure the clean footer",handler:async(i,a)=>{let g=i.trim();if(g==="refresh"){await n.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(g==="reload"){await n.reload(a),a.hasUI&&n.isEnabled&&s(a),a.hasUI&&!n.isEnabled&&a.ui.setFooter(void 0),r(),d(a);return}if(g==="config"){u(a);return}let l=await n.toggle();a.hasUI&&(l?(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 n.start(a),a.hasUI&&n.loadedError&&n.isEnabled&&a.ui.notify(`Config error: ${n.loadedError}`,"error"),a.hasUI&&n.isEnabled&&s(a)}),e.on("session_shutdown",(i,a)=>{n.shutdown(),r=()=>{},a.hasUI&&a.ui.setFooter(void 0)}),e.on("thinking_level_select",i=>{n.onThinkingLevel(i.level)}),e.on("model_select",()=>{n.onModelSelect()}),e.on("message_start",i=>{n.onMessageStart(i.message.role)}),e.on("message_end",i=>{var l;let a=i.message,g;if(a.role==="assistant"){let m=a,w=m.usage??((l=m.message)==null?void 0:l.usage);g=w==null?void 0:w.output}n.onMessageEnd(a.role,g)}),e.on("tool_execution_end",i=>{n.onToolEnd(i.toolName)}),e.on("user_bash",()=>{n.onUserBash()});function s(i){i.hasUI&&i.ui.setFooter((a,g)=>(r=()=>a.requestRender(),{invalidate(){},render(l){let m=n.getFooterInput(i);return D(m,g,l)}}))}function d(i){i.hasUI&&(n.loadedError?i.ui.notify(`Clean footer config error: ${n.loadedError}`,"error"):n.loadedWarnings.length>0?i.ui.notify(`Clean footer config loaded with warnings: ${n.loadedWarnings.join("; ")}`,"warning"):i.ui.notify("Clean footer config loaded","info"))}function u(i){if(!i.hasUI)return;let a=n.loadedPaths.length?n.loadedPaths.join(`
3
3
  `):"none",g=n.loadedWarnings.length?n.loadedWarnings.join(`
4
- `):"none",u=o(i.cwd);i.ui.notify(["Clean footer config",`global: ${t}`,`project: ${u}`,`loaded:
4
+ `):"none",l=o(i.cwd);i.ui.notify(["Clean footer config",`global: ${t}`,`project: ${l}`,`loaded:
5
5
  ${a}`,n.loadedError?`error: ${n.loadedError}`:"error: none",`warnings:
6
6
  ${g}`,`preset: ${n.config.preset}`,`resolved: ${JSON.stringify(n.config)}`].join(`
7
- `),"info")}}export{$e as default};
7
+ `),"info")}}export{Be as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neilurk12/pi-clean-footer",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
4
4
  "description": "Clean, minimal, and lightweight powerline-style footer extension for pi coding agent.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -33,7 +33,9 @@
33
33
  "build": "tsup",
34
34
  "dev": "tsup --watch",
35
35
  "test": "vitest run",
36
- "test:watch": "vitest"
36
+ "test:watch": "vitest",
37
+ "format": "prettier --write \"src/**/*.ts\"",
38
+ "format:check": "prettier --check \"src/**/*.ts\""
37
39
  },
38
40
  "peerDependencies": {
39
41
  "@earendil-works/pi-ai": "*",
@@ -41,6 +43,7 @@
41
43
  "@earendil-works/pi-tui": "*"
42
44
  },
43
45
  "devDependencies": {
46
+ "prettier": "^3.8.3",
44
47
  "tsup": "^8.5.1",
45
48
  "typescript": "^6.0.3",
46
49
  "vitest": "^4.1.6"