@juanibiapina/pi-powerbar 0.2.1 → 0.3.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/powerbar/render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/powerbar/render.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,+BAA+B,CAAC;AAEvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAgHD,wBAAgB,SAAS,CACxB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,GACX,MAAM,CAoCR"}
|
package/dist/powerbar/render.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* joined by themed separators. Supports inline progress bars using
|
|
6
6
|
* block characters (█ + partials ▏▎▍▌▋▊▉).
|
|
7
7
|
*/
|
|
8
|
-
import { visibleWidth } from "@mariozechner/pi-tui";
|
|
8
|
+
import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
9
9
|
/**
|
|
10
10
|
* Render a progress bar using full-height block characters.
|
|
11
11
|
*
|
|
@@ -53,22 +53,73 @@ function renderSegmentText(segment, settings, theme) {
|
|
|
53
53
|
}
|
|
54
54
|
return parts.join(" ");
|
|
55
55
|
}
|
|
56
|
-
function
|
|
56
|
+
function renderSideSegments(ids, segments, settings, theme) {
|
|
57
57
|
const rendered = [];
|
|
58
58
|
for (const id of ids) {
|
|
59
59
|
const seg = segments.get(id);
|
|
60
60
|
if (!seg || (!seg.text && !seg.suffix && seg.bar === undefined))
|
|
61
61
|
continue;
|
|
62
|
-
|
|
62
|
+
const text = renderSegmentText(seg, settings, theme);
|
|
63
|
+
rendered.push({ text, width: visibleWidth(text) });
|
|
63
64
|
}
|
|
64
|
-
return rendered
|
|
65
|
+
return rendered;
|
|
66
|
+
}
|
|
67
|
+
function joinSegments(segments, separator, separatorWidth) {
|
|
68
|
+
if (segments.length === 0)
|
|
69
|
+
return { text: "", width: 0 };
|
|
70
|
+
const text = segments.map((s) => s.text).join(separator);
|
|
71
|
+
const width = segments.reduce((sum, s) => sum + s.width, 0) + separatorWidth * (segments.length - 1);
|
|
72
|
+
return { text, width };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Truncate the widest segment to reclaim overflow space.
|
|
76
|
+
* Mutates the array in place and returns the new total width.
|
|
77
|
+
*/
|
|
78
|
+
function shrinkWidest(segments, overflow) {
|
|
79
|
+
if (segments.length === 0)
|
|
80
|
+
return;
|
|
81
|
+
let widestIdx = 0;
|
|
82
|
+
for (let i = 1; i < segments.length; i++) {
|
|
83
|
+
if (segments[i].width > segments[widestIdx].width) {
|
|
84
|
+
widestIdx = i;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const seg = segments[widestIdx];
|
|
88
|
+
const targetWidth = Math.max(1, seg.width - overflow);
|
|
89
|
+
segments[widestIdx] = {
|
|
90
|
+
text: truncateToWidth(seg.text, targetWidth, "…"),
|
|
91
|
+
width: targetWidth,
|
|
92
|
+
};
|
|
65
93
|
}
|
|
66
94
|
export function renderBar(segments, settings, theme, width) {
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
95
|
+
const separator = theme.fg("dim", settings.separator);
|
|
96
|
+
const separatorWidth = visibleWidth(separator);
|
|
97
|
+
const leftSegs = renderSideSegments(settings.left, segments, settings, theme);
|
|
98
|
+
const rightSegs = renderSideSegments(settings.right, segments, settings, theme);
|
|
99
|
+
const allSegs = [...leftSegs, ...rightSegs];
|
|
100
|
+
// Calculate total content width (segments + separators within each side + 1 for minimum padding)
|
|
101
|
+
const leftSepCount = Math.max(0, leftSegs.length - 1);
|
|
102
|
+
const rightSepCount = Math.max(0, rightSegs.length - 1);
|
|
103
|
+
const totalSepWidth = (leftSepCount + rightSepCount) * separatorWidth;
|
|
104
|
+
const totalSegWidth = allSegs.reduce((sum, s) => sum + s.width, 0);
|
|
105
|
+
const minPadding = 1;
|
|
106
|
+
const totalNeeded = totalSegWidth + totalSepWidth + minPadding;
|
|
107
|
+
// Shrink the widest segment(s) until it fits
|
|
108
|
+
if (totalNeeded > width) {
|
|
109
|
+
let overflow = totalNeeded - width;
|
|
110
|
+
const maxPasses = allSegs.length;
|
|
111
|
+
for (let i = 0; i < maxPasses && overflow > 0; i++) {
|
|
112
|
+
shrinkWidest(allSegs, overflow);
|
|
113
|
+
const newSegWidth = allSegs.reduce((sum, s) => sum + s.width, 0);
|
|
114
|
+
overflow = newSegWidth + totalSepWidth + minPadding - width;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Rebuild left/right from the (possibly truncated) segments
|
|
118
|
+
const left = joinSegments(allSegs.slice(0, leftSegs.length), separator, separatorWidth);
|
|
119
|
+
const right = joinSegments(allSegs.slice(leftSegs.length), separator, separatorWidth);
|
|
120
|
+
const padding = Math.max(minPadding, width - left.width - right.width);
|
|
121
|
+
const line = `${left.text}${" ".repeat(padding)}${right.text}`;
|
|
122
|
+
// Safety net
|
|
123
|
+
return truncateToWidth(line, width, "…");
|
|
73
124
|
}
|
|
74
125
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/powerbar/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rendering logic for the powerbar.\n *\n * Builds a single line with left-aligned and right-aligned segments,\n * joined by themed separators. Supports inline progress bars using\n * block characters (█ + partials ▏▎▍▌▋▊▉).\n */\n\nimport type { Theme, ThemeColor } from \"@mariozechner/pi-coding-agent\";\nimport { visibleWidth } from \"@mariozechner/pi-tui\";\nimport type { PowerbarSettings } from \"./settings.js\";\n\nexport interface Segment {\n\tid: string;\n\t/** Primary text, rendered before the bar. */\n\ttext: string;\n\t/** Text rendered after the bar (e.g., \"59%\"). */\n\tsuffix?: string;\n\ticon?: string;\n\tcolor?: string;\n\t/** If set, renders a progress bar. Value is 0–100. */\n\tbar?: number;\n}\n\n/**\n * Render a progress bar using full-height block characters.\n *\n * █ for filled blocks, ▏▎▍▌▋▊▉ for partial, space for empty.\n * Matches the pi-sub visual style.\n */\nfunction renderProgressBar(percent: number, width: number, theme: Theme, color: string): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filledFloat = (clamped / 100) * width;\n\tconst filledFull = Math.floor(filledFloat);\n\tconst remainder = filledFloat - filledFull;\n\n\t// Partial block levels: ▏(1/8) ▎(2/8) ▍(3/8) ▌(4/8) ▋(5/8) ▊(6/8) ▉(7/8)\n\tconst levels = [\"▏\", \"▎\", \"▍\", \"▌\", \"▋\", \"▊\", \"▉\"];\n\n\tconst themeColor = color as ThemeColor;\n\tconst filledStr = \"█\".repeat(filledFull);\n\n\tlet partial = \"\";\n\tlet emptyCount = width - filledFull;\n\n\tif (remainder >= 0.0625 && filledFull < width) {\n\t\tconst levelIndex = Math.max(0, Math.min(levels.length - 1, Math.round(remainder * 8) - 1));\n\t\tpartial = levels[levelIndex];\n\t\temptyCount = Math.max(0, emptyCount - 1);\n\t}\n\n\tconst emptyStr = \" \".repeat(emptyCount);\n\n\treturn theme.fg(themeColor, filledStr + partial) + emptyStr;\n}\n\n/**\n * Render a single segment.\n *\n * Layout: [icon] [text] [bar] [suffix]\n */\nfunction renderSegmentText(segment: Segment, settings: PowerbarSettings, theme: Theme): string {\n\tconst parts: string[] = [];\n\tconst themeColor = (segment.color || \"muted\") as ThemeColor;\n\n\tif (segment.icon) {\n\t\tparts.push(theme.fg(themeColor, segment.icon));\n\t}\n\n\tif (segment.text) {\n\t\tparts.push(theme.fg(themeColor, segment.text));\n\t}\n\n\tif (segment.bar !== undefined) {\n\t\tparts.push(renderProgressBar(segment.bar, settings.barWidth, theme, segment.color || \"muted\"));\n\t}\n\n\tif (segment.suffix) {\n\t\tparts.push(theme.fg(themeColor, segment.suffix));\n\t}\n\n\treturn parts.join(\" \");\n}\n\nfunction renderSide(ids: string[], segments: Map<string, Segment>, settings: PowerbarSettings, theme: Theme): string {\n\tconst rendered: string[] = [];\n\tfor (const id of ids) {\n\t\tconst seg = segments.get(id);\n\t\tif (!seg || (!seg.text && !seg.suffix && seg.bar === undefined)) continue;\n\t\trendered.push(renderSegmentText(seg, settings, theme));\n\t}\n\treturn rendered.join(theme.fg(\"dim\", settings.separator));\n}\n\nexport function renderBar(\n\tsegments: Map<string, Segment>,\n\tsettings: PowerbarSettings,\n\ttheme: Theme,\n\twidth: number,\n): string {\n\tconst leftStr = renderSide(settings.left, segments, settings, theme);\n\tconst rightStr = renderSide(settings.right, segments, settings, theme);\n\n\tconst leftWidth = visibleWidth(leftStr);\n\tconst rightWidth = visibleWidth(rightStr);\n\n\tconst padding = Math.max(1, width - leftWidth - rightWidth);\n\n\treturn `${leftStr}${\" \".repeat(padding)}${rightStr}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/powerbar/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rendering logic for the powerbar.\n *\n * Builds a single line with left-aligned and right-aligned segments,\n * joined by themed separators. Supports inline progress bars using\n * block characters (█ + partials ▏▎▍▌▋▊▉).\n */\n\nimport type { Theme, ThemeColor } from \"@mariozechner/pi-coding-agent\";\nimport { truncateToWidth, visibleWidth } from \"@mariozechner/pi-tui\";\nimport type { PowerbarSettings } from \"./settings.js\";\n\nexport interface Segment {\n\tid: string;\n\t/** Primary text, rendered before the bar. */\n\ttext: string;\n\t/** Text rendered after the bar (e.g., \"59%\"). */\n\tsuffix?: string;\n\ticon?: string;\n\tcolor?: string;\n\t/** If set, renders a progress bar. Value is 0–100. */\n\tbar?: number;\n}\n\n/**\n * Render a progress bar using full-height block characters.\n *\n * █ for filled blocks, ▏▎▍▌▋▊▉ for partial, space for empty.\n * Matches the pi-sub visual style.\n */\nfunction renderProgressBar(percent: number, width: number, theme: Theme, color: string): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filledFloat = (clamped / 100) * width;\n\tconst filledFull = Math.floor(filledFloat);\n\tconst remainder = filledFloat - filledFull;\n\n\t// Partial block levels: ▏(1/8) ▎(2/8) ▍(3/8) ▌(4/8) ▋(5/8) ▊(6/8) ▉(7/8)\n\tconst levels = [\"▏\", \"▎\", \"▍\", \"▌\", \"▋\", \"▊\", \"▉\"];\n\n\tconst themeColor = color as ThemeColor;\n\tconst filledStr = \"█\".repeat(filledFull);\n\n\tlet partial = \"\";\n\tlet emptyCount = width - filledFull;\n\n\tif (remainder >= 0.0625 && filledFull < width) {\n\t\tconst levelIndex = Math.max(0, Math.min(levels.length - 1, Math.round(remainder * 8) - 1));\n\t\tpartial = levels[levelIndex];\n\t\temptyCount = Math.max(0, emptyCount - 1);\n\t}\n\n\tconst emptyStr = \" \".repeat(emptyCount);\n\n\treturn theme.fg(themeColor, filledStr + partial) + emptyStr;\n}\n\n/**\n * Render a single segment.\n *\n * Layout: [icon] [text] [bar] [suffix]\n */\nfunction renderSegmentText(segment: Segment, settings: PowerbarSettings, theme: Theme): string {\n\tconst parts: string[] = [];\n\tconst themeColor = (segment.color || \"muted\") as ThemeColor;\n\n\tif (segment.icon) {\n\t\tparts.push(theme.fg(themeColor, segment.icon));\n\t}\n\n\tif (segment.text) {\n\t\tparts.push(theme.fg(themeColor, segment.text));\n\t}\n\n\tif (segment.bar !== undefined) {\n\t\tparts.push(renderProgressBar(segment.bar, settings.barWidth, theme, segment.color || \"muted\"));\n\t}\n\n\tif (segment.suffix) {\n\t\tparts.push(theme.fg(themeColor, segment.suffix));\n\t}\n\n\treturn parts.join(\" \");\n}\n\ninterface RenderedSegment {\n\ttext: string;\n\twidth: number;\n}\n\nfunction renderSideSegments(\n\tids: string[],\n\tsegments: Map<string, Segment>,\n\tsettings: PowerbarSettings,\n\ttheme: Theme,\n): RenderedSegment[] {\n\tconst rendered: RenderedSegment[] = [];\n\tfor (const id of ids) {\n\t\tconst seg = segments.get(id);\n\t\tif (!seg || (!seg.text && !seg.suffix && seg.bar === undefined)) continue;\n\t\tconst text = renderSegmentText(seg, settings, theme);\n\t\trendered.push({ text, width: visibleWidth(text) });\n\t}\n\treturn rendered;\n}\n\nfunction joinSegments(segments: RenderedSegment[], separator: string, separatorWidth: number): RenderedSegment {\n\tif (segments.length === 0) return { text: \"\", width: 0 };\n\tconst text = segments.map((s) => s.text).join(separator);\n\tconst width = segments.reduce((sum, s) => sum + s.width, 0) + separatorWidth * (segments.length - 1);\n\treturn { text, width };\n}\n\n/**\n * Truncate the widest segment to reclaim overflow space.\n * Mutates the array in place and returns the new total width.\n */\nfunction shrinkWidest(segments: RenderedSegment[], overflow: number): void {\n\tif (segments.length === 0) return;\n\n\tlet widestIdx = 0;\n\tfor (let i = 1; i < segments.length; i++) {\n\t\tif (segments[i].width > segments[widestIdx].width) {\n\t\t\twidestIdx = i;\n\t\t}\n\t}\n\n\tconst seg = segments[widestIdx];\n\tconst targetWidth = Math.max(1, seg.width - overflow);\n\tsegments[widestIdx] = {\n\t\ttext: truncateToWidth(seg.text, targetWidth, \"…\"),\n\t\twidth: targetWidth,\n\t};\n}\n\nexport function renderBar(\n\tsegments: Map<string, Segment>,\n\tsettings: PowerbarSettings,\n\ttheme: Theme,\n\twidth: number,\n): string {\n\tconst separator = theme.fg(\"dim\", settings.separator);\n\tconst separatorWidth = visibleWidth(separator);\n\n\tconst leftSegs = renderSideSegments(settings.left, segments, settings, theme);\n\tconst rightSegs = renderSideSegments(settings.right, segments, settings, theme);\n\tconst allSegs = [...leftSegs, ...rightSegs];\n\n\t// Calculate total content width (segments + separators within each side + 1 for minimum padding)\n\tconst leftSepCount = Math.max(0, leftSegs.length - 1);\n\tconst rightSepCount = Math.max(0, rightSegs.length - 1);\n\tconst totalSepWidth = (leftSepCount + rightSepCount) * separatorWidth;\n\tconst totalSegWidth = allSegs.reduce((sum, s) => sum + s.width, 0);\n\tconst minPadding = 1;\n\tconst totalNeeded = totalSegWidth + totalSepWidth + minPadding;\n\n\t// Shrink the widest segment(s) until it fits\n\tif (totalNeeded > width) {\n\t\tlet overflow = totalNeeded - width;\n\t\tconst maxPasses = allSegs.length;\n\t\tfor (let i = 0; i < maxPasses && overflow > 0; i++) {\n\t\t\tshrinkWidest(allSegs, overflow);\n\t\t\tconst newSegWidth = allSegs.reduce((sum, s) => sum + s.width, 0);\n\t\t\toverflow = newSegWidth + totalSepWidth + minPadding - width;\n\t\t}\n\t}\n\n\t// Rebuild left/right from the (possibly truncated) segments\n\tconst left = joinSegments(allSegs.slice(0, leftSegs.length), separator, separatorWidth);\n\tconst right = joinSegments(allSegs.slice(leftSegs.length), separator, separatorWidth);\n\n\tconst padding = Math.max(minPadding, width - left.width - right.width);\n\tconst line = `${left.text}${\" \".repeat(padding)}${right.text}`;\n\n\t// Safety net\n\treturn truncateToWidth(line, width, \"…\");\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/powerbar-tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/powerbar-tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,+BAA+B,CAAC;AAgDpF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAQ9D"}
|
|
@@ -41,9 +41,18 @@ function emitTokens(pi, ctx) {
|
|
|
41
41
|
color: "dim",
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
pi.
|
|
46
|
-
|
|
44
|
+
function resetTokens(pi) {
|
|
45
|
+
pi.events.emit("powerbar:update", {
|
|
46
|
+
id: "tokens",
|
|
47
|
+
text: undefined,
|
|
47
48
|
});
|
|
48
49
|
}
|
|
50
|
+
export default function createExtension(pi) {
|
|
51
|
+
// Reset on new/switched session
|
|
52
|
+
pi.on("session_start", async () => resetTokens(pi));
|
|
53
|
+
pi.on("session_switch", async () => resetTokens(pi));
|
|
54
|
+
// Update frequently during agent work
|
|
55
|
+
pi.on("tool_result", async (_event, ctx) => emitTokens(pi, ctx));
|
|
56
|
+
pi.on("turn_end", async (_event, ctx) => emitTokens(pi, ctx));
|
|
57
|
+
}
|
|
49
58
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/powerbar-tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,SAAS,YAAY,CAAC,KAAa;IAClC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1C,IAAI,KAAK,GAAG,KAAK;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1D,IAAI,KAAK,GAAG,OAAO;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC;IAC3D,IAAI,KAAK,GAAG,QAAQ;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAChE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC;AAC1C,CAAC;AAED,SAAS,UAAU,CAAC,EAAgB,EAAE,GAAqB;IAC1D,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;IAEhD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpE,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;YACxC,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;YAC1C,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAC7C,CAAC;IACF,CAAC;IAED,IAAI,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO;IAElD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC5C,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE;QACjC,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QACrB,KAAK,EAAE,KAAK;KACZ,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAgB;IACvD,EAAE,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/powerbar-tokens/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Powerbar Tokens Producer\n *\n * Shows cumulative token stats and session cost.\n * Segment ID: \"tokens\"\n */\n\nimport type { ExtensionAPI, ExtensionContext } from \"@mariozechner/pi-coding-agent\";\n\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction emitTokens(pi: ExtensionAPI, ctx: ExtensionContext): void {\n\tconst entries = ctx.sessionManager.getEntries();\n\n\tlet totalInput = 0;\n\tlet totalOutput = 0;\n\tlet totalCost = 0;\n\n\tfor (const entry of entries) {\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\ttotalInput += entry.message.usage.input;\n\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t}\n\t}\n\n\tif (totalInput === 0 && totalOutput === 0) return;\n\n\tconst parts: string[] = [];\n\tparts.push(`↑${formatTokens(totalInput)}`);\n\tparts.push(`↓${formatTokens(totalOutput)}`);\n\tif (totalCost > 0) {\n\t\tparts.push(`$${totalCost.toFixed(2)}`);\n\t}\n\n\tpi.events.emit(\"powerbar:update\", {\n\t\tid: \"tokens\",\n\t\ttext: parts.join(\" \"),\n\t\tcolor: \"dim\",\n\t});\n}\n\nfunction resetTokens(pi: ExtensionAPI): void {\n\tpi.events.emit(\"powerbar:update\", {\n\t\tid: \"tokens\",\n\t\ttext: undefined,\n\t});\n}\n\nexport default function createExtension(pi: ExtensionAPI): void {\n\t// Reset on new/switched session\n\tpi.on(\"session_start\", async () => resetTokens(pi));\n\tpi.on(\"session_switch\", async () => resetTokens(pi));\n\n\t// Update frequently during agent work\n\tpi.on(\"tool_result\", async (_event, ctx) => emitTokens(pi, ctx));\n\tpi.on(\"turn_end\", async (_event, ctx) => emitTokens(pi, ctx));\n}\n"]}
|
package/package.json
CHANGED