pi-bar 0.3.13 → 0.3.15
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 +9 -32
- package/extensions/status-footer.ts +128 -93
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -3,23 +3,23 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/pi-bar)
|
|
4
4
|
[](https://www.npmjs.com/package/pi-bar)
|
|
5
5
|
|
|
6
|
-
**Never accidentally run Opus on a typo again.** pi-bar
|
|
6
|
+
**Never accidentally run Opus on a typo again.** pi-bar keeps your model, thinking level, context pressure, extension status, and a live one-line TLDR visible in pi's footer.
|
|
7
7
|
|
|
8
8
|
```text
|
|
9
|
-
|
|
9
|
+
claude-opus-4.7 ❯ think:med ❯ 2.6% / 1.0M ❯ Inspecting package structure ❯ plan:active
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-

|
|
13
13
|
|
|
14
14
|
## Why use it?
|
|
15
15
|
|
|
16
16
|
- **See the active model at a glance** — catch accidental model switches before an expensive or sensitive task starts.
|
|
17
17
|
- **Track thinking level in place** — immediately notice when you are using the wrong reasoning setting.
|
|
18
18
|
- **Watch context pressure early** — context usage turns green, yellow, then red as you approach the limit.
|
|
19
|
-
- **
|
|
19
|
+
- **Follow what pi is doing** — a live TLDR keeps the current task visible without scrolling.
|
|
20
20
|
- **Keep extension statuses visible** — statuses set with `ctx.ui.setStatus()` still appear in the custom footer.
|
|
21
21
|
|
|
22
|
-
pi-bar is intentionally tiny: one small extension, no broad behavior changes, and no commands to learn. It replaces pi's built-in footer with a compact model / thinking / context /
|
|
22
|
+
pi-bar is intentionally tiny: one small extension, no broad behavior changes, and no commands to learn. It replaces pi's built-in footer with a compact model / thinking / context / TLDR / extension-status line.
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
@@ -48,15 +48,15 @@ Allowed segments are `model`, `thinking`, `context`, `tldr`, and `extensions`. T
|
|
|
48
48
|
|
|
49
49
|
### Configure live TLDR
|
|
50
50
|
|
|
51
|
-
pi-bar
|
|
51
|
+
pi-bar shows a concise live TLDR of the current task in the footer. It generates TLDRs from compacted recent prompt, assistant, tool, and result activity. It resets when you navigate the session tree so stale summaries do not follow you across branches. Set `PI_BAR_SHOW` without `tldr` to hide it.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Override the TLDR model with:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
56
|
PI_BAR_TLDR_MODEL=anthropic/claude-haiku-4-5 pi
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
You can also set `bar.tldrModel` in pi settings
|
|
59
|
+
You can also set `bar.tldrModel` in pi settings.
|
|
60
60
|
|
|
61
61
|
### Configure extension statuses
|
|
62
62
|
|
|
@@ -79,29 +79,6 @@ PI_BAR_THRESHOLDS=60,85 pi
|
|
|
79
79
|
|
|
80
80
|
The first number is the warning/yellow threshold. The second number is the danger/red threshold. Defaults are `70,90`.
|
|
81
81
|
|
|
82
|
-
### Change icon style
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
PI_BAR_ICONS=plain pi
|
|
86
|
-
PI_BAR_ICONS=emoji pi
|
|
87
|
-
PI_BAR_ICONS=nerdfont pi
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Supported presets:
|
|
91
|
-
|
|
92
|
-
- `unicode` — default, e.g. `◈ gpt-5.5 ❯ ✦ think:medium ❯ ◷ 42.7% / 272k ❯ Reading files ❯ ✧ plan:active`
|
|
93
|
-
- `plain` — maximum compatibility, e.g. `model:gpt-5.5 | think:medium | ctx:42.7% / 272k | Reading files | ext:plan:active`
|
|
94
|
-
- `emoji` — colorful emoji markers, e.g. `🤖 gpt-5.5 › ✨ think:medium › 🧭 42.7% / 272k › Reading files › 🧩 plan:active`
|
|
95
|
-
- `nerdfont` — icon-font glyphs for terminals configured with a Nerd Font, e.g. ` gpt-5.5 think:medium 42.7% / 272k Reading files plan:active`
|
|
96
|
-
|
|
97
|
-
## Compatibility
|
|
98
|
-
|
|
99
|
-
The default `unicode` preset uses common Unicode symbols that render well in most modern terminals. If your terminal shows boxes or misaligned glyphs, use:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
PI_BAR_ICONS=plain pi
|
|
103
|
-
```
|
|
104
|
-
|
|
105
82
|
## Pairs well with
|
|
106
83
|
|
|
107
84
|
- **[pi-chrome](https://www.npmjs.com/package/pi-chrome)** — give your Pi agent your real, signed-in Chrome. Use pi-bar's red-context threshold as the signal to wrap up long browser scrapes before context overflows.
|
|
@@ -111,4 +88,4 @@ PI_BAR_ICONS=plain pi
|
|
|
111
88
|
|
|
112
89
|
Pi extensions run with your local user permissions. Review any pi package source before installing it.
|
|
113
90
|
|
|
114
|
-
Live TLDR generation sends short snippets
|
|
91
|
+
Live TLDR generation sends short activity snippets to the selected TLDR model provider. Disable the `tldr` segment with `PI_BAR_SHOW` if that is unacceptable.
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* pi-bar — footer/statusline extension.
|
|
3
3
|
*
|
|
4
4
|
* Replaces the built-in footer with left-aligned segments:
|
|
5
|
-
*
|
|
5
|
+
* <model name> ❯ think:<level> ❯ <context% / window> ❯ <tldr> ❯ <extension statuses>
|
|
6
6
|
*
|
|
7
7
|
* Examples:
|
|
8
|
-
*
|
|
8
|
+
* claude-opus-4.7 ❯ think:med ❯ 2.6% / 1.0M
|
|
9
9
|
*
|
|
10
10
|
* Re-renders on model change, thinking-level change, status updates,
|
|
11
11
|
* and after each assistant turn so context usage stays current.
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* Configuration env vars:
|
|
14
14
|
* PI_BAR_SHOW=model,thinking,context,tldr,extensions
|
|
15
15
|
* PI_BAR_THRESHOLDS=70,90
|
|
16
|
-
* PI_BAR_ICONS=unicode|plain|emoji|nerdfont
|
|
17
16
|
*/
|
|
18
17
|
|
|
19
18
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
@@ -35,7 +34,6 @@ import {
|
|
|
35
34
|
} from "@earendil-works/pi-tui";
|
|
36
35
|
|
|
37
36
|
type SegmentName = "model" | "thinking" | "context" | "tldr" | "extensions";
|
|
38
|
-
type IconPreset = "unicode" | "plain" | "emoji" | "nerdfont";
|
|
39
37
|
type StatusFilter =
|
|
40
38
|
| { mode: "all"; hidden: Set<string> }
|
|
41
39
|
| { mode: "only"; shown: Set<string> };
|
|
@@ -76,8 +74,14 @@ type FastModelAuth = {
|
|
|
76
74
|
const STATUS_FILTER_ENTRY_TYPE = "pi-bar-status-filter";
|
|
77
75
|
const SETTINGS_TLDR_KEY = "tldr";
|
|
78
76
|
const SETTINGS_BAR_KEY = "bar";
|
|
79
|
-
const MAX_ACTIVITY_TEXT_CHARS =
|
|
77
|
+
const MAX_ACTIVITY_TEXT_CHARS = 800;
|
|
78
|
+
const MAX_USER_TEXT_CHARS = 700;
|
|
79
|
+
const MAX_ASSISTANT_UPDATE_CHARS = 500;
|
|
80
|
+
const MAX_TOOL_RESULT_OK_CHARS = 500;
|
|
81
|
+
const MAX_TOOL_RESULT_ERROR_CHARS = 900;
|
|
82
|
+
const MAX_FINAL_TEXT_CHARS = 700;
|
|
80
83
|
const MAX_RETAINED_RAW_ACTIVITIES = 128;
|
|
84
|
+
const ANSI_PATTERN = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
81
85
|
const MAX_CONTEXT_CHECKPOINTS = 8;
|
|
82
86
|
const TLDR_MAX_TOKENS = 120;
|
|
83
87
|
const TLDR_REQUEST_TIMEOUT_MS = 2_000;
|
|
@@ -96,45 +100,7 @@ const DEFAULT_SEGMENTS: SegmentName[] = [
|
|
|
96
100
|
const DEFAULT_WARNING_THRESHOLD = 70;
|
|
97
101
|
const DEFAULT_ERROR_THRESHOLD = 90;
|
|
98
102
|
|
|
99
|
-
const
|
|
100
|
-
IconPreset,
|
|
101
|
-
{
|
|
102
|
-
model: string;
|
|
103
|
-
thinking: string;
|
|
104
|
-
context: string;
|
|
105
|
-
extensions: string;
|
|
106
|
-
separator: string;
|
|
107
|
-
}
|
|
108
|
-
> = {
|
|
109
|
-
unicode: {
|
|
110
|
-
model: "◈",
|
|
111
|
-
thinking: "✦",
|
|
112
|
-
context: "◷",
|
|
113
|
-
extensions: "✧",
|
|
114
|
-
separator: "❯",
|
|
115
|
-
},
|
|
116
|
-
plain: {
|
|
117
|
-
model: "model",
|
|
118
|
-
thinking: "think",
|
|
119
|
-
context: "ctx",
|
|
120
|
-
extensions: "ext",
|
|
121
|
-
separator: "|",
|
|
122
|
-
},
|
|
123
|
-
emoji: {
|
|
124
|
-
model: "🤖",
|
|
125
|
-
thinking: "✨",
|
|
126
|
-
context: "🧭",
|
|
127
|
-
extensions: "🧩",
|
|
128
|
-
separator: "›",
|
|
129
|
-
},
|
|
130
|
-
nerdfont: {
|
|
131
|
-
model: "",
|
|
132
|
-
thinking: "",
|
|
133
|
-
context: "",
|
|
134
|
-
extensions: "",
|
|
135
|
-
separator: "",
|
|
136
|
-
},
|
|
137
|
-
};
|
|
103
|
+
const SEGMENT_SEPARATOR = "❯";
|
|
138
104
|
|
|
139
105
|
function formatTokens(n: number): string {
|
|
140
106
|
if (n >= 1_000_000) {
|
|
@@ -229,12 +195,6 @@ function parseThresholds(): { warningThreshold: number; errorThreshold: number }
|
|
|
229
195
|
};
|
|
230
196
|
}
|
|
231
197
|
|
|
232
|
-
function parseIconPreset(): IconPreset {
|
|
233
|
-
const raw = process.env.PI_BAR_ICONS?.trim().toLowerCase();
|
|
234
|
-
if (raw === "plain" || raw === "emoji" || raw === "nerdfont") return raw;
|
|
235
|
-
return "unicode";
|
|
236
|
-
}
|
|
237
|
-
|
|
238
198
|
function parseTldrModelSpec(value: string): TldrModelPreference | undefined {
|
|
239
199
|
const trimmed = value.trim();
|
|
240
200
|
if (!trimmed || trimmed === "auto") return undefined;
|
|
@@ -324,6 +284,76 @@ function truncateText(text: string, maxChars: number): string {
|
|
|
324
284
|
return `${text.slice(0, maxChars - 1)}…`;
|
|
325
285
|
}
|
|
326
286
|
|
|
287
|
+
function tailText(text: string, maxChars: number): string {
|
|
288
|
+
if (text.length <= maxChars) return text;
|
|
289
|
+
return `…${text.slice(-(maxChars - 1))}`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function compactText(text: string): string {
|
|
293
|
+
return text.replace(ANSI_PATTERN, "").replace(/\s+/g, " ").trim();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function compactValue(value: unknown, maxChars: number): string | undefined {
|
|
297
|
+
if (value === undefined || value === null) return undefined;
|
|
298
|
+
let text: string;
|
|
299
|
+
if (typeof value === "string") {
|
|
300
|
+
text = value;
|
|
301
|
+
} else {
|
|
302
|
+
try {
|
|
303
|
+
text = JSON.stringify(value);
|
|
304
|
+
} catch {
|
|
305
|
+
text = String(value);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return text ? truncateText(compactText(text), maxChars) : undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function compactToolInput(toolName: string, input: Record<string, unknown> | undefined): string {
|
|
312
|
+
if (!input) return toolName;
|
|
313
|
+
|
|
314
|
+
const path = compactValue(input.path ?? input.filePath ?? input.cwd, 120);
|
|
315
|
+
const command = compactValue(input.command, 180);
|
|
316
|
+
const pattern = compactValue(input.pattern ?? input.query, 120);
|
|
317
|
+
const include = compactValue(input.include ?? input.glob, 80);
|
|
318
|
+
|
|
319
|
+
switch (toolName) {
|
|
320
|
+
case "bash":
|
|
321
|
+
return command ? `bash ${command}` : "bash";
|
|
322
|
+
case "read":
|
|
323
|
+
return path ? `read ${path}` : "read";
|
|
324
|
+
case "edit":
|
|
325
|
+
return path ? `edit ${path}` : "edit";
|
|
326
|
+
case "write":
|
|
327
|
+
return path ? `write ${path}` : "write";
|
|
328
|
+
case "grep":
|
|
329
|
+
return ["grep", pattern, path, include ? `include ${include}` : undefined]
|
|
330
|
+
.filter(Boolean)
|
|
331
|
+
.join(" ");
|
|
332
|
+
case "find":
|
|
333
|
+
return ["find", path, pattern].filter(Boolean).join(" ");
|
|
334
|
+
case "ls":
|
|
335
|
+
return path ? `ls ${path}` : "ls";
|
|
336
|
+
default: {
|
|
337
|
+
const args = Object.entries(input)
|
|
338
|
+
.slice(0, 3)
|
|
339
|
+
.map(([key, value]) => {
|
|
340
|
+
const formatted = compactValue(value, 80);
|
|
341
|
+
return formatted ? `${key}=${formatted}` : undefined;
|
|
342
|
+
})
|
|
343
|
+
.filter(Boolean)
|
|
344
|
+
.join(" ");
|
|
345
|
+
return args ? `${toolName} ${args}` : toolName;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function compactToolResultText(text: string | undefined, isError: boolean): string | undefined {
|
|
351
|
+
if (!text) return undefined;
|
|
352
|
+
const compacted = compactText(text);
|
|
353
|
+
const maxChars = isError ? MAX_TOOL_RESULT_ERROR_CHARS : MAX_TOOL_RESULT_OK_CHARS;
|
|
354
|
+
return isError ? truncateText(compacted, maxChars) : tailText(compacted, maxChars);
|
|
355
|
+
}
|
|
356
|
+
|
|
327
357
|
function extractTextContent(content: readonly unknown[] | undefined): string | undefined {
|
|
328
358
|
if (!content) return undefined;
|
|
329
359
|
const text = content
|
|
@@ -336,12 +366,8 @@ function extractTextContent(content: readonly unknown[] | undefined): string | u
|
|
|
336
366
|
})
|
|
337
367
|
.filter((part): part is string => Boolean(part))
|
|
338
368
|
.join("\n");
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
function prefixed(icon: string, text: string, preset: IconPreset): string {
|
|
343
|
-
if (preset === "plain") return `${icon}:${text}`;
|
|
344
|
-
return `${icon} ${text}`;
|
|
369
|
+
const compacted = compactText(text);
|
|
370
|
+
return compacted.length > 0 ? compacted : undefined;
|
|
345
371
|
}
|
|
346
372
|
|
|
347
373
|
class TldrFactCollector {
|
|
@@ -354,7 +380,11 @@ class TldrFactCollector {
|
|
|
354
380
|
}
|
|
355
381
|
|
|
356
382
|
recordUserMessage(prompt: string): TldrActivity {
|
|
357
|
-
return this.addActivity(
|
|
383
|
+
return this.addActivity(
|
|
384
|
+
"user_message",
|
|
385
|
+
"immediate",
|
|
386
|
+
`user: ${truncateText(compactText(prompt), MAX_USER_TEXT_CHARS)}`,
|
|
387
|
+
);
|
|
358
388
|
}
|
|
359
389
|
|
|
360
390
|
recordAssistantUpdate(message: unknown): TldrActivity | undefined {
|
|
@@ -363,27 +393,38 @@ class TldrFactCollector {
|
|
|
363
393
|
if (record.role !== "assistant") return undefined;
|
|
364
394
|
const text = extractTextContent(record.content as readonly unknown[] | undefined);
|
|
365
395
|
return text
|
|
366
|
-
? this.addActivity(
|
|
396
|
+
? this.addActivity(
|
|
397
|
+
"assistant_update",
|
|
398
|
+
"normal",
|
|
399
|
+
`assistant: ${tailText(text, MAX_ASSISTANT_UPDATE_CHARS)}`,
|
|
400
|
+
)
|
|
367
401
|
: undefined;
|
|
368
402
|
}
|
|
369
403
|
|
|
370
|
-
recordToolCall(event: { toolName: string }): TldrActivity {
|
|
371
|
-
return this.addActivity(
|
|
404
|
+
recordToolCall(event: { toolName: string; input?: Record<string, unknown> }): TldrActivity {
|
|
405
|
+
return this.addActivity(
|
|
406
|
+
"tool_call",
|
|
407
|
+
"normal",
|
|
408
|
+
`tool: ${compactToolInput(event.toolName, event.input)}`,
|
|
409
|
+
);
|
|
372
410
|
}
|
|
373
411
|
|
|
374
412
|
recordToolResult(event: {
|
|
375
413
|
toolName: string;
|
|
414
|
+
input?: Record<string, unknown>;
|
|
376
415
|
isError?: boolean;
|
|
377
416
|
content?: readonly unknown[];
|
|
378
417
|
}): TldrActivity {
|
|
379
|
-
const
|
|
380
|
-
const
|
|
418
|
+
const isError = Boolean(event.isError);
|
|
419
|
+
const resultText = compactToolResultText(extractTextContent(event.content), isError);
|
|
420
|
+
const status = isError ? "error" : "ok";
|
|
421
|
+
const tool = compactToolInput(event.toolName, event.input);
|
|
381
422
|
return this.addActivity(
|
|
382
423
|
"tool_result",
|
|
383
424
|
"normal",
|
|
384
425
|
resultText
|
|
385
|
-
? `
|
|
386
|
-
: `
|
|
426
|
+
? `result: ${tool} ${status}; ${resultText}`
|
|
427
|
+
: `result: ${tool} ${status}`,
|
|
387
428
|
);
|
|
388
429
|
}
|
|
389
430
|
|
|
@@ -399,12 +440,12 @@ class TldrFactCollector {
|
|
|
399
440
|
if (stopReason === "stop") {
|
|
400
441
|
const finalText = extractTextContent(record.content as readonly unknown[] | undefined);
|
|
401
442
|
if (!finalText) return "emptyFinalStop";
|
|
402
|
-
text = `
|
|
443
|
+
text = `final: ${truncateText(finalText, MAX_FINAL_TEXT_CHARS)}`;
|
|
403
444
|
} else if (stopReason) {
|
|
404
|
-
const error = typeof record.errorMessage === "string" ? record.errorMessage : undefined;
|
|
445
|
+
const error = typeof record.errorMessage === "string" ? compactText(record.errorMessage) : undefined;
|
|
405
446
|
text = error
|
|
406
|
-
? `
|
|
407
|
-
: `
|
|
447
|
+
? `final: ${stopReason}; ${truncateText(error, MAX_FINAL_TEXT_CHARS)}`
|
|
448
|
+
: `final: ${stopReason}`;
|
|
408
449
|
}
|
|
409
450
|
|
|
410
451
|
return text
|
|
@@ -501,13 +542,21 @@ class FooterTldrEngine {
|
|
|
501
542
|
if (activity) this.enqueue(ctx, activity);
|
|
502
543
|
}
|
|
503
544
|
|
|
504
|
-
recordToolCall(
|
|
545
|
+
recordToolCall(
|
|
546
|
+
ctx: ExtensionContext,
|
|
547
|
+
event: { toolName: string; input?: Record<string, unknown> },
|
|
548
|
+
): void {
|
|
505
549
|
this.enqueue(ctx, this.facts.recordToolCall(event));
|
|
506
550
|
}
|
|
507
551
|
|
|
508
552
|
recordToolResult(
|
|
509
553
|
ctx: ExtensionContext,
|
|
510
|
-
event: {
|
|
554
|
+
event: {
|
|
555
|
+
toolName: string;
|
|
556
|
+
input?: Record<string, unknown>;
|
|
557
|
+
isError?: boolean;
|
|
558
|
+
content?: readonly unknown[];
|
|
559
|
+
},
|
|
511
560
|
): void {
|
|
512
561
|
this.enqueue(ctx, this.facts.recordToolResult(event));
|
|
513
562
|
}
|
|
@@ -746,7 +795,9 @@ Summarize only activity up to the requested index.
|
|
|
746
795
|
If context is sparse, still summarize the available activity.
|
|
747
796
|
Never ask for more information or say there is not enough context.
|
|
748
797
|
Return one concise status fragment under ${TLDR_TARGET_SUMMARY_CHARS} characters.
|
|
749
|
-
|
|
798
|
+
Omit subjects like "the agent" or "it".
|
|
799
|
+
Prefer verb + direct object. Include outcome only if important.
|
|
800
|
+
Do not address the user.
|
|
750
801
|
Plain text only; no markdown, JSON, code, bullets, quotes, or file/tool names.
|
|
751
802
|
${tenseInstruction}`;
|
|
752
803
|
}
|
|
@@ -760,7 +811,7 @@ function previousCheckpointLines(checkpoints: readonly TldrCheckpoint[]): string
|
|
|
760
811
|
}
|
|
761
812
|
|
|
762
813
|
function formatRawActivity(activity: TldrActivity): string {
|
|
763
|
-
return `[${activity.index}] ${activity.
|
|
814
|
+
return `[${activity.index}] ${activity.text}`;
|
|
764
815
|
}
|
|
765
816
|
|
|
766
817
|
function shouldShowStatus(key: string, filter: StatusFilter): boolean {
|
|
@@ -1078,8 +1129,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1078
1129
|
if (!ctx.hasUI) return;
|
|
1079
1130
|
|
|
1080
1131
|
const visibleSegments = parseSegments();
|
|
1081
|
-
const iconPreset = parseIconPreset();
|
|
1082
|
-
const icons = ICON_PRESETS[iconPreset];
|
|
1083
1132
|
const { warningThreshold, errorThreshold } = parseThresholds();
|
|
1084
1133
|
|
|
1085
1134
|
ctx.ui.setFooter((tui, theme, footerData) => {
|
|
@@ -1111,28 +1160,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
1111
1160
|
const tldrText = tldr.text();
|
|
1112
1161
|
|
|
1113
1162
|
const segmentRenderers: Record<SegmentName, string | null> = {
|
|
1114
|
-
model: theme.fg(
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
),
|
|
1118
|
-
thinking: theme.fg(
|
|
1119
|
-
thinkingColor(thinkingLevel),
|
|
1120
|
-
prefixed(icons.thinking, `think:${thinkingLevel}`, iconPreset),
|
|
1121
|
-
),
|
|
1122
|
-
context: theme.fg(
|
|
1123
|
-
contextSegmentColor,
|
|
1124
|
-
prefixed(icons.context, contextText, iconPreset),
|
|
1125
|
-
),
|
|
1163
|
+
model: theme.fg("accent", modelName),
|
|
1164
|
+
thinking: theme.fg(thinkingColor(thinkingLevel), `think:${thinkingLevel}`),
|
|
1165
|
+
context: theme.fg(contextSegmentColor, contextText),
|
|
1126
1166
|
tldr: tldrText ? theme.fg("muted", tldrText) : null,
|
|
1127
|
-
extensions: extensionStatuses
|
|
1128
|
-
? theme.fg(
|
|
1129
|
-
"muted",
|
|
1130
|
-
prefixed(icons.extensions, extensionStatuses, iconPreset),
|
|
1131
|
-
)
|
|
1132
|
-
: null,
|
|
1167
|
+
extensions: extensionStatuses ? theme.fg("muted", extensionStatuses) : null,
|
|
1133
1168
|
};
|
|
1134
1169
|
|
|
1135
|
-
const separator = ` ${theme.fg("dim",
|
|
1170
|
+
const separator = ` ${theme.fg("dim", SEGMENT_SEPARATOR)} `;
|
|
1136
1171
|
const line = visibleSegments
|
|
1137
1172
|
.map((segment) => segmentRenderers[segment])
|
|
1138
1173
|
.filter((segment): segment is string => segment !== null)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-bar",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.15",
|
|
4
|
+
"description": "Pi footer/statusline showing active model, thinking level, context pressure, live TLDR, and extension statuses.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"pi-package",
|
|
@@ -51,6 +51,6 @@
|
|
|
51
51
|
"extensions": [
|
|
52
52
|
"./extensions/status-footer.ts"
|
|
53
53
|
],
|
|
54
|
-
"image": "https://cdn.jsdelivr.net/npm/pi-bar@0.3.
|
|
54
|
+
"image": "https://cdn.jsdelivr.net/npm/pi-bar@0.3.15/assets/screenshot.png"
|
|
55
55
|
}
|
|
56
56
|
}
|