@hank-warren/pi-statusline 0.7.2 → 0.7.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @hank-warren/pi-statusline
2
2
 
3
+ ## 0.7.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d0c46a5: Resolve `auth.json`, the usage cache and `statusline-settings.json` through Pi's agent directory (`PI_CODING_AGENT_DIR`) instead of a hardcoded `~/.pi/agent`. Behaviour is unchanged for a normal install; a session started with a scratch agent dir no longer reads the real credentials or writes the real usage cache. `engines.node` now states Pi's own floor, `>=22.19.0`.
8
+
3
9
  ## 0.7.2
4
10
 
5
11
  ### Patch Changes
@@ -2,7 +2,7 @@ export const CACHE_HIT_THRESHOLD = 0.96;
2
2
  export const CACHE_CELEBRATION_FRAME_INTERVAL_MS = 60;
3
3
  export const CACHE_CELEBRATION_DURATION_MS = 2_000;
4
4
 
5
- export interface CacheUsage {
5
+ interface CacheUsage {
6
6
  input: number;
7
7
  cacheRead: number;
8
8
  cacheWrite: number;
@@ -13,11 +13,11 @@ export interface CacheCelebrationSnapshot {
13
13
  frame: number;
14
14
  }
15
15
 
16
- export interface CacheCelebrationTarget {
16
+ interface CacheCelebrationTarget {
17
17
  start(percent: number): void;
18
18
  }
19
19
 
20
- export interface CacheCelebrationControllerOptions {
20
+ interface CacheCelebrationControllerOptions {
21
21
  frameIntervalMs?: number;
22
22
  durationMs?: number;
23
23
  now?: () => number;
@@ -7,7 +7,7 @@ import type { SettingsListTheme } from "@earendil-works/pi-tui";
7
7
  /** Percentage shown by the settings-menu preview badge. */
8
8
  export const PREVIEW_PERCENT = 96;
9
9
 
10
- export interface CelebrationPreviewOptions {
10
+ interface CelebrationPreviewOptions {
11
11
  frameIntervalMs?: number;
12
12
  schedule?: (callback: () => void, intervalMs: number) => unknown;
13
13
  cancel?: (handle: unknown) => void;
@@ -11,13 +11,13 @@ import type { StatuslinePalette } from "./themes.ts";
11
11
  const RESET = "\x1b[0m";
12
12
  const BOLD = "\x1b[1m";
13
13
 
14
- export interface Rgb {
14
+ interface Rgb {
15
15
  r: number;
16
16
  g: number;
17
17
  b: number;
18
18
  }
19
19
 
20
- export const fgCode = ({ r, g, b }: Rgb): string =>
20
+ const fgCode = ({ r, g, b }: Rgb): string =>
21
21
  `\x1b[38;2;${Math.round(r)};${Math.round(g)};${Math.round(b)}m`;
22
22
 
23
23
  /** Parse an SGR true-colour prefix back into channels; anything else reads as white. */
@@ -68,7 +68,7 @@ function hue(degrees: number): Rgb {
68
68
  }
69
69
 
70
70
  /** Colour every character of `badge` for one frame. */
71
- export type CelebrationStyle = (badge: string, frame: number, palette: StatuslinePalette) => string;
71
+ type CelebrationStyle = (badge: string, frame: number, palette: StatuslinePalette) => string;
72
72
 
73
73
  const uniform = (badge: string, colour: Rgb): string => `${BOLD}${fgCode(colour)}${badge}${RESET}`;
74
74
 
package/index.ts CHANGED
@@ -124,7 +124,7 @@ function renderRepository(
124
124
  return part;
125
125
  }
126
126
 
127
- export function renderCacheCelebrationLine(
127
+ function renderCacheCelebrationLine(
128
128
  summary: string,
129
129
  celebration: CacheCelebrationSnapshot,
130
130
  palette: StatuslinePalette = DEFAULT_PALETTE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hank-warren/pi-statusline",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Compact Pi footer statusline with Git/worktree context, token usage, and neon celebrations for exceptional prompt-cache hits.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "homepage": "https://github.com/hank-warren/pi-extensions/tree/main/packages/pi-statusline#readme",
25
25
  "engines": {
26
- "node": ">=18.0.0"
26
+ "node": ">=22.19.0"
27
27
  },
28
28
  "pi": {
29
29
  "extensions": [
package/redraw.ts CHANGED
@@ -33,7 +33,7 @@ export interface RedrawTarget {
33
33
  requestRender(force?: boolean): void;
34
34
  }
35
35
 
36
- export interface FullRedrawSchedulerOptions {
36
+ interface FullRedrawSchedulerOptions {
37
37
  minGapMs?: number;
38
38
  rowRefreshIntervalMs?: number;
39
39
  idleIntervalMs?: number;
package/settings-menu.ts CHANGED
@@ -23,7 +23,7 @@ export const ON = "on";
23
23
  export const OFF = "off";
24
24
  const TOGGLE_VALUES = [ON, OFF];
25
25
 
26
- export interface BooleanRow {
26
+ interface BooleanRow {
27
27
  id: BooleanSettingKey;
28
28
  label: string;
29
29
  description: string;
package/settings.ts CHANGED
@@ -2,6 +2,7 @@ import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { dirname, isAbsolute, join } from "node:path";
4
4
  import { pid } from "node:process";
5
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
5
6
  import {
6
7
  type CelebrationStyleName,
7
8
  DEFAULT_CELEBRATION_STYLE,
@@ -34,7 +35,7 @@ export interface StatuslineSettings extends Record<BooleanSettingKey, boolean> {
34
35
  repoAliases: Record<string, string>;
35
36
  }
36
37
 
37
- export function defaultWorktreeRoot(home: string = homedir()): string {
38
+ function defaultWorktreeRoot(home: string = homedir()): string {
38
39
  return join(home || homedir(), "repos", "worktrees");
39
40
  }
40
41
 
@@ -56,8 +57,17 @@ export function defaultSettings(home: string = homedir()): StatuslineSettings {
56
57
  };
57
58
  }
58
59
 
59
- export function defaultSettingsPath(home: string = homedir()): string {
60
- return join(home || homedir(), ".pi", "agent", "statusline-settings.json");
60
+ /**
61
+ * Where the settings live when the caller names no path.
62
+ *
63
+ * The agent dir, not the home dir: pi honours `PI_CODING_AGENT_DIR`, so a
64
+ * session running against a scratch agent dir must save its statusline settings
65
+ * there rather than into the host's real `~/.pi/agent`. `home` still shapes the
66
+ * settings' *content* (the worktree root default, `~` collapsing) — that is a
67
+ * different thing and keeps its own parameter.
68
+ */
69
+ export function defaultSettingsPath(): string {
70
+ return join(getAgentDir(), "statusline-settings.json");
61
71
  }
62
72
 
63
73
  /** Expand a leading `~` (and `$HOME`) against `home`; other paths are returned as-is. */
@@ -78,7 +88,7 @@ export function collapseHome(path: string, home: string = homedir()): string {
78
88
  return path.startsWith(`${base}/`) ? `~/${path.slice(base.length + 1)}` : path;
79
89
  }
80
90
 
81
- export interface WorktreeRootResult {
91
+ interface WorktreeRootResult {
82
92
  path?: string;
83
93
  error?: string;
84
94
  }
@@ -109,7 +119,7 @@ function normalizeAliases(value: unknown): Record<string, string> | undefined {
109
119
  return aliases;
110
120
  }
111
121
 
112
- export interface NormalizedSettings {
122
+ interface NormalizedSettings {
113
123
  settings: StatuslineSettings;
114
124
  /** Top-level keys this version does not know about, preserved on write. */
115
125
  extra: Record<string, unknown>;
@@ -225,7 +235,7 @@ export function serializeSettings(
225
235
  return out;
226
236
  }
227
237
 
228
- export interface SettingsStoreOptions {
238
+ interface SettingsStoreOptions {
229
239
  path?: string;
230
240
  home?: string;
231
241
  }
@@ -242,7 +252,7 @@ export class SettingsStore {
242
252
 
243
253
  constructor(options: SettingsStoreOptions = {}) {
244
254
  this.home = options.home ?? homedir();
245
- this.path = options.path ?? defaultSettingsPath(this.home);
255
+ this.path = options.path ?? defaultSettingsPath();
246
256
  this.current = defaultSettings(this.home);
247
257
  }
248
258
 
package/usage.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readFile, rename, writeFile } from "node:fs/promises";
3
- import { homedir } from "node:os";
4
3
  import { join } from "node:path";
5
4
  import { pid } from "node:process";
5
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
6
6
 
7
7
  /**
8
8
  * Remaining (not used) integer percents per provider window.
@@ -84,7 +84,7 @@ export const USAGE_RATE_LIMIT_BACKOFF_MS = 15 * 60_000;
84
84
  * process's fresh values appear within one tick instead of at the next turn.
85
85
  * Request volume is unchanged: both throttles still gate every fetch.
86
86
  */
87
- export const USAGE_TICK_INTERVAL_MS = 10_000;
87
+ const USAGE_TICK_INTERVAL_MS = 10_000;
88
88
  const FETCH_TIMEOUT_MS = 10_000;
89
89
  const ONE_DAY_SECONDS = 86_400;
90
90
 
@@ -283,7 +283,7 @@ type ProviderKey = "claude" | "codex";
283
283
  const PROVIDER_KEYS = ["claude", "codex"] as const;
284
284
 
285
285
  /** Provider ids whose additional logins (`${base}-${suffix}`) share a meter. */
286
- export const USAGE_BASE_PROVIDERS: Record<ProviderKey, string> = {
286
+ const USAGE_BASE_PROVIDERS: Record<ProviderKey, string> = {
287
287
  claude: "anthropic",
288
288
  codex: "openai-codex",
289
289
  };
@@ -295,7 +295,7 @@ const PROVIDER_REFRESH_INTERVAL_MS: Record<ProviderKey, number> = {
295
295
  };
296
296
 
297
297
  /** Credential id polled for each family. */
298
- export type UsageAccounts = Record<ProviderKey, string>;
298
+ type UsageAccounts = Record<ProviderKey, string>;
299
299
 
300
300
  /** A freshly fetched value together with the boundary it is valid until. */
301
301
  interface FetchedUsage<K extends ProviderKey> {
@@ -477,8 +477,11 @@ export class UsageTracker {
477
477
  private tickHandle: unknown;
478
478
 
479
479
  constructor(options: UsageTrackerOptions = {}) {
480
- this.authPath = options.authPath ?? join(homedir(), ".pi", "agent", "auth.json");
481
- this.cachePath = options.cachePath ?? join(homedir(), ".pi", "agent", "statusline-usage.json");
480
+ // getAgentDir(), not ~/.pi/agent: pi honours PI_CODING_AGENT_DIR, and a
481
+ // hardcoded home path made a session pointed at another agent dir read the
482
+ // wrong credentials and write its usage cache into the host's real one.
483
+ this.authPath = options.authPath ?? join(getAgentDir(), "auth.json");
484
+ this.cachePath = options.cachePath ?? join(getAgentDir(), "statusline-usage.json");
482
485
  this.fetchFn = options.fetchFn ?? ((url, init) => fetch(url, init));
483
486
  this.onChange = options.onChange;
484
487
  this.now = options.now ?? Date.now;
package/worktrees.ts CHANGED
@@ -29,7 +29,7 @@ interface WorktreeMetadata {
29
29
  branch: string;
30
30
  }
31
31
 
32
- export interface WorktreeTrackerHost {
32
+ interface WorktreeTrackerHost {
33
33
  exec(
34
34
  command: string,
35
35
  args: string[],