@underactive/pi-topping 0.2.0 → 0.2.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.
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /** pi-topping extension entry point. */
2
2
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
- import { SessionManager } from "./session.ts";
3
+ import { SessionManager } from "./src/session.ts";
4
4
 
5
5
  export default function (pi: ExtensionAPI): void {
6
6
  new SessionManager(pi).install();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@underactive/pi-topping",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A Pi extension that replaces the default \"Working...\" loader with a shimmering, randomized activity word, live elapsed timer, and output-token activity meter",
5
5
  "keywords": ["pi-package", "pi-extension"],
6
6
  "license": "MIT",
@@ -20,7 +20,7 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
- "files": ["*.ts", "README.md", "LICENSE"],
23
+ "files": ["index.ts", "src/**/*.ts", "README.md", "LICENSE"],
24
24
  "scripts": {
25
25
  "test": "node --test tests/*.test.ts",
26
26
  "typecheck": "tsc --noEmit"
@@ -67,29 +67,39 @@ export function buildWorkingMessage(
67
67
  export function shimmerString(
68
68
  text: string,
69
69
  elapsedMs: number,
70
- theme: Pick<Theme, "fg" | "bold">,
70
+ theme: Pick<Theme, "getFgAnsi">,
71
71
  ): string {
72
72
  const chars = [...text];
73
73
  if (chars.length === 0) return "";
74
74
  const SHIMMER_SWEEP_S = 2.0;
75
75
  const SHIMMER_BAND_HALF = 5.0;
76
76
  const SHIMMER_PADDING = 10;
77
+ const SHIMMER_BASE = ansiToRgb(theme.getFgAnsi("dim"));
78
+ const SHIMMER_HIGHLIGHT = ansiToRgb(theme.getFgAnsi("text"));
77
79
  const period = chars.length + SHIMMER_PADDING * 2;
78
80
  const elapsedS = elapsedMs / 1000;
79
81
  const pos = ((elapsedS % SHIMMER_SWEEP_S) / SHIMMER_SWEEP_S) * period;
80
82
 
81
83
  return chars
82
84
  .map((ch, i) => {
83
- const dist = Math.abs(i + SHIMMER_PADDING - pos);
84
- const intensity =
85
- dist <= SHIMMER_BAND_HALF
86
- ? 0.5 * (1 + Math.cos((Math.PI * dist) / SHIMMER_BAND_HALF))
87
- : 0;
88
- if (intensity > 0.6) return theme.bold(theme.fg("text", ch));
89
- if (intensity > 0.15) return theme.fg("muted", ch);
90
- return theme.fg("dim", ch);
85
+ const dist = Math.abs((i + SHIMMER_PADDING) - pos);
86
+ const t = dist <= SHIMMER_BAND_HALF
87
+ ? 0.5 * (1 + Math.cos(Math.PI * dist / SHIMMER_BAND_HALF))
88
+ : 0;
89
+ const alpha = t * 0.9;
90
+ const r = Math.round(SHIMMER_HIGHLIGHT[0] * alpha + SHIMMER_BASE[0] * (1 - alpha));
91
+ const g = Math.round(SHIMMER_HIGHLIGHT[1] * alpha + SHIMMER_BASE[1] * (1 - alpha));
92
+ const b = Math.round(SHIMMER_HIGHLIGHT[2] * alpha + SHIMMER_BASE[2] * (1 - alpha));
93
+ const bold = t > 0.2 ? "\x1b[1m" : "";
94
+ return `${bold}\x1b[38;2;${r};${g};${b}m${ch}\x1b[22m`;
91
95
  })
92
- .join("");
96
+ .join("") + "\x1b[0m";
97
+ }
98
+
99
+ function ansiToRgb(ansi: string): [number, number, number] {
100
+ const match = ansi.match(/^\x1b\[38;2;(\d+);(\d+);(\d+)m$/);
101
+ if (!match) throw new Error(`Shimmer requires truecolor theme colors, received ${JSON.stringify(ansi)}`);
102
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
93
103
  }
94
104
 
95
105
  /**
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes