@lokiyou/pi-nano-footer 0.15.1 → 0.15.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.
- package/README.md +21 -21
- package/index.ts +52 -10
- package/package.json +37 -37
package/README.md
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
# @lokiyou/pi-nano-footer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lightweight powerline-style footer for Pi Coding Agent.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This extension replaces the default footer with a compact single-line status bar while keeping Pi's built-in `Working...` indicator. It is designed to stay small and focused.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
pi install npm:@lokiyou/pi-nano-footer
|
|
11
|
+
/reload
|
|
11
12
|
```
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
## What it shows
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
/reload
|
|
17
|
-
```
|
|
16
|
+
From left to right, the footer shows:
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
- current model
|
|
19
|
+
- thinking level
|
|
20
|
+
- current directory name
|
|
21
|
+
- MCP status summary when MCP status is available
|
|
22
|
+
- context usage
|
|
23
|
+
- token totals
|
|
24
|
+
- estimated cost
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
## Behavior
|
|
22
27
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- 💾 Token 用量
|
|
28
|
-
- 💰 费用
|
|
28
|
+
- Uses a compact powerline-style separator layout.
|
|
29
|
+
- Keeps Pi's built-in `Working...` indicator instead of replacing it.
|
|
30
|
+
- Reads MCP status from extension status data when an MCP adapter exposes it.
|
|
31
|
+
- Focuses only on the footer and does not replace the editor component.
|
|
29
32
|
|
|
30
|
-
##
|
|
33
|
+
## Notes
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
- 颜色和 `pi-powerline-footer` 的默认 preset 保持一致
|
|
34
|
-
- 不替代内置工作状态指示器
|
|
35
|
-
- 适合想要简洁 footer、但不想丢掉 Pi 原生反馈的人
|
|
35
|
+
No additional configuration is required.
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## License
|
|
38
38
|
|
|
39
39
|
MIT
|
package/index.ts
CHANGED
|
@@ -11,13 +11,14 @@ import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
|
11
11
|
|
|
12
12
|
// ── Nerd Font 图标(与 pi-powerline-footer 完全一致) ──
|
|
13
13
|
const icons = {
|
|
14
|
-
model: "\uec19",
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
model: "\uec19", // nf-md-chip
|
|
15
|
+
mcp: "\u{f048d}", // nf-md-server-network
|
|
16
|
+
folder: "\uf115", // nf-fa-folder_open
|
|
17
|
+
context: "\ue70f", // nf-dev-database
|
|
18
|
+
cache: "\uf1c0", // nf-fa-database
|
|
19
|
+
input: "\uf090", // nf-fa-sign_in
|
|
20
|
+
cost: "\uf155", // nf-fa-dollar
|
|
21
|
+
sep: "\ue0b1", // powerline-thin
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
// ── 用户自定义霓虹配色 ──
|
|
@@ -87,14 +88,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
87
88
|
const dir = ctx.cwd.replace(/\\/g, "/").split("/").filter(Boolean).pop() || ctx.cwd;
|
|
88
89
|
parts.push(ansi(C.path, `${icons.folder} ${dir}`));
|
|
89
90
|
|
|
90
|
-
// 4.
|
|
91
|
+
// 4. MCP 摘要 —— 紧凑图标版
|
|
92
|
+
const mcp = renderMcpN(footerData);
|
|
93
|
+
if (mcp) parts.push(mcp);
|
|
94
|
+
|
|
95
|
+
// 5. 上下文用量 —— #6c5ce7 紫 / #fdcb6e 黄 / #ff3366 红
|
|
91
96
|
parts.push(renderContextN(ctx));
|
|
92
97
|
|
|
93
|
-
//
|
|
98
|
+
// 6. Token 用量 —— #00ff87 荧光绿
|
|
94
99
|
const { input, cost } = calcTotals(ctx);
|
|
95
100
|
parts.push(ansi(C.tokens, `${icons.cache} ${icons.input} ${fmt(input)}`));
|
|
96
101
|
|
|
97
|
-
//
|
|
102
|
+
// 7. 费用 —— #fdcb6e 明黄色
|
|
98
103
|
parts.push(ansi(C.cost, `${icons.cost} ${cost.toFixed(2)}`));
|
|
99
104
|
|
|
100
105
|
return [truncateToWidth(parts.join(S), width, "")];
|
|
@@ -168,6 +173,43 @@ function renderContextN(ctx: any): string {
|
|
|
168
173
|
return ansi(color, `${icons.context} ${pct?.toFixed(1) ?? "?"}%${maxStr}`);
|
|
169
174
|
}
|
|
170
175
|
|
|
176
|
+
/** 渲染 MCP 状态摘要,优先显示已连接/总数 */
|
|
177
|
+
function renderMcpN(footerData: any): string | null {
|
|
178
|
+
const statuses = footerData?.getExtensionStatuses?.();
|
|
179
|
+
if (!statuses || typeof statuses.get !== "function") return null;
|
|
180
|
+
|
|
181
|
+
const raw = typeof statuses.get("mcp") === "string"
|
|
182
|
+
? statuses.get("mcp")
|
|
183
|
+
: Array.from(statuses.values()).find((value: unknown) => typeof value === "string" && value.includes("MCP:"));
|
|
184
|
+
if (typeof raw !== "string") return null;
|
|
185
|
+
|
|
186
|
+
const status = raw.replace(/\x1b\[[0-9;]*m/g, "").replace(/\s+/g, " ").trim();
|
|
187
|
+
|
|
188
|
+
const ratio = /MCP:\s*(\d+)\s*\/\s*(\d+)\s+servers?/i.exec(status);
|
|
189
|
+
if (ratio) {
|
|
190
|
+
const connected = Number(ratio[1]);
|
|
191
|
+
const total = Number(ratio[2]);
|
|
192
|
+
const color = connected >= total ? C.tokens : C.thinkingMedium;
|
|
193
|
+
return ansi(color, `${icons.mcp} ${connected}/${total}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const connected = /MCP:\s*(\d+)\s+servers connected(?:\s*\((\d+)\s+tools\))?/i.exec(status);
|
|
197
|
+
if (connected) {
|
|
198
|
+
return ansi(C.tokens, `${icons.mcp} ${connected[1]}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const connecting = /MCP:\s*connecting to\s+(\d+)\s+servers?/i.exec(status);
|
|
202
|
+
if (connecting) {
|
|
203
|
+
return ansi(C.thinkingMedium, `${icons.mcp} …/${connecting[1]}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (/failed|error|needs-auth|oauth/i.test(status)) {
|
|
207
|
+
return ansi(C.contextError, `${icons.mcp} !`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return ansi(C.context, `${icons.mcp} ?`);
|
|
211
|
+
}
|
|
212
|
+
|
|
171
213
|
/** 遍历会话分支,累计 input token 数和总费用 */
|
|
172
214
|
function calcTotals(ctx: any): { input: number; cost: number } {
|
|
173
215
|
let input = 0, cost = 0;
|
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@lokiyou/pi-nano-footer",
|
|
3
|
-
"version": "0.15.
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"pi-package",
|
|
8
|
-
"pi-extension",
|
|
9
|
-
"footer",
|
|
10
|
-
"statusline",
|
|
11
|
-
"powerline",
|
|
12
|
-
"neon"
|
|
13
|
-
],
|
|
14
|
-
"author": "lokiyou",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"files": [
|
|
17
|
-
"index.ts",
|
|
18
|
-
"README.md"
|
|
19
|
-
],
|
|
20
|
-
"pi": {
|
|
21
|
-
"extensions": [
|
|
22
|
-
"./index.ts"
|
|
23
|
-
]
|
|
24
|
-
},
|
|
25
|
-
"peerDependencies": {
|
|
26
|
-
"@earendil-works/pi-coding-agent": "*",
|
|
27
|
-
"@earendil-works/pi-tui": "*",
|
|
28
|
-
"@earendil-works/pi-ai": "*"
|
|
29
|
-
},
|
|
30
|
-
"repository": {
|
|
31
|
-
"type": "git",
|
|
32
|
-
"url": ""
|
|
33
|
-
},
|
|
34
|
-
"publishConfig": {
|
|
35
|
-
"access": "public"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@lokiyou/pi-nano-footer",
|
|
3
|
+
"version": "0.15.2",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension",
|
|
9
|
+
"footer",
|
|
10
|
+
"statusline",
|
|
11
|
+
"powerline",
|
|
12
|
+
"neon"
|
|
13
|
+
],
|
|
14
|
+
"author": "lokiyou",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"files": [
|
|
17
|
+
"index.ts",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"pi": {
|
|
21
|
+
"extensions": [
|
|
22
|
+
"./index.ts"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
27
|
+
"@earendil-works/pi-tui": "*",
|
|
28
|
+
"@earendil-works/pi-ai": "*"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": ""
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|