@neilurk12/pi-clean-footer 0.2.2 → 0.2.5
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 +2 -2
- package/dist/index.js +4 -4
- package/package.json +6 -3
- package/example.png +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Clean, minimal, and lightweight powerline-style footer extension for [pi](https:
|
|
|
4
4
|
|
|
5
5
|
Shows a compact split footer:
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@ Shows a compact split footer:
|
|
|
20
20
|
|
|
21
21
|
## Install
|
|
22
22
|
|
|
23
|
-
From npm (recommended):
|
|
23
|
+
From npm (recommended) | https://www.npmjs.com/package/@neilurk12/pi-clean-footer:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
pi install @neilurk12/pi-clean-footer
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
`).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:
|
|
3
|
-
`):"none",
|
|
4
|
-
${a}`,
|
|
1
|
+
import T from"path";import H from"os";import N from"path";import{existsSync as M,readFileSync as $}from"fs";var D=500,f={enabled:!0,showGit:!0,showTokens:!0,showCache:!0,showContext:!0,showDirectory:!0,showEffort:!0,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 p(e,t){return S([e,t])}function S(e){let t=[],o={},n;for(let r of e)if(M(r))try{let s=JSON.parse($(r,"utf8"));o=I(o,s),t.push(r)}catch(s){n=`${r}: ${s instanceof Error?s.message:String(s)}`}return{config:_(o),loadedPaths:t,error:n}}function I(e,t){return{...e,...t,modelAliases:{...e.modelAliases??{},...t.modelAliases??{}},colors:{...e.colors??{},...t.colors??{}}}}function _(e){return{...f,...e,gitRefreshDebounceMs:L(e.gitRefreshDebounceMs,f.gitRefreshDebounceMs),contextWarningPercent:x(e.contextWarningPercent,f.contextWarningPercent),contextDangerPercent:x(e.contextDangerPercent,f.contextDangerPercent),modelAliases:{...f.modelAliases,...e.modelAliases??{}},colors:{...f.colors,...e.colors??{}}}}function L(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:t}function x(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0&&e<=100?e:t}import{execFile as j}from"child_process";import{promisify as A}from"util";var w=A(j);function F(e){let t={inRepo:!1,dirtyCount:0},o,n=[];e.onChange&&n.push(e.onChange);async function r(){if(!e.enabled){t={inRepo:!1,dirtyCount:0};return}try{let[l,i]=await Promise.all([w("git",["branch","--show-current"],{cwd:e.cwd,timeout:2e3}),w("git",["status","--porcelain"],{cwd:e.cwd,timeout:2e3})]),a=l.stdout.trim()||"detached",d=i.stdout.split(`
|
|
2
|
+
`).filter(Boolean).length;t={inRepo:!0,branch:a,dirtyCount:d}}catch{t={inRepo:!1,dirtyCount:0}}for(let l of n)l()}function s(){c(),o=setTimeout(()=>{o=void 0,r()},e.debounceMs)}function c(){o&&(clearTimeout(o),o=void 0)}return{get state(){return t},schedule:s,clear:c,refresh:r,onChange(l){return n.push(l),()=>{let i=n.indexOf(l);i>=0&&n.splice(i,1)}}}}function P(e){var o,n,r,s,c;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+=((n=i.usage)==null?void 0:n.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+=((c=i.usage)==null?void 0:c.cacheWrite)??0}return t}function m(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 C=class{#t;#r;#i;#e;#o;#s;#a;#l;#c;#n;constructor(t){this.#a=t.globalConfigPath,this.#l=t.getProjectConfigPath,this.#c=t.getThinkingLevel,this.#n=t.onRenderNeeded,this.#t=f,this.#r={config:this.#t,loadedPaths:[]},this.#i=void 0,this.#e=void 0,this.#o=!0,this.#s=""}async start(t){this.#s=t.cwd,this.#r=p(this.#a,this.#l(t.cwd)),this.#t=this.#r.config,this.#i=m(this.#c()),this.#o=this.#t.enabled,this.#o&&(this.#d(t.cwd),await this.#e.refresh())}shutdown(){var t;(t=this.#e)==null||t.clear(),this.#e=void 0}#d(t){this.#e=F({cwd:t,debounceMs:this.#t.gitRefreshDebounceMs,enabled:this.#t.showGit,onChange:()=>this.#n()})}onThinkingLevel(t){this.#i=m(t),this.#n()}onModelSelect(){this.#n()}onMessageEnd(t){t==="assistant"&&this.#n()}onToolEnd(t){var o;["bash","edit","write"].includes(t)&&((o=this.#e)==null||o.schedule()),this.#n()}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.#r=p(this.#a,this.#l(t.cwd)),this.#t=this.#r.config,this.#o=this.#t.enabled,(o=this.#e)==null||o.clear(),this.#e=void 0,this.#o&&(this.#d(this.#s),await this.#e.refresh()),this.#n()}async toggle(){var t;return this.#o=!this.#o,this.#o?(this.#i=m(this.#c()),this.#d(this.#s),await this.#e.refresh()):((t=this.#e)==null||t.clear(),this.#e=void 0),this.#n(),this.#o}getFooterInput(t){var o,n,r,s,c,l;return{modelId:((o=t.model)==null?void 0:o.id)??"no-model",thinkingLevel:this.#i,directory:N.basename(t.cwd),gitBranch:(n=this.#e)==null?void 0:n.state.branch,gitDirtyCount:((r=this.#e)==null?void 0:r.state.dirtyCount)??0,contextUsed:((c=(s=t.getContextUsage)==null?void 0:s.call(t))==null?void 0:c.tokens)??0,contextMax:(l=t.model)==null?void 0:l.contextWindow,totals:P(t.sessionManager.getBranch()),config:this.#t}}get isEnabled(){return this.#o}get loadedError(){return this.#r.error}get loadedPaths(){return this.#r.loadedPaths}get config(){return this.#t}};import{truncateToWidth as u,visibleWidth as k}from"@earendil-works/pi-tui";function R(e,t){if(t[e])return t[e];let o=e.toLowerCase(),n=o.includes("/")?o.split("/").pop():o;if(t[n])return t[n];if(n.includes("claude")&&n.includes("sonnet"))return n.includes("4-5")||n.includes("4.5")?"sonnet-4.5":n.includes("4")?"sonnet-4":"sonnet";if(n.includes("claude")&&n.includes("opus"))return"opus";if(n.includes("claude")&&n.includes("haiku"))return"haiku";let r=n.match(/gpt-5(?:[.-][a-z0-9]+)*/);if(r)return r[0];let s=n.match(/gpt-4(?:[.-][a-z0-9]+)*/);if(s)return s[0];let c=n.match(/gemini-[a-z0-9.-]+/);return c?c[0].replace(/-preview.*/,""):n.length>24?`${n.slice(0,21)}\u2026`:n}function v(e,t,o){let n=(c,l)=>t.fg(c,l),r=U(e,n),s=n(e.config.colors.separator," | ");return z(r,s,o)}function U(e,t){let o=e.config,n=W(e,t),r=o.showDirectory?G(e,t):void 0,s=o.showGit?B(e,t):void 0,c=o.showContext?O(e,t):void 0,l={};return o.showTokens&&(l.full=b(e.totals,"full",o.showCache,t,o.colors.tokens),l.noCache=b(e.totals,"no-cache",o.showCache,t,o.colors.tokens),l.totalOnly=b(e.totals,"total-only",o.showCache,t,o.colors.tokens)),{model:n,dir:r,git:s,context:c,tokens:l}}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 W(e,t){let o=R(e.modelId,e.config.modelAliases),n=e.config.showEffort&&e.thinkingLevel?` \u2022 ${e.thinkingLevel}`:"";return t(e.config.colors.model,`${o}${n}`)}function G(e,t){if(e.directory)return t(e.config.colors.directory,e.directory)}function B(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 b(e,t,o,n,r){let s=o?t:t==="full"?"no-cache":t,c=e.input+e.output,l;if(s==="total-only")l=`\u03A3${g(c)}`;else{let i=`\u2191${g(e.input)} \u2193${g(e.output)} \u03A3${g(c)}`;l=s==="full"?`${i} \u21AF${g(e.cacheRead)} \u21A5${g(e.cacheWrite)}`:i}return n(r,l)}function O(e,t){let o=`ctx ${g(e.contextUsed)}/${e.contextMax?g(e.contextMax):"--"}`;if(!e.contextMax||e.contextMax<=0)return t("dim",o);let n=e.contextUsed/e.contextMax*100;return n>=e.config.contextDangerPercent?t(e.config.colors.contextDanger,o):n>=e.config.contextWarningPercent?t(e.config.colors.contextWarning,o):t(e.config.colors.contextNormal,o)}function z(e,t,o){let n=[e.model,e.dir,e.git].filter(Boolean).join(t),r=e.model;if(o>=100){let s=[e.context,e.tokens.full].filter(Boolean).join(t);return[h(n,s,o)]}if(o>=80){let s=[e.context,e.tokens.noCache].filter(Boolean).join(t);return[h(n,s,o)]}if(o>=60){let s=[e.context,e.tokens.totalOnly].filter(Boolean).join(t);return[h(n,s,o)]}return o>=40?[h(n,e.context??"",o)]:[h(r,e.context??"",o)]}function h(e,t,o){if(!t)return u(e,o);if(!e)return u(t,o);let n=o-k(e)-k(t);if(n>=1)return u(e+" ".repeat(n)+t,o);let r=Math.max(1,Math.floor((o-1)/2));return u(e,r)+" "+u(t,o-r-1)}function ue(e){let t=T.join(H.homedir(),".pi","agent","clean-footer.json"),o=i=>T.join(i,".pi","clean-footer.json"),n=()=>{},r=new C({globalConfigPath:t,getProjectConfigPath:o,getThinkingLevel:()=>{var i;return(i=e.getThinkingLevel)==null?void 0:i.call(e)},onRenderNeeded:()=>n()});e.registerCommand("footer",{description:"Toggle, refresh, or configure the clean footer",handler:async(i,a)=>{let d=i.trim();if(d==="refresh"){await r.refresh(),a.hasUI&&a.ui.notify("Footer refreshed","info");return}if(d==="reload"){await r.reload(a),a.hasUI&&r.isEnabled&&s(a),a.hasUI&&!r.isEnabled&&a.ui.setFooter(void 0),n(),c(a);return}if(d==="config"){l(a);return}let y=await r.toggle();a.hasUI&&(y?(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(),n=()=>{},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_end",i=>{r.onMessageEnd(i.message.role)}),e.on("tool_execution_end",i=>{r.onToolEnd(i.toolName)}),e.on("user_bash",()=>{r.onUserBash()});function s(i){i.hasUI&&i.ui.setFooter((a,d)=>(n=()=>a.requestRender(),{invalidate(){},render(y){let E=r.getFooterInput(i);return v(E,d,y)}}))}function c(i){i.hasUI&&(r.loadedError?i.ui.notify(`Clean footer config error: ${r.loadedError}`,"error"):i.ui.notify("Clean footer config loaded","info"))}function l(i){if(!i.hasUI)return;let a=r.loadedPaths.length?r.loadedPaths.join(`
|
|
3
|
+
`):"none",d=o(i.cwd);i.ui.notify(["Clean footer config",`global: ${t}`,`project: ${d}`,`loaded:
|
|
4
|
+
${a}`,r.loadedError?`error: ${r.loadedError}`:"error: none",`resolved: ${JSON.stringify(r.config)}`].join(`
|
|
5
5
|
`),"info")}}export{ue as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neilurk12/pi-clean-footer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Clean, minimal, and lightweight powerline-style footer extension for pi coding agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsup",
|
|
34
|
-
"dev": "tsup --watch"
|
|
34
|
+
"dev": "tsup --watch",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest"
|
|
35
37
|
},
|
|
36
38
|
"peerDependencies": {
|
|
37
39
|
"@earendil-works/pi-ai": "*",
|
|
@@ -40,7 +42,8 @@
|
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
44
|
"tsup": "^8.5.1",
|
|
43
|
-
"typescript": "^6.0.3"
|
|
45
|
+
"typescript": "^6.0.3",
|
|
46
|
+
"vitest": "^4.1.6"
|
|
44
47
|
},
|
|
45
48
|
"pnpm": {
|
|
46
49
|
"onlyBuiltDependencies": [
|
package/example.png
DELETED
|
Binary file
|