@neilurk12/pi-clean-footer 0.3.1 → 0.4.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.
package/README.md CHANGED
@@ -14,6 +14,7 @@ Shows a compact split footer:
14
14
  - Event-driven git refresh after file-changing tools and user bash commands
15
15
  - Context usage as `used/max`
16
16
  - Cumulative active-branch token totals: input, output, total, cache read, cache write
17
+ - Optional session cost display (`$x.xx`) using provider cost data; auto-hides for zero-cost models
17
18
  - Adaptive width tiers for narrow terminals
18
19
  - `/footer` toggle
19
20
  - `/footer refresh` force refresh
@@ -83,24 +84,34 @@ Example:
83
84
  "enabled": true,
84
85
  "showGit": true,
85
86
  "showTokens": true,
86
- "showCache": true,
87
87
  "showCacheRead": true,
88
- "showCacheWrites": true,
88
+ "showCacheWrites": false,
89
89
  "showContext": true,
90
90
  "showDirectory": true,
91
91
  "showEffort": true,
92
+ "showCost": true,
92
93
  "gitRefreshDebounceMs": 500,
93
- "separator": " ",
94
+ "separator": " | ",
94
95
  "layouts": [
95
96
  {
96
97
  "minWidth": 100,
97
- "left": ["model", "directory", "git"],
98
- "right": ["context", "tokensFull"]
98
+ "left": ["model", "directory", "git", "toks"],
99
+ "right": ["cost", "context", "tokensFull"]
100
+ },
101
+ {
102
+ "minWidth": 80,
103
+ "left": ["model", "directory", "git", "toks"],
104
+ "right": ["cost", "context", "tokensNoCache"]
99
105
  },
100
106
  {
101
107
  "minWidth": 60,
102
- "left": ["model", "git"],
103
- "right": ["context", "tokensTotal"]
108
+ "left": ["model", "directory", "git", "toks"],
109
+ "right": ["cost", "context", "tokensTotal"]
110
+ },
111
+ {
112
+ "minWidth": 40,
113
+ "left": ["model", "directory", "git"],
114
+ "right": ["cost", "context"]
104
115
  },
105
116
  {
106
117
  "minWidth": 0,
@@ -123,6 +134,7 @@ Example:
123
134
  "contextWarning": "warning",
124
135
  "contextDanger": "error",
125
136
  "tokens": "muted",
137
+ "cost": "muted",
126
138
  "separator": "dim"
127
139
  }
128
140
  }
@@ -159,6 +171,8 @@ Supported layout segment IDs:
159
171
  - `tokensFull` - input, output, total, cache read, and cache write tokens
160
172
  - `tokensNoCache` - input, output, and total tokens
161
173
  - `tokensTotal` - total tokens only
174
+ - `toks` - tokens-per-second rate or activity indicator
175
+ - `cost` - cumulative session cost in `$x.xx` format
162
176
 
163
177
  `layouts` are selected by the highest `minWidth` less than or equal to the terminal width. `showGit`, `showTokens`, `showContext`, `showDirectory`, and `showEffort` still act as global visibility controls. `showCache` is a deprecated global cache-token gate; use `showCacheRead` and `showCacheWrites` to hide cache read (`↯`) and write (`↥`) counts independently. Unknown or duplicate layout segments are omitted and reported by `/footer config`.
164
178
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import N from"path";import Se from"os";import se from"path";import{existsSync as Z,readFileSync as ee}from"fs";var j=["model","directory","git","context","tokensFull","tokensNoCache","tokensTotal","toks"],U=["default","minimal","compact","dense","focus","muted"],m=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:80,left:["model","directory","git","toks"],right:["context","tokensNoCache"]},{minWidth:60,left:["model","directory","git","toks"],right:["context","tokensTotal"]},{minWidth:40,left:["model","directory","git"],right:["context"]},{minWidth:0,left:["model"],right:["context"]}],G=[{minWidth:0,left:["model"],right:["context"]}],B=[{minWidth:80,left:["model","git"],right:["context","tokensTotal"]},{minWidth:0,left:["model"],right:["context"]}],H=[{minWidth:100,left:["model","directory","git","toks"],right:["context","tokensFull"]},{minWidth:60,left:["model","git"],right:["context","tokensNoCache"]},{minWidth:0,left:["model"],right:["context"]}],z=[{minWidth:0,left:["model"],right:["context"]}],K={default:{},minimal:{separator:" \xB7 ",showDirectory:!1,showGit:!1,showTokens:!1,layouts:G},compact:{separator:" \xB7 ",showDirectory:!1,showCacheRead:!1,showCacheWrites:!1,layouts:B},dense:{showCacheRead:!0,showCacheWrites:!0,layouts:H},focus:{showDirectory:!1,showGit:!1,showTokens:!1,layouts:z},muted:{colors:{model:"muted",directory:"dim",git:"muted",gitDirty:"warning",contextNormal:"muted",contextWarning:"warning",contextDanger:"error",tokens:"dim",separator:"dim"}}},l={preset:"default",enabled:!0,showGit:!0,showTokens:!0,showCache:!0,showCacheRead:!0,showCacheWrites:!1,showContext:!0,showDirectory:!0,showEffort:!0,separator:" | ",layouts:m,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 C(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function F(e){let t=[],n=J(e.preset,t),o=K[n],r=C(o,e),s=q(r.layouts);return{config:{...l,...r,preset:n,separator:typeof r.separator=="string"?r.separator:l.separator,layouts:s.layouts,gitRefreshDebounceMs:Q(r.gitRefreshDebounceMs,l.gitRefreshDebounceMs),contextWarningPercent:T(r.contextWarningPercent,l.contextWarningPercent),contextDangerPercent:T(r.contextDangerPercent,l.contextDangerPercent),modelAliases:{...l.modelAliases,...o.modelAliases??{},...e.modelAliases??{}},colors:{...l.colors,...o.colors??{},...e.colors??{}}},loadedPaths:[],warnings:[...t,...s.warnings]}}function J(e,t){return e===void 0||e==="default"?"default":typeof e!="string"?(t.push("preset must be a string; using default preset"),"default"):U.includes(e)?e:(t.push(`unknown preset '${e}'; using default preset`),"default")}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 n=e.flatMap((o,r)=>{if(!X(o))return t.push(`layouts[${r}] must be an object; skipping`),[];let s=Y(o.minWidth);if(s===void 0)return t.push(`layouts[${r}].minWidth must be a non-negative number; skipping`),[];let d=w(o.left,`layouts[${r}].left`,t),u=w(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:s,left:d,right:u}]});return n.length===0?(t.push("no valid layouts configured; using default layouts"),{layouts:m,warnings:t}):{layouts:[...n].sort((o,r)=>r.minWidth-o.minWidth),warnings:t}}function w(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(!V(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 V(e){return typeof e=="string"&&j.includes(e)}function X(e){return typeof e=="object"&&e!==null}function Y(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 T(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}function x(e,t){return te([e,t])}function te(e){let t=[],n={},o;for(let s of e)if(Z(s))try{let d=JSON.parse(ee(s,"utf8"));n=C(n,d),t.push(s)}catch(d){o=`${s}: ${d instanceof Error?d.message:String(d)}`}let r=F(n);return{config:r.config,loadedPaths:t,warnings:r.warnings,error:o}}import{execFile as oe}from"child_process";import{promisify as ne}from"util";var k=ne(oe);function S(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,i]=await Promise.all([k("git",["branch","--show-current"],{cwd:e.cwd,timeout:2e3}),k("git",["status","--porcelain"],{cwd:e.cwd,timeout:2e3})]),a=u.stdout.trim()||"detached",f=i.stdout.split(`
2
- `).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:f}}catch{t={inRepo:!1,dirtyCount:0}}for(let u of o)u()}function s(){d(),n=setTimeout(()=>{n=void 0,r()},e.debounceMs)}function d(){n&&(clearTimeout(n),n=void 0)}return{get state(){return t},schedule:s,clear:d,refresh:r,onChange(u){return o.push(u),()=>{let i=o.indexOf(u);i>=0&&o.splice(i,1)}}}}function v(e){var n,o,r,s,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 i=u.message;t.input+=((o=i.usage)==null?void 0:o.input)??0,t.output+=((r=i.usage)==null?void 0:r.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 p(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 re={edit:"edit",write:"write",bash:"bash",ctx_shell:"bash",read:"read",ctx_read:"read",Agent:"agent",agent_browser:"browser"},ie=[["gitnexus_","nexus"],["context7_","docs"]],R=8;function _(e){if(!e)return"";let t=re[e];if(t)return t;for(let[n,o]of ie)if(e.startsWith(n))return o;return e.length>R?e.slice(0,R):e}var ae=.25,de=.67,ue=.5,fe=1,ce=.5,le=300,ge=5e3,he=[". ",".. ","..."];function me(e){let t=0;for(let n of e){let o=n.codePointAt(0)??0;o>=32&&o<=126?t+=ae: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<=12590||o>=12784&&o<=12799||o>=65281&&o<=65374||o>=65381&&o<=65439?t+=de:o>=12288&&o<=12351?t+=ue:o>65535?t+=fe:t+=ce}return Math.ceil(t)}var y=class{#n;#i;#a;#t;#r;#u;#m;#p;#y;#o;#f={input:0,output:0,cacheRead:0,cacheWrite:0};#c=0;#e=void 0;#s=0;#C="";#l=0;#g=void 0;#d=void 0;constructor(t){this.#m=t.globalConfigPath,this.#p=t.getProjectConfigPath,this.#y=t.getThinkingLevel,this.#o=t.onRenderNeeded,this.#n=l,this.#i={config:this.#n,loadedPaths:[],warnings:[]},this.#a=void 0,this.#t=void 0,this.#r=!0,this.#u=""}async start(t){this.#f={input:0,output:0,cacheRead:0,cacheWrite:0},this.#c=0,this.#u=t.cwd,this.#i=x(this.#m,this.#p(t.cwd)),this.#n=this.#i.config,this.#a=p(this.#y()),this.#r=this.#n.enabled,this.#r&&(this.#x(t.cwd),await this.#t.refresh())}shutdown(){var t;(t=this.#t)==null||t.clear(),this.#t=void 0,this.#b()}#x(t){this.#t=S({cwd:t,debounceMs:this.#n.gitRefreshDebounceMs,enabled:this.#n.showGit,onChange:()=>this.#o()})}onThinkingLevel(t){this.#a=p(t),this.#o()}onModelSelect(){this.#o()}onMessageStart(t){t==="assistant"&&(this.#w(),this.#e={startTime:Date.now(),estimatedTokens:0,hasObservedOutput:!1,displayState:{state:"pending"}},this.#o())}onToolExecutionStart(t){this.#s++,this.#C=_(t)+"...",this.#l=0,this.#F(),this.#o()}onToolExecutionUpdate(t){}onToolExecutionEnd(t){var n;this.#s=Math.max(0,this.#s-1),this.#s===0&&this.#h(),["bash","edit","write"].includes(t)&&((n=this.#t)==null||n.schedule()),this.#o()}onMessageUpdate(t,n,o){if(!this.#e||!n||t!=="text_delta"&&t!=="thinking_delta"&&t!=="toolcall_delta")return;this.#e.estimatedTokens+=me(n),this.#e.hasObservedOutput=!0;let r=(Date.now()-this.#e.startTime)/1e3;if(r>0){let s=o&&o>0?o:this.#e.estimatedTokens;this.#e.displayState={state:"rate",value:s/r,approximate:!(o&&o>0)}}this.#o()}onMessageEnd(t,n){if(t==="assistant"){if(this.#s=0,this.#h(),this.#e){let o=(Date.now()-this.#e.startTime)/1e3;n&&n>0&&o>0?(this.#e.displayState={state:"rate",value:n/o,approximate:!1},this.#T()):this.#e.hasObservedOutput&&o>0?(this.#e.displayState={state:"rate",value:this.#e.estimatedTokens/o,approximate:!0},this.#T()):this.#e=void 0}this.#o()}}onMessageAbort(){if(this.#e)if(this.#e.hasObservedOutput){let t=(Date.now()-this.#e.startTime)/1e3;t>0&&(this.#e.displayState={state:"rate",value:this.#e.estimatedTokens/t,approximate:!0})}else this.#e=void 0;this.#o()}#b(){this.#f={input:0,output:0,cacheRead:0,cacheWrite:0},this.#c=0,this.#e=void 0,this.#s=0,this.#C="",this.#l=0,this.#h(),this.#w()}#F(){this.#h(),this.#g=setInterval(()=>{this.#l=(this.#l+1)%he.length,this.#o()},le)}#h(){this.#g&&(clearInterval(this.#g),this.#g=void 0)}#T(){this.#w(),this.#d=setTimeout(()=>{this.#d=void 0,this.#e&&(this.#e=void 0,this.#o())},ge)}#w(){this.#d&&(clearTimeout(this.#d),this.#d=void 0)}onUserBash(){var t;(t=this.#t)==null||t.schedule()}async refresh(){var t;await((t=this.#t)==null?void 0:t.refresh())}async reload(t){var n;this.#b(),this.#i=x(this.#m,this.#p(t.cwd)),this.#n=this.#i.config,this.#r=this.#n.enabled,(n=this.#t)==null||n.clear(),this.#t=void 0,this.#r&&(this.#x(this.#u),await this.#t.refresh()),this.#o()}async toggle(){var t;return this.#b(),this.#r=!this.#r,this.#r?(this.#a=p(this.#y()),this.#x(this.#u),await this.#t.refresh()):((t=this.#t)==null||t.clear(),this.#t=void 0),this.#o(),this.#r}getFooterInput(t){var o,r,s,d,u,i;let n=t.sessionManager.getBranch();return n.length!==this.#c&&(this.#f=v(n),this.#c=n.length),{modelId:((o=t.model)==null?void 0:o.id)??"no-model",thinkingLevel:this.#a,directory:se.basename(t.cwd),gitBranch:(r=this.#t)==null?void 0:r.state.branch,gitDirtyCount:((s=this.#t)==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.#f,toksState:this.#k(),config:this.#n}}#k(){var t;return this.#s>0?{state:"activity",label:this.#C}:((t=this.#e)==null?void 0:t.displayState)??{state:"hidden"}}get isEnabled(){return this.#r}get loadedError(){return this.#i.error}get loadedWarnings(){return this.#i.warnings}get loadedPaths(){return this.#i.loadedPaths}get config(){return this.#n}};import{truncateToWidth as h,visibleWidth as E}from"@earendil-works/pi-tui";function I(e,t,n,o){let r=e.filter(Boolean).join(n),s=t.filter(Boolean).join(n);return pe(r,s,o)}function pe(e,t,n){if(!t)return h(e,n);if(!e)return h(t,n);let o=n-E(e)-E(t);if(o>=1)return h(e+" ".repeat(o)+t,n);let r=Math.max(1,Math.floor((n-1)/2));return h(e,r)+" "+h(t,n-r-1)}function L(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 P(e,t){let n=e.input+e.output,o=`\u2191${c(e.input)} \u2193${c(e.output)} \u03A3${c(n)}`,r=[t.showCacheRead?`\u21AF${c(e.cacheRead)}`:void 0,t.showCacheWrites?`\u21A5${c(e.cacheWrite)}`:void 0].filter(Boolean),s=r.length?`${o} ${r.join(" ")}`:o;return t.cf(t.color,s)}function W(e,t,n){let o=e.input+e.output,r=`\u2191${c(e.input)} \u2193${c(e.output)} \u03A3${c(o)}`;return t(n,r)}function M(e,t,n){let o=e.input+e.output;return t(n,`\u03A3${c(o)}`)}function D(e,t,n){let o=(d,u)=>t.fg(d,u),r=ye(e,o),s=o(e.config.colors.separator,e.config.separator);return[Fe(r,s,e.config.layouts,n)]}function ye(e,t){let n=e.config,o=n.showCache&&n.showCacheRead,r=n.showCache&&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?we(e,t):void 0,tokensFull:n.showTokens?P(e.totals,{showCacheRead:o,showCacheWrites:r,cf:t,color:n.colors.tokens}):void 0,tokensNoCache:n.showTokens?W(e.totals,t,n.colors.tokens):void 0,tokensTotal:n.showTokens?M(e.totals,t,n.colors.tokens):void 0,toks:Te(e,t)}}function Ce(e,t){let n=L(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 we(e,t){let n=`ctx ${c(e.contextUsed)}/${e.contextMax?c(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 Te(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,n,o){let r=ke(n,o),s=$(r.left,e),d=$(r.right,e);return I(s,d,t,o)}function ke(e,t){return e.find(n=>t>=n.minWidth)??e[e.length-1]}function $(e,t){return e.map(n=>t[n]).filter(n=>!!n)}function A(e){return e!==null&&typeof e=="object"&&"usage"in e&&e.usage!==null&&typeof e.usage=="object"}function b(e){if(e===null||typeof e!="object")return;let t=e,n=A(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"&&A(o)){let r=o.usage.output;if(typeof r=="number"&&Number.isFinite(r)&&r>0)return r}}function st(e){let t=N.join(Se.homedir(),".pi","agent","clean-footer.json"),n=i=>N.join(i,".pi","clean-footer.json"),o=()=>{},r=new y({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 f=i.trim();if(f==="refresh"){await r.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(f==="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(f==="config"){u(a);return}let g=await r.toggle();a.hasUI&&(g?(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,f=a.role==="assistant"?b(a):void 0;r.onMessageEnd(a.role,f)}),e.on("message_update",i=>{let a=i.assistantMessageEvent;if(i.message.role==="assistant"){let f="delta"in a?a.delta:void 0,g=b(i.message);r.onMessageUpdate(a.type,f,g)}}),e.on("tool_execution_start",i=>{r.onToolExecutionStart(i.toolName)}),e.on("tool_execution_update",i=>{r.onToolExecutionUpdate(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,f)=>(o=()=>a.requestRender(),{invalidate(){},render(g){let O=r.getFooterInput(i);return D(O,f,g)}}))}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 u(i){if(!i.hasUI)return;let a=r.loadedPaths.length?r.loadedPaths.join(`
3
- `):"none",f=r.loadedWarnings.length?r.loadedWarnings.join(`
4
- `):"none",g=n(i.cwd);i.ui.notify(["Clean footer config",`global: ${t}`,`project: ${g}`,`loaded:
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:
5
5
  ${a}`,r.loadedError?`error: ${r.loadedError}`:"error: none",`warnings:
6
- ${f}`,`preset: ${r.config.preset}`,`resolved: ${JSON.stringify(r.config)}`].join(`
7
- `),"info")}}export{st as default};
6
+ ${c}`,`preset: ${r.config.preset}`,`resolved: ${JSON.stringify(r.config)}`].join(`
7
+ `),"info")}}export{lt as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neilurk12/pi-clean-footer",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Clean, minimal, and lightweight powerline-style footer extension for pi coding agent.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -42,6 +42,9 @@
42
42
  "@earendil-works/pi-coding-agent": "*",
43
43
  "@earendil-works/pi-tui": "*"
44
44
  },
45
+ "engines": {
46
+ "node": ">=18"
47
+ },
45
48
  "devDependencies": {
46
49
  "prettier": "^3.8.3",
47
50
  "tsup": "^8.5.1",