@pi-unipi/footer 3.0.0-alpha.26 → 3.0.0-alpha.28
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 +31 -45
- package/package.json +3 -3
- package/src/commands.ts +12 -41
- package/src/config.ts +162 -225
- package/src/events.ts +40 -247
- package/src/glance-editor.ts +116 -31
- package/src/index.ts +193 -377
- package/src/registry/index.ts +4 -53
- package/src/rendering/icons.ts +18 -1
- package/src/segments/compactor.ts +4 -55
- package/src/segments/long-horizon.ts +2 -35
- package/src/session-scan.ts +271 -0
- package/src/strip.ts +238 -0
- package/src/types.ts +48 -135
- package/src/help.ts +0 -160
- package/src/presets.ts +0 -128
- package/src/rendering/renderer.ts +0 -454
- package/src/rendering/separators.ts +0 -102
- package/src/segments/core.ts +0 -412
- package/src/segments/kanboard.ts +0 -91
- package/src/segments/mcp.ts +0 -109
- package/src/segments/memory.ts +0 -168
- package/src/segments/notify.ts +0 -61
- package/src/segments/ralph.ts +0 -123
- package/src/segments/status-ext.ts +0 -123
- package/src/segments/workflow.ts +0 -124
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Footer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Frames the input box and shows live session stats at the bottom of the terminal.
|
|
4
4
|
|
|
5
5
|
`@pi-unipi/footer` · part of [UniPi](../../README.md)
|
|
6
6
|
|
|
@@ -8,11 +8,10 @@ Show live session stats and the state of every UniPi package at the bottom of th
|
|
|
8
8
|
|
|
9
9
|
## What it does
|
|
10
10
|
|
|
11
|
-
- Puts a frame around the input box
|
|
12
|
-
- Shows a stats line below the input
|
|
11
|
+
- Puts a frame around the input box (**the glance frame**, always on when the footer is enabled).
|
|
12
|
+
- Shows a stats line below the input: input/output tokens, cost, average time to first token (TTFT), tokens per second, turns, steps, model and tool time, cache hit rate, and compactions.
|
|
13
13
|
- Shows a line above the input with counts of background tasks: running, stopped, failed and done.
|
|
14
|
-
-
|
|
15
|
-
- Lets you select a preset, separator, icon style and color mode, and turn each segment on or off.
|
|
14
|
+
- Adapts to the terminal: parts of the stats line drop by priority when the terminal is narrow, badges leave the frame titles before the branch or model truncate, and on very short terminals the stats and task lines hide.
|
|
16
15
|
|
|
17
16
|
## Quick start
|
|
18
17
|
|
|
@@ -36,35 +35,23 @@ The footer starts with the session. Open `/unipi:settings` → **Footer** to cha
|
|
|
36
35
|
|---|---|
|
|
37
36
|
| `/unipi:footer` | Turns the footer on or off. |
|
|
38
37
|
| `/unipi:footer on` | Turns the footer on. |
|
|
39
|
-
| `/unipi:footer off` | Turns the footer off. |
|
|
40
|
-
| `/unipi:footer-help` | Shows each active segment with its icon, label and description. |
|
|
38
|
+
| `/unipi:footer off` | Turns the footer off (plain pi editor). |
|
|
41
39
|
|
|
42
40
|
## The glance frame
|
|
43
41
|
|
|
44
|
-
The
|
|
42
|
+
The frame has three parts:
|
|
45
43
|
|
|
46
|
-
- **Top border.** The UNIPI brand, the long-horizon mode, the git branch, and the plan and permission mode. The brand shows a moving rainbow. The frame also shows the rainbow when the thinking level is `xhigh` or `max
|
|
44
|
+
- **Top border.** The UNIPI brand, the long-horizon mode, the git branch, and the plan and permission mode. The brand shows a moving rainbow. The frame also shows the rainbow when the thinking level is `xhigh` or `max` (unless **Rainbow** is `brand-only`).
|
|
47
45
|
- **Bottom border.** The workspace name, context use and window size, the model and the thinking level. With a [Fusion](../fusion/README.md) pair, it shows the lead and the sidekick. It also shows Kanboard claims.
|
|
48
46
|
- **Stats line.** The line below the input. A part stays hidden until it has data. For example, compactions show only after the first compaction.
|
|
49
47
|
|
|
50
48
|
The background-task line reads the [Background Tasks](../background-tasks/README.md) registry. It shows nothing when no task exists.
|
|
51
49
|
|
|
52
|
-
|
|
50
|
+
## Responsive behavior
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
| Preset | Segments |
|
|
59
|
-
|---|---|
|
|
60
|
-
| `default` | brand, mode, model, directory, git, context, compactions, tokens, TPS, cost, clock, duration |
|
|
61
|
-
| `classic` | mode, model, API state, tool count, git, TPS, context, cost, compactions, memory, command, loop status, extensions |
|
|
62
|
-
| `minimal` | mode, model, git, context, clock |
|
|
63
|
-
| `compact` | mode, model, git, TPS, context, cost, clock, duration |
|
|
64
|
-
| `full` | all groups, with a second row |
|
|
65
|
-
| `ascii` | the same segments as `compact` |
|
|
66
|
-
|
|
67
|
-
The hub list also shows `dense`, `devops` and `zen`. These names have no preset definition, so the footer uses `default` for them. To select `compact`, `full` or `ascii`, edit the settings file.
|
|
52
|
+
- **Width.** Each stats-line part has a priority. When the line does not fit, the lowest-priority parts drop whole (never mid-part), in this order: compactions, cache, time, turns, speed, cost — tokens always survive. The frame titles degrade the same way: the Kanboard label, the Fusion pair, the plan/permission cluster and the mode label drop (lowest value first) before the branch or model ever truncate.
|
|
53
|
+
- **Width safety.** Nothing ever writes the last terminal column (a full-width line desyncs wrapping terminals).
|
|
54
|
+
- **Height.** Below 20 terminal rows the stats line and the background-task line hide; the frame stays.
|
|
68
55
|
|
|
69
56
|
## Settings
|
|
70
57
|
|
|
@@ -72,33 +59,32 @@ Open `/unipi:settings` → **Footer**. The file is `~/.unipi/config/footer/confi
|
|
|
72
59
|
|
|
73
60
|
| Key | Default | What it does |
|
|
74
61
|
|---|---|---|
|
|
75
|
-
| `enabled` | `true` | Turns the footer on or off. |
|
|
76
|
-
| `glanceMode` | `true` | Uses the glance frame around the input. |
|
|
77
|
-
| `preset` | `default` | Selects the segments of the classic status line. |
|
|
78
|
-
| `showFullLabels` | `false` | Shows full labels in place of short labels. |
|
|
79
|
-
| `separator` | `powerline-thin` | Segment divider: `powerline`, `powerline-thin`, `slash`, `pipe`, `dot`, `ascii`. |
|
|
80
|
-
| `zoneSeparator` | `│` | Divider between the left, center and right zones. |
|
|
62
|
+
| `enabled` | `true` | Turns the footer on or off. `false` leaves the plain pi editor. |
|
|
81
63
|
| `iconStyle` | `nerd` | Icon set: `nerd` (needs a Nerd Font), `emoji` or `text`. |
|
|
82
|
-
| `colorMode` | `auto` | `auto`, `truecolor`, `256` or `none`. |
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
64
|
+
| `colorMode` | `auto` | `auto`, `truecolor`, `256` or `none`. The legacy value `mono` loads as `none`. |
|
|
65
|
+
| `rainbow` | `always` | `always` animates the brand (and the whole frame at `xhigh`/`max` thinking); `brand-only` never animates the whole frame; `off` disables the animation. |
|
|
66
|
+
| `processLine` | `true` | Shows the background-task line above the input. |
|
|
67
|
+
| `strip.turns` | `true` | Turn and step counters. |
|
|
68
|
+
| `strip.time` | `true` | Model time and tool time. |
|
|
69
|
+
| `strip.speed` | `true` | Average TTFT and tokens per second. |
|
|
70
|
+
| `strip.tokens` | `true` | Session input and output tokens. |
|
|
71
|
+
| `strip.cost` | `true` | Session cost, or `sub` when the model runs on a subscription. |
|
|
72
|
+
| `strip.compactions` | `true` | Compaction count, sizes and recency. |
|
|
73
|
+
| `strip.cache` | `true` | Cache hit percentage. |
|
|
74
|
+
| `badges.mode` | `true` | Long-horizon mode label beside the brand. |
|
|
75
|
+
| `badges.planPermission` | `true` | PLAN badge and permission mode in the top border. |
|
|
76
|
+
| `badges.fusion` | `true` | Fusion lead and sidekick in the bottom border. |
|
|
77
|
+
| `badges.kanboard` | `true` | Kanboard claims label in the top border. |
|
|
78
|
+
|
|
79
|
+
`colorMode: auto` uses 24-bit color where the terminal supports it, 256 colors in terminals such as Apple Terminal, and no color when the `NO_COLOR` environment variable exists.
|
|
80
|
+
|
|
81
|
+
Old v2 keys (`preset`, `separator`, `zoneSeparator`, `showFullLabels`, `groups`, `glanceMode`) in existing config files are ignored.
|
|
91
82
|
|
|
92
83
|
## How it works
|
|
93
84
|
|
|
94
|
-
The footer listens to UniPi events on the [event bus](../../docs/architecture/event-bus.md).
|
|
95
|
-
|
|
96
|
-
Some segments read data directly: the Pi session, the Kanboard registry and the Info Screen cache. The footer draws again each second.
|
|
97
|
-
|
|
98
|
-
The classic status line puts segments that do not fit into a second row.
|
|
85
|
+
The footer listens to UniPi events on the [event bus](../../docs/architecture/event-bus.md) for mode, plan and permission state. Usage data comes from an incremental scan of the session branch: each second only new entries are processed (a compaction or branch change triggers a full rescan), the same pass filling a cached snapshot for the stats line. The TPS tracker is fed live by pi's streaming events and reconciled by the same scan. The footer redraws when something it displays changed — plus once a second while the rainbow animates.
|
|
99
86
|
|
|
100
87
|
## See also
|
|
101
88
|
|
|
102
|
-
- [Footer customization](../../FOOTER_CUSTOMIZATION.md)
|
|
103
89
|
- [Info Screen](../info-screen/README.md)
|
|
104
90
|
- [Settings reference](../../docs/reference/settings.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.28",
|
|
4
4
|
"description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.28",
|
|
36
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.28"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
package/src/commands.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @pi-unipi/footer — Commands
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* /unipi:footer — toggle the footer on/off.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
8
|
import { UNIPI_PREFIX, FOOTER_COMMANDS } from "@pi-unipi/core";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import { applyGlanceMode, type FooterState } from "./index.js";
|
|
9
|
+
import { saveFooterSettings } from "./config.js";
|
|
10
|
+
import type { FooterState } from "./index.js";
|
|
11
|
+
import { fullRescan } from "./index.js";
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Register footer commands.
|
|
@@ -21,34 +20,17 @@ export function registerCommands(pi: ExtensionAPI, state: FooterState): void {
|
|
|
21
20
|
handler: async (args, ctx) => {
|
|
22
21
|
const arg = args?.trim().toLowerCase();
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
if (arg === "on")
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
saveFooterSettings({ enabled: true });
|
|
29
|
-
state.setupUI?.(pi, ctx);
|
|
30
|
-
ctx.ui.notify("Footer enabled", "info");
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
23
|
+
let enable: boolean;
|
|
24
|
+
if (arg === "on") enable = true;
|
|
25
|
+
else if (arg === "off") enable = false;
|
|
26
|
+
else enable = !state.enabled;
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
state.enabled = false;
|
|
37
|
-
state.renderer.setActive(false);
|
|
38
|
-
ctx.ui.setFooter(undefined);
|
|
39
|
-
ctx.ui.setWidget("footer-top", undefined);
|
|
40
|
-
ctx.ui.setWidget("footer-secondary", undefined);
|
|
41
|
-
saveFooterSettings({ enabled: false });
|
|
42
|
-
ctx.ui.notify("Footer disabled", "info");
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Toggle (no args or unknown args)
|
|
47
|
-
state.enabled = !state.enabled;
|
|
48
|
-
state.renderer.setActive(state.enabled);
|
|
28
|
+
state.enabled = enable;
|
|
29
|
+
saveFooterSettings({ enabled: enable });
|
|
49
30
|
|
|
50
|
-
if (
|
|
31
|
+
if (enable) {
|
|
51
32
|
state.setupUI?.(pi, ctx);
|
|
33
|
+
fullRescan(state);
|
|
52
34
|
ctx.ui.notify("Footer enabled", "info");
|
|
53
35
|
} else {
|
|
54
36
|
ctx.ui.setFooter(undefined);
|
|
@@ -56,17 +38,6 @@ export function registerCommands(pi: ExtensionAPI, state: FooterState): void {
|
|
|
56
38
|
ctx.ui.setWidget("footer-secondary", undefined);
|
|
57
39
|
ctx.ui.notify("Footer disabled", "info");
|
|
58
40
|
}
|
|
59
|
-
|
|
60
|
-
saveFooterSettings({ enabled: state.enabled });
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// /unipi:footer-help — show help overlay
|
|
65
|
-
pi.registerCommand(`${UNIPI_PREFIX}${FOOTER_COMMANDS.FOOTER_HELP}`, {
|
|
66
|
-
description: "Show footer segment guide (icons, labels, descriptions)",
|
|
67
|
-
handler: async (_args, _ctx) => {
|
|
68
|
-
const allSegments = Array.from(state.segmentLookup.values());
|
|
69
|
-
showFooterHelp(pi, allSegments, state.renderer.getPresetName());
|
|
70
41
|
},
|
|
71
42
|
});
|
|
72
43
|
}
|