@lokiyou/pi-nano-footer 0.15.2 → 0.15.3

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/index.ts +28 -2
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -66,10 +66,22 @@ export default function (pi: ExtensionAPI) {
66
66
  ctx.ui.setFooter((tui, theme, footerData) => {
67
67
  requestRender = () => tui.requestRender();
68
68
  const unsubBranch = footerData.onBranchChange(() => tui.requestRender());
69
+ let lastStatusSnapshot = snapshotStatuses(footerData);
70
+ const statusPoll = setInterval(() => {
71
+ const nextStatusSnapshot = snapshotStatuses(footerData);
72
+ if (nextStatusSnapshot !== lastStatusSnapshot) {
73
+ lastStatusSnapshot = nextStatusSnapshot;
74
+ tui.requestRender();
75
+ }
76
+ }, 500);
69
77
  const clock = setInterval(() => tui.requestRender(), 30_000);
70
78
 
71
79
  return {
72
- dispose() { unsubBranch(); clearInterval(clock); },
80
+ dispose() {
81
+ unsubBranch();
82
+ clearInterval(statusPoll);
83
+ clearInterval(clock);
84
+ },
73
85
  invalidate() {},
74
86
  render(width: number): string[] {
75
87
  if (width <= 0) return [];
@@ -124,10 +136,24 @@ export default function (pi: ExtensionAPI) {
124
136
  });
125
137
  }
126
138
 
139
+ function snapshotStatuses(footerData: any): string {
140
+ const statuses = footerData?.getExtensionStatuses?.();
141
+ if (!statuses || typeof statuses.entries !== "function") return "";
142
+
143
+ return Array.from(statuses.entries())
144
+ .sort(([a], [b]) => String(a).localeCompare(String(b)))
145
+ .map(([key, value]) => `${String(key)}:${stripAnsi(String(value))}`)
146
+ .join("|");
147
+ }
148
+
127
149
  // ═══════════════════════════════════════════════════════════════════════════
128
150
  // Helper 函数
129
151
  // ═══════════════════════════════════════════════════════════════════════════
130
152
 
153
+ function stripAnsi(text: string): string {
154
+ return text.replace(/\x1b\[[0-9;]*m/g, "");
155
+ }
156
+
131
157
  /** 16 进制色值 → ANSI 24-bit true color 前景色转义序列 */
132
158
  function ansi(hex: string, text: string): string {
133
159
  const h = hex.replace("#", "");
@@ -183,7 +209,7 @@ function renderMcpN(footerData: any): string | null {
183
209
  : Array.from(statuses.values()).find((value: unknown) => typeof value === "string" && value.includes("MCP:"));
184
210
  if (typeof raw !== "string") return null;
185
211
 
186
- const status = raw.replace(/\x1b\[[0-9;]*m/g, "").replace(/\s+/g, " ").trim();
212
+ const status = stripAnsi(raw).replace(/\s+/g, " ").trim();
187
213
 
188
214
  const ratio = /MCP:\s*(\d+)\s*\/\s*(\d+)\s+servers?/i.exec(status);
189
215
  if (ratio) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokiyou/pi-nano-footer",
3
- "version": "0.15.2",
3
+ "version": "0.15.3",
4
4
  "description": "Lightweight powerline-style footer for Pi Coding Agent that shows model, thinking level, directory, MCP status, context usage, tokens, and cost while keeping the built-in Working indicator.",
5
5
  "type": "module",
6
6
  "keywords": [