@narumitw/pi-statusline 0.49.15 โ†’ 0.50.0

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@narumitw/pi-statusline)](https://www.npmjs.com/package/@narumitw/pi-statusline) [![Pi extension](https://img.shields.io/badge/Pi-extension-blue)](https://pi.dev) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
4
4
 
5
- Add an opinionated Powerline-style footer that works without setup and keeps the most useful Pi, workspace, Git, usage, and time context visible as the terminal narrows.
5
+ Add a Powerline-style footer that works without setup and keeps important Pi, workspace, Git, usage, and time context visible as the terminal narrows.
6
6
 
7
7
  A representative uncolored layout:
8
8
 
@@ -14,19 +14,16 @@ A representative uncolored layout:
14
14
 
15
15
  - Works immediately with a balanced default for model, thinking, workspace, Git, context, activity, and time.
16
16
  - Removes lower-priority segments before important information is clipped.
17
- - Shows activity only while Pi is streaming or running tools.
17
+ - Shows when Pi is waiting for an extension UI prompt, streaming, or running tools.
18
18
  - Adds optional token, prompt-cache, provider usage, and cost details.
19
19
  - Offers three information levels, seven previewable palettes, and advanced custom layouts.
20
+ - Uses ANSI-256 palette colors when Pi's effective terminal capabilities disable true color.
20
21
  - Loads a generated split runtime to reduce Pi package startup work.
21
22
 
22
23
  > **Need more customization?**
23
- > See
24
- > [`pi-starship`](https://github.com/narumiruna/pi-extensions/tree/main/packages/pi-starship) ([npm](https://www.npmjs.com/package/@narumitw/pi-starship)).
25
- > It uses a
26
- > [Starship-inspired](https://starship.rs/) TOML format and style syntax for deeper control over layout, modules, and colors.
24
+ > See [`pi-starship`](https://github.com/narumiruna/pi-extensions/tree/main/packages/pi-starship) ([npm](https://www.npmjs.com/package/@narumitw/pi-starship)).
25
+ > It uses [Starship-inspired](https://starship.rs/) TOML and style syntax for deeper control over layout, modules, and colors.
27
26
  > Choose `pi-statusline` for practical defaults and quick setup.
28
- >
29
- > Do not enable both extensions at the same time because both own Pi's footer.
30
27
 
31
28
  ## ๐Ÿ“ฆ Install
32
29
 
@@ -47,9 +44,8 @@ npm --workspace @narumitw/pi-statusline run build
47
44
  pi -e ./packages/pi-statusline
48
45
  ```
49
46
 
50
- The package declares `dist/index.ts`, so an unbuilt local checkout must run the build before Pi loads the package directory.
51
-
52
- For the best result, use a terminal font that includes Powerline glyphs and emoji.
47
+ The package declares `dist/index.ts`, so build an unbuilt local checkout before Pi loads the package directory.
48
+ Install only from sources you trust because Pi extensions run with Pi's permissions.
53
49
 
54
50
  ## ๐Ÿš€ Quick start
55
51
 
@@ -69,15 +65,14 @@ Help
69
65
  | Menu item | What it does |
70
66
  | --- | --- |
71
67
  | **Appearance** | Preview palettes with Up/Down; Enter applies and Escape cancels |
72
- | **Information** | Preview and apply a curated set of segments |
68
+ | **Information** | Preview and apply a curated segment set |
73
69
  | **Advanced** | Open Custom layout or Edit settings JSON |
74
70
  | **Status** | Show the effective source, path, appearance, layout, and diagnostics |
75
71
  | **Help** | Show command and schema guidance |
76
72
 
77
73
  ### Information levels
78
74
 
79
- Selecting a level replaces only the `segments` array.
80
- Unknown and unrelated JSON fields are preserved.
75
+ Selecting a level replaces only `segments` and preserves unrelated JSON fields.
81
76
 
82
77
  | Level | Included segments |
83
78
  | --- | --- |
@@ -99,10 +94,10 @@ The `tools` segment takes no space while idle.
99
94
  | `/statusline help` | Show command and schema guidance |
100
95
 
101
96
  The direct `settings`, `status`, and `help` routes remain for compatibility.
102
- The root standard menu is TUI-only; Escape returns from Advanced or closes Main.
103
- RPC receives observable notifications instead of TUI-only controls.
97
+ The main menu is TUI-only; Escape returns from Advanced or closes the menu.
98
+ RPC receives notifications instead of TUI-only controls.
104
99
  Unknown subcommands and trailing arguments are rejected.
105
- The standard palette picker owns navigation and cleanup while pi-statusline still owns footer previews, settings, and rollback.
100
+ The standard palette picker owns navigation and cleanup; pi-statusline owns footer previews, settings, and rollback.
106
101
  The width-aware layout editor and JSON editor remain specialized UI.
107
102
 
108
103
  ## ๐Ÿ“ Runtime behavior
@@ -125,12 +120,14 @@ If the last remaining segment is itself wider than the row, that row renders emp
125
120
  - `cwd` uses Starship's directory presentation defaults: contract the home directory to `~`, contract to the Git repository root when available, then retain at most the last three path components.
126
121
  This changes display only; the configured segment list and Pi working directory are untouched.
127
122
  - Repository-root discovery is cached with Git status outside footer rendering; a failed root query falls back to home/path-component contraction without hiding the segment.
128
- - During active work, `tools` shows `๐Ÿ’ญ thinking` or `โš™ <tool>` with parallel counts.
123
+ - During active work, `tools` shows `โŒจ waiting for <kind>`, `๐Ÿ’ญ thinking`, or `โš™๏ธ <tool>` with parallel counts.
124
+ - A sanitized prompt title follows the prompt kind when available.
125
+ - Prompt waiting takes precedence without losing the underlying tool or streaming state, which returns when the prompt closes.
129
126
  - Activity disappears after the agent settles and resets across session replacement or shutdown.
130
127
  - Clean repositories show no Git counters.
131
128
  - Dirty counters are `โ‡ก` ahead, `โ‡ฃ` behind, `+` staged, `~` modified/deleted, `?` untracked, and `!`
132
129
  conflicts.
133
- - A linked GitHub PR appears with the branch when possible, avoiding a duplicate extension status.
130
+ - A linked or plain GitHub PR reference appears with the branch when possible, avoiding a duplicate extension status.
134
131
  - Context color changes to warning at 70% and error at 90%.
135
132
  - Git state is cached outside footer rendering and stale session results are ignored.
136
133
 
@@ -155,7 +152,7 @@ The extension uses one user-level file:
155
152
  ```
156
153
 
157
154
  There are no project or environment overrides.
158
- When the file is absent, pi-statusline uses its built-in defaults without creating the file or parent directory.
155
+ When the file is absent, pi-statusline uses built-in defaults without creating the file or its parent directory.
159
156
  The first successful settings save creates a complete editable document atomically.
160
157
  Malformed or unreadable settings are never overwritten.
161
158
  Settings reload on startup, `/reload`, and session replacement.
@@ -177,8 +174,8 @@ If both files exist, `pi-statusline.json` wins.
177
174
 
178
175
  All fields are optional in an existing document.
179
176
  Missing fields use defaults.
180
- Unknown fields produce a warning but are preserved by menu saves.
181
- Invalid recognized values block saving, leaving the previous file and live footer unchanged.
177
+ Menu saves warn about and preserve unknown fields.
178
+ Invalid recognized values block saving and leave the file and live footer unchanged.
182
179
 
183
180
  A compact customization example:
184
181
 
@@ -229,6 +226,7 @@ When `palettePreset` is `custom`, `palette` maps segment names to foreground/bac
229
226
  - Legacy string palettes such as `"palette": "ocean"` remain accepted.
230
227
  - Missing custom colors remain unstyled instead of inheriting Tokyo Night.
231
228
  - Adjacent segments with identical colors share one block; transitions use `๎‚ด`.
229
+ - Hex palette colors render as ANSI-256 when Pi's effective terminal capabilities disable true color.
232
230
 
233
231
  `segmentText` values must be single-line text without terminal control characters.
234
232
  Use `line_break` for another row rather than inserting a newline into a prefix or suffix.
@@ -260,7 +258,8 @@ The direction names the removed portion:
260
258
  Truncation runs after the built-in Claude/GPT shortening rules but before the configured model prefix and suffix.
261
259
  It changes display onlyโ€”the provider model ID is untouched.
262
260
  Terminal control sequences in model IDs are removed at render time, and unsafe configured symbols are rejected.
263
- An empty `truncationSymbol` truncates without a marker. pi-statusline treats model IDs as opaque strings and does not parse paths, repositories, GGUF suffixes, or quantization names.
261
+ An empty `truncationSymbol` truncates without a marker.
262
+ pi-statusline treats model IDs as opaque strings and does not parse paths, repositories, GGUF suffixes, or quantization names.
264
263
  At very narrow widths, the existing responsive priorities may still omit the model rather than overflow the terminal.
265
264
 
266
265
  ## ๐Ÿงฉ Advanced layout
@@ -280,7 +279,8 @@ Open **Advanced โ†’ Custom layout** when the curated levels are not enough.
280
279
  | Ctrl+C | Close the screen immediately, including from Move mode |
281
280
 
282
281
  The layout displays the effective Back key and keeps Ctrl+C available when Back is remapped.
283
- Every successful change saves and applies immediately; closing the screen does not roll it back.
282
+ Every successful change saves and applies immediately.
283
+ Closing the screen does not roll it back.
284
284
 
285
285
  Available data segments:
286
286
 
@@ -301,12 +301,11 @@ Manually authored leading/trailing breaks represent empty rows.
301
301
  ```
302
302
 
303
303
  An empty `segments` array hides the main powerline while extension statuses can still render.
304
- The extension intentionally has no variable or format language; use `pi-starship` when you need one.
305
304
 
306
305
  ## ๐Ÿ”Œ Extension statuses and icons
307
306
 
308
307
  Other extension statuses appear below the main powerline, wrap to terminal width, and are limited to five items.
309
- Icons resolve in this order:
308
+ Icons use this order:
310
309
 
311
310
  1. Exact configured raw key, such as `goal` or `foo:server`.
312
311
  2. Longest configured colon wildcard, such as `foo:*` or `foo:server:*`.
@@ -327,11 +326,17 @@ For interoperable extensions, prefer one aggregated key or a stable coexistence
327
326
  <extension-id>:<stable-slot>
328
327
  ```
329
328
 
330
- Put transient activity in the value and always clear the same complete key.
329
+ Put transient activity in the value, and clear the exact key that was set.
330
+
331
+ ## ๐Ÿšง Limitations
332
+
333
+ - The footer needs Powerline glyphs and emoji for its intended appearance.
334
+ - Pi does not arbitrate footer ownership, so another footer extension can replace pi-statusline.
335
+ - Custom layouts support ordered segments and line breaks, not a variable or format language.
331
336
 
332
337
  ## ๐Ÿ› ๏ธ Troubleshooting
333
338
 
334
- - **Powerline symbols look wrong:** use a font with Powerline glyphs; emoji support is also recommended.
339
+ - **Powerline symbols look wrong:** use a font with Powerline glyphs and emoji support.
335
340
  - **The footer reports settings warnings:** run `/statusline status`, then `/statusline settings` to fix invalid recognized fields.
336
341
  - **The footer appears to be replaced:** disable `pi-starship` or another extension that also calls Pi's `setFooter()`.
337
342
  - **A custom segment disappears on a narrow terminal:** check the responsive priority above or add an explicit `line_break`.
package/dist/index.ts CHANGED
@@ -16,6 +16,7 @@ import { homedir } from "node:os";
16
16
  import {
17
17
  getAgentDir as getAgentDir2
18
18
  } from "@earendil-works/pi-coding-agent";
19
+ import { getCapabilities } from "@earendil-works/pi-tui";
19
20
 
20
21
  // src/extension-status.ts
21
22
  import { existsSync, readFileSync } from "node:fs";
@@ -27,17 +28,21 @@ import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
27
28
  import { visibleWidth } from "@earendil-works/pi-tui";
28
29
 
29
30
  // src/ansi.ts
30
- function ansiStyle(text, colors) {
31
+ function ansiStyle(text, colors, trueColor = true) {
31
32
  const codes = [
32
- colors.fg ? truecolorCode("38", colors.fg) : void 0,
33
- colors.bg ? truecolorCode("48", colors.bg) : void 0
33
+ colors.fg ? colorCode("38", colors.fg, trueColor) : void 0,
34
+ colors.bg ? colorCode("48", colors.bg, trueColor) : void 0
34
35
  ].filter((code) => code !== void 0);
35
36
  if (codes.length === 0) return text;
36
37
  return `\x1B[${codes.join(";")}m${text}\x1B[0m`;
37
38
  }
38
- function truecolorCode(prefix, hex) {
39
+ function colorCode(prefix, hex, trueColor) {
39
40
  const { red, green, blue } = hexToRgb(hex);
40
- return `${prefix};2;${red};${green};${blue}`;
41
+ return trueColor ? `${prefix};2;${red};${green};${blue}` : `${prefix};5;${rgbToAnsi256(red, green, blue)}`;
42
+ }
43
+ function rgbToAnsi256(red, green, blue) {
44
+ const channels = [red, green, blue].map((value) => Math.round(value / 255 * 5));
45
+ return 16 + 36 * (channels[0] ?? 0) + 6 * (channels[1] ?? 0) + (channels[2] ?? 0);
41
46
  }
42
47
  function hexToRgb(hex) {
43
48
  const normalized = hex.replace(/^#/, "");
@@ -49,9 +54,9 @@ function hexToRgb(hex) {
49
54
  }
50
55
 
51
56
  // src/powerline.ts
52
- function renderPowerlineStatusline(width, items, config) {
57
+ function renderPowerlineStatusline(width, items, config, trueColor = true) {
53
58
  if (items.length === 0 || width <= 0) return "";
54
- return splitLines(items).map((segments) => fitPowerlineSegments(segments, width, config)).join("\n");
59
+ return splitLines(items).map((segments) => fitPowerlineSegments(segments, width, config, trueColor)).join("\n");
55
60
  }
56
61
  function splitLines(items) {
57
62
  const lines = [[]];
@@ -76,11 +81,11 @@ var SEGMENT_RETENTION_PRIORITY = {
76
81
  turn: 20,
77
82
  brand: 10
78
83
  };
79
- function fitPowerlineSegments(segments, width, config) {
84
+ function fitPowerlineSegments(segments, width, config, trueColor) {
80
85
  if (segments.length === 0) return "";
81
86
  const fitted = [...segments];
82
87
  while (fitted.length > 1) {
83
- const rendered2 = joinPowerlineSegments(fitted, config);
88
+ const rendered2 = joinPowerlineSegments(fitted, config, trueColor);
84
89
  if (visibleWidth(rendered2) <= width) return rendered2;
85
90
  let removalIndex = 0;
86
91
  for (let index = 1; index < fitted.length; index += 1) {
@@ -92,23 +97,25 @@ function fitPowerlineSegments(segments, width, config) {
92
97
  }
93
98
  fitted.splice(removalIndex, 1);
94
99
  }
95
- const rendered = joinPowerlineSegments(fitted, config);
100
+ const rendered = joinPowerlineSegments(fitted, config, trueColor);
96
101
  return visibleWidth(rendered) <= width ? rendered : "";
97
102
  }
98
- function powerlineExtensionSeparator(_theme, palettePreset = "tokyo-night") {
99
- return ansiStyle(" \u2022 ", { fg: resolvePreset(palettePreset).extensionSeparator });
103
+ function powerlineExtensionSeparator(_theme, palettePreset = "tokyo-night", trueColor = true) {
104
+ return ansiStyle(" \u2022 ", { fg: resolvePreset(palettePreset).extensionSeparator }, trueColor);
100
105
  }
101
- function joinPowerlineSegments(segments, config) {
106
+ function joinPowerlineSegments(segments, config, trueColor) {
102
107
  const preset = resolvePreset(config.palettePreset);
103
108
  const blocks = contiguousBlocks(segments, preset, config.palettePreset, config.palette);
104
- let line = ansiStyle("\u2591\u2592\u2593", { fg: preset.lead });
109
+ let line = ansiStyle("\u2591\u2592\u2593", { fg: preset.lead }, trueColor);
105
110
  for (const [index, block] of blocks.entries()) {
106
111
  const previous = index === 0 ? void 0 : blocks[index - 1]?.colors;
107
- if (previous) line += ansiStyle("\uE0B4", { fg: previous.bg, bg: block.colors.bg });
108
- line += ansiStyle(formatBlockText(block, config), block.colors);
112
+ if (previous) {
113
+ line += ansiStyle("\uE0B4", { fg: previous.bg, bg: block.colors.bg }, trueColor);
114
+ }
115
+ line += ansiStyle(formatBlockText(block, config), block.colors, trueColor);
109
116
  }
110
117
  const lastBlock = blocks.at(-1);
111
- if (lastBlock) line += ansiStyle("\uE0B4", { fg: lastBlock.colors.bg });
118
+ if (lastBlock) line += ansiStyle("\uE0B4", { fg: lastBlock.colors.bg }, trueColor);
112
119
  return line;
113
120
  }
114
121
  function contiguousBlocks(segments, preset, palettePreset, configuredPalette) {
@@ -161,11 +168,11 @@ var COMPATIBLE_STATUS_ICON_KEYS = {
161
168
  pisync: "sync"
162
169
  };
163
170
  var EMPTY_EXTENSION_STATUS_ICON_ALIASES = /* @__PURE__ */ new Map();
164
- function extensionStatusSeparator(config, theme) {
165
- return powerlineExtensionSeparator(theme, config.palettePreset);
171
+ function extensionStatusSeparator(config, theme, trueColor) {
172
+ return powerlineExtensionSeparator(theme, config.palettePreset, trueColor);
166
173
  }
167
- function formatExtensionStatuses(statuses, theme, config, runtime, hiddenKeys = /* @__PURE__ */ new Set()) {
168
- const separator = extensionStatusSeparator(config, theme);
174
+ function formatExtensionStatuses(statuses, theme, config, runtime, hiddenKeys = /* @__PURE__ */ new Set(), trueColor = true) {
175
+ const separator = extensionStatusSeparator(config, theme, trueColor);
169
176
  const visibleStatuses = [
170
177
  ...formatDuplicateExtensionStatus(runtime, theme),
171
178
  ...[...statuses.entries()].filter(
@@ -463,6 +470,7 @@ function formatCount(value) {
463
470
  }
464
471
 
465
472
  // src/render.ts
473
+ import { sliceByColumn, visibleWidth as visibleWidth2 } from "@earendil-works/pi-tui";
466
474
  import { sanitizeTerminalText as sanitizeTerminalText2 } from "@narumitw/pi-tui-kit/terminal-text";
467
475
 
468
476
  // src/directory.ts
@@ -539,7 +547,7 @@ function summarizeFooterUsage(entries) {
539
547
  // src/render.ts
540
548
  var GITHUB_PR_KEY = "github-pr";
541
549
  var GITHUB_PR_STATUS_KEYS = /* @__PURE__ */ new Set([GITHUB_PR_KEY]);
542
- function renderStatusline(width, ctx, footerData, _theme, config, runtime) {
550
+ function renderStatusline(width, ctx, footerData, _theme, config, runtime, trueColor = true) {
543
551
  if (width <= 0) return "";
544
552
  const usageSummary = summarizeFooterUsage(ctx.sessionManager.getEntries());
545
553
  const rows = [
@@ -564,9 +572,9 @@ function renderStatusline(width, ctx, footerData, _theme, config, runtime) {
564
572
  if (index > 0) segments.push({ name: LINE_BREAK_SEGMENT_NAME });
565
573
  segments.push(...row.segments);
566
574
  }
567
- return renderPowerlineStatusline(width, segments, config);
575
+ return renderPowerlineStatusline(width, segments, config, trueColor);
568
576
  }
569
- function renderExtensionStatusline(width, footerData, theme, config, runtime, mainLine) {
577
+ function renderExtensionStatusline(width, footerData, theme, config, runtime, mainLine, trueColor = true) {
570
578
  const statuses = footerData.getExtensionStatuses();
571
579
  const prContext = prContextFromStatuses(statuses);
572
580
  const rendersPrInline = prContext !== void 0 && mainLine.includes(prContext);
@@ -575,7 +583,8 @@ function renderExtensionStatusline(width, footerData, theme, config, runtime, ma
575
583
  theme,
576
584
  config,
577
585
  runtime,
578
- rendersPrInline ? GITHUB_PR_STATUS_KEYS : void 0
586
+ rendersPrInline ? GITHUB_PR_STATUS_KEYS : void 0,
587
+ trueColor
579
588
  );
580
589
  return wrapExtensionStatusline(status, width);
581
590
  }
@@ -701,12 +710,36 @@ function contextColor(percent) {
701
710
  if (percent >= 70) return "warning";
702
711
  return "success";
703
712
  }
713
+ var MAX_UI_PROMPT_TITLE_CODE_POINTS = 256;
714
+ var MAX_UI_PROMPT_TITLE_WIDTH = 40;
715
+ function boundUIPromptTitleLength(title) {
716
+ let end = 0;
717
+ let ellipsisEnd = 0;
718
+ let codePoints = 0;
719
+ while (end < title.length && codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) {
720
+ const codePoint = title.codePointAt(end) ?? 0;
721
+ end += codePoint > 65535 ? 2 : 1;
722
+ codePoints += 1;
723
+ if (codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) ellipsisEnd = end;
724
+ }
725
+ return end < title.length ? `${title.slice(0, ellipsisEnd)}\u2026` : title;
726
+ }
727
+ function formatUIPromptTitle(title) {
728
+ const safeTitle = title ? sanitizeTerminalText2(title).trim() : "";
729
+ const boundedTitle = boundUIPromptTitleLength(safeTitle);
730
+ if (visibleWidth2(boundedTitle) <= MAX_UI_PROMPT_TITLE_WIDTH) return boundedTitle;
731
+ return `${sliceByColumn(boundedTitle, 0, MAX_UI_PROMPT_TITLE_WIDTH - 1, true)}\u2026`;
732
+ }
704
733
  function formatToolActivity(runtime) {
734
+ if (runtime.uiPrompt) {
735
+ const title = formatUIPromptTitle(runtime.uiPrompt.title);
736
+ return `\u2328 waiting for ${runtime.uiPrompt.kind}${title ? ` \xB7 ${title}` : ""}`;
737
+ }
705
738
  const active = [...runtime.activeTools.entries()];
706
739
  if (active.length > 0) {
707
740
  const [name, count] = active[0] ?? ["tool", 1];
708
741
  const suffix = count > 1 ? `\xD7${count}` : active.length > 1 ? `+${active.length - 1}` : "";
709
- return `\u2699 ${name}${suffix}`;
742
+ return `\u2699\uFE0F ${name}${suffix}`;
710
743
  }
711
744
  return runtime.isStreaming ? "\u{1F4AD} thinking" : void 0;
712
745
  }
@@ -721,10 +754,15 @@ function prLinkFromStatuses(statuses) {
721
754
  }
722
755
  function prContextFromStatuses(statuses) {
723
756
  const value = statuses.get(GITHUB_PR_KEY);
757
+ if (!value) return void 0;
724
758
  const link = prLinkFromStatuses(statuses);
725
- if (!value || !link) return void 0;
726
- const state = compactPrState(value.replace(link, ""));
727
- return state ? `${link} \xB7 ${state}` : void 0;
759
+ const reference = link ?? plainPrReference(value);
760
+ if (!reference) return void 0;
761
+ const state = compactPrState(link ? value.replace(link, "") : value);
762
+ return state ? `${reference} \xB7 ${state}` : void 0;
763
+ }
764
+ function plainPrReference(value) {
765
+ return /^PR\s+(#\d+):/u.exec(value)?.[1];
728
766
  }
729
767
  function compactPrState(value) {
730
768
  if (/:\s*merged\s*$/.test(value)) return "merged";
@@ -927,10 +965,27 @@ function statusline(pi) {
927
965
  render(width) {
928
966
  if (!loaded) return [];
929
967
  const config = previewPalettePreset ? { ...loaded.config, palettePreset: previewPalettePreset } : loaded.config;
930
- const mainLine = renderStatusline(width, ctx, footerData, theme, config, runtime);
968
+ const trueColor = getCapabilities().trueColor;
969
+ const mainLine = renderStatusline(
970
+ width,
971
+ ctx,
972
+ footerData,
973
+ theme,
974
+ config,
975
+ runtime,
976
+ trueColor
977
+ );
931
978
  const lines = mainLine ? mainLine.split("\n") : [];
932
979
  lines.push(
933
- ...renderExtensionStatusline(width, footerData, theme, config, runtime, mainLine)
980
+ ...renderExtensionStatusline(
981
+ width,
982
+ footerData,
983
+ theme,
984
+ config,
985
+ runtime,
986
+ mainLine,
987
+ trueColor
988
+ )
934
989
  );
935
990
  return lines;
936
991
  }
@@ -975,6 +1030,7 @@ function statusline(pi) {
975
1030
  runtime.turnCount = 0;
976
1031
  runtime.activeTools.clear();
977
1032
  runtime.isStreaming = false;
1033
+ runtime.uiPrompt = void 0;
978
1034
  loaded = loadStatuslineSettingsForAgent(agentDir);
979
1035
  const settingsNotice = consumeStatuslineSettingsNotice();
980
1036
  if (settingsNotice) ctx.ui.notify(settingsNotice, "warning");
@@ -1001,6 +1057,7 @@ function statusline(pi) {
1001
1057
  runtime.gitStatus = void 0;
1002
1058
  runtime.activeTools.clear();
1003
1059
  runtime.isStreaming = false;
1060
+ runtime.uiPrompt = void 0;
1004
1061
  runtime.duplicateExtensions = [];
1005
1062
  runtime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES2;
1006
1063
  ctx.ui.setFooter(void 0);
@@ -1029,6 +1086,16 @@ function statusline(pi) {
1029
1086
  runtime.activeTools.clear();
1030
1087
  refresh();
1031
1088
  });
1089
+ pi.on("ui_prompt_start", (event, ctx) => {
1090
+ if (!ownsRuntime(ctx)) return;
1091
+ runtime.uiPrompt = { kind: event.kind, title: event.title };
1092
+ refresh();
1093
+ });
1094
+ pi.on("ui_prompt_end", (_event, ctx) => {
1095
+ if (!ownsRuntime(ctx)) return;
1096
+ runtime.uiPrompt = void 0;
1097
+ refresh();
1098
+ });
1032
1099
  pi.on("turn_start", (_event, ctx) => {
1033
1100
  if (!ownsRuntime(ctx)) return;
1034
1101
  runtime.turnCount += 1;
package/dist/index.ts.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/statusline.ts", "../src/extension-status.ts", "../src/powerline.ts", "../src/ansi.ts", "../src/git-status.ts", "../src/render.ts", "../src/directory.ts", "../src/usage.ts"],
4
- "sourcesContent": ["import { homedir } from \"node:os\";\nimport {\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\tgetAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\nimport { completeStatuslineArguments } from \"./command-contract.js\";\nimport type { StatuslineCommandOptions } from \"./commands.js\";\nimport {\n\tbuildExtensionStatusIconAliases,\n\ttype ExtensionStatusIconAliasMap,\n\tfindDuplicateExtensions,\n\treadInstalledExtensionPackages,\n} from \"./extension-status.js\";\nimport { type GitStatusSummary, gitStatusSummaryEqual, readGitStatus } from \"./git-status.js\";\nimport { type RuntimeState, renderExtensionStatusline, renderStatusline } from \"./render.js\";\nimport {\n\tconsumeStatuslineSettingsNotice,\n\ttype LoadedStatuslineSettings,\n\tloadStatuslineSettings,\n\tloadStatuslineSettingsForAgent,\n\tsettingsFilePath,\n} from \"./settings.js\";\nimport type { PalettePreset } from \"./types.js\";\n\nconst STATUSLINE_KEY = \"statusline\";\nconst GIT_STATUS_REFRESH_INTERVAL_MS = 30_000;\nconst GIT_STATUS_EVENT_DEBOUNCE_MS = 250;\nconst EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();\n\ntype StatuslineCommands = typeof import(\"./commands.js\");\nlet statuslineCommandsPromise: Promise<StatuslineCommands> | undefined;\n\nfunction loadStatuslineCommands(): Promise<StatuslineCommands> {\n\tif (!statuslineCommandsPromise) {\n\t\tstatuslineCommandsPromise = import(\"./commands.js\").catch((error) => {\n\t\t\tstatuslineCommandsPromise = undefined;\n\t\t\tthrow error;\n\t\t});\n\t}\n\treturn statuslineCommandsPromise;\n}\n\nexport default function statusline(pi: ExtensionAPI) {\n\tlet loaded: LoadedStatuslineSettings | undefined;\n\tlet previewPalettePreset: PalettePreset | undefined;\n\tlet activeSessionManager: ExtensionContext[\"sessionManager\"] | undefined;\n\tconst runtime: RuntimeState = {\n\t\tturnCount: 0,\n\t\tactiveTools: new Map(),\n\t\tisStreaming: false,\n\t\tthinkingLevel: \"off\",\n\t\tduplicateExtensions: [],\n\t\textensionStatusIconAliases: EMPTY_EXTENSION_STATUS_ICON_ALIASES,\n\t};\n\n\tlet sessionGeneration = 0;\n\tlet menuController = new AbortController();\n\tlet gitStatusRequestId = 0;\n\tlet activeGitStatusTarget: { cwd: string; generation: number } | undefined;\n\tlet gitStatusRefreshInFlight = false;\n\tlet gitStatusAbortController: AbortController | undefined;\n\tlet gitStatusDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\tlet pendingGitStatusRefresh: { cwd: string; generation: number; requestId: number } | undefined;\n\n\tconst refresh = () => runtime.requestRender?.();\n\tconst ownsRuntime = (ctx: ExtensionContext) => ctx.sessionManager === activeSessionManager;\n\n\tconst setGitStatus = (summary: GitStatusSummary | undefined) => {\n\t\tif (gitStatusSummaryEqual(runtime.gitStatus, summary)) return;\n\t\truntime.gitStatus = summary;\n\t\trefresh();\n\t};\n\n\tconst clearGitStatusDebounce = () => {\n\t\tif (!gitStatusDebounceTimer) return;\n\t\tclearTimeout(gitStatusDebounceTimer);\n\t\tgitStatusDebounceTimer = undefined;\n\t};\n\n\tconst abortGitStatusRefresh = (reason: string) => {\n\t\tgitStatusAbortController?.abort(new DOMException(reason, \"AbortError\"));\n\t};\n\n\tconst isActiveGitStatusTarget = (cwd: string, generation: number) =>\n\t\tactiveGitStatusTarget?.cwd === cwd &&\n\t\tactiveGitStatusTarget.generation === generation &&\n\t\tgeneration === sessionGeneration;\n\n\tconst isCurrentGitStatusRequest = (cwd: string, generation: number, requestId: number) =>\n\t\tisActiveGitStatusTarget(cwd, generation) && requestId === gitStatusRequestId;\n\n\tconst runGitStatusRefresh = (cwd: string, generation: number, requestId: number) => {\n\t\tif (!isCurrentGitStatusRequest(cwd, generation, requestId)) return;\n\t\tif (gitStatusRefreshInFlight) {\n\t\t\tpendingGitStatusRefresh = { cwd, generation, requestId };\n\t\t\treturn;\n\t\t}\n\n\t\tgitStatusRefreshInFlight = true;\n\t\tconst abortController = new AbortController();\n\t\tgitStatusAbortController = abortController;\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst summary = await readGitStatus(pi, cwd, abortController.signal);\n\t\t\t\tif (isCurrentGitStatusRequest(cwd, generation, requestId)) setGitStatus(summary);\n\t\t\t} catch {\n\t\t\t\tif (isCurrentGitStatusRequest(cwd, generation, requestId)) setGitStatus(undefined);\n\t\t\t} finally {\n\t\t\t\tgitStatusRefreshInFlight = false;\n\t\t\t\tif (gitStatusAbortController === abortController) gitStatusAbortController = undefined;\n\t\t\t\tconst pending = pendingGitStatusRefresh;\n\t\t\t\tpendingGitStatusRefresh = undefined;\n\t\t\t\tif (pending) runGitStatusRefresh(pending.cwd, pending.generation, pending.requestId);\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst refreshGitStatus = (cwd: string, generation = sessionGeneration) => {\n\t\tif (!isActiveGitStatusTarget(cwd, generation)) return;\n\t\trunGitStatusRefresh(cwd, generation, ++gitStatusRequestId);\n\t};\n\n\tconst scheduleGitStatusRefresh = (cwd: string, generation = sessionGeneration) => {\n\t\tif (!isActiveGitStatusTarget(cwd, generation)) return;\n\t\tconst requestId = ++gitStatusRequestId;\n\t\tclearGitStatusDebounce();\n\t\tgitStatusDebounceTimer = setTimeout(() => {\n\t\t\tgitStatusDebounceTimer = undefined;\n\t\t\trunGitStatusRefresh(cwd, generation, requestId);\n\t\t}, GIT_STATUS_EVENT_DEBOUNCE_MS);\n\t};\n\n\tconst scheduleGitStatusRefreshForContext = (ctx: ExtensionContext) => {\n\t\tif (!activeGitStatusTarget || activeGitStatusTarget.cwd !== ctx.cwd) return;\n\t\tscheduleGitStatusRefresh(activeGitStatusTarget.cwd, activeGitStatusTarget.generation);\n\t};\n\n\tconst installFooter = (ctx: ExtensionContext) => {\n\t\tconst generation = ++sessionGeneration;\n\t\tmenuController.abort(new DOMException(\"Statusline session context replaced\", \"AbortError\"));\n\t\tmenuController = new AbortController();\n\t\tconst cwd = ctx.cwd;\n\t\tactiveSessionManager = ctx.sessionManager;\n\t\truntime.homeDir = homedir();\n\t\tpreviewPalettePreset = undefined;\n\t\tabortGitStatusRefresh(\"Statusline session context replaced\");\n\t\tclearGitStatusDebounce();\n\t\tactiveGitStatusTarget = ctx.mode === \"tui\" ? { cwd, generation } : undefined;\n\t\truntime.gitStatus = undefined;\n\t\truntime.duplicateExtensions = [];\n\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\tctx.ui.setStatus(STATUSLINE_KEY, undefined);\n\t\tif (!activeGitStatusTarget || !loaded) return;\n\t\tconst installedPackages = readInstalledExtensionPackages(cwd);\n\t\truntime.duplicateExtensions = findDuplicateExtensions(installedPackages);\n\t\truntime.extensionStatusIconAliases = buildExtensionStatusIconAliases(installedPackages);\n\t\tctx.ui.setFooter((tui, theme, footerData) => {\n\t\t\truntime.requestRender = () => tui.requestRender();\n\n\t\t\tconst refreshFooterGitStatus = () => refreshGitStatus(cwd, generation);\n\t\t\tconst branchUnsubscribe = footerData.onBranchChange(() => {\n\t\t\t\truntime.gitStatus = undefined;\n\t\t\t\tabortGitStatusRefresh(\"Statusline Git branch changed\");\n\t\t\t\tclearGitStatusDebounce();\n\t\t\t\trefreshFooterGitStatus();\n\t\t\t\ttui.requestRender();\n\t\t\t});\n\t\t\tconst clock = setInterval(() => {\n\t\t\t\tclearGitStatusDebounce();\n\t\t\t\trefreshFooterGitStatus();\n\t\t\t\ttui.requestRender();\n\t\t\t}, GIT_STATUS_REFRESH_INTERVAL_MS);\n\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\tbranchUnsubscribe();\n\t\t\t\t\tclearInterval(clock);\n\t\t\t\t\tif (isActiveGitStatusTarget(cwd, generation)) {\n\t\t\t\t\t\tactiveGitStatusTarget = undefined;\n\t\t\t\t\t\tabortGitStatusRefresh(\"Statusline footer disposed\");\n\t\t\t\t\t\tclearGitStatusDebounce();\n\t\t\t\t\t\tpendingGitStatusRefresh = undefined;\n\t\t\t\t\t\truntime.gitStatus = undefined;\n\t\t\t\t\t\truntime.duplicateExtensions = [];\n\t\t\t\t\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\t\t\t\t\truntime.requestRender = undefined;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tinvalidate() {},\n\t\t\t\trender(width: number): string[] {\n\t\t\t\t\tif (!loaded) return [];\n\t\t\t\t\tconst config = previewPalettePreset\n\t\t\t\t\t\t? { ...loaded.config, palettePreset: previewPalettePreset }\n\t\t\t\t\t\t: loaded.config;\n\t\t\t\t\tconst mainLine = renderStatusline(width, ctx, footerData, theme, config, runtime);\n\t\t\t\t\tconst lines = mainLine ? mainLine.split(\"\\n\") : [];\n\t\t\t\t\tlines.push(\n\t\t\t\t\t\t...renderExtensionStatusline(width, footerData, theme, config, runtime, mainLine),\n\t\t\t\t\t);\n\t\t\t\t\treturn lines;\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\t\trefreshGitStatus(cwd, generation);\n\t};\n\n\tconst agentDir = getAgentDir();\n\tconst configPath = settingsFilePath(agentDir);\n\tconst commandOptions: StatuslineCommandOptions = {\n\t\tsettingsPath: configPath,\n\t\tgetLoaded: () => loaded ?? loadStatuslineSettings(configPath),\n\t\tgetMenuOwner: () => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\treturn {\n\t\t\t\tsignal: menuController.signal,\n\t\t\t\tisCurrent: () => generation === sessionGeneration && !menuController.signal.aborted,\n\t\t\t};\n\t\t},\n\t\tapply(next, ctx) {\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tpreviewPalettePreset = undefined;\n\t\t\tloaded = next;\n\t\t\trefresh();\n\t\t},\n\t\tpreview(palettePreset, ctx) {\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tpreviewPalettePreset = palettePreset;\n\t\t\trefresh();\n\t\t},\n\t};\n\tpi.registerCommand(\"statusline\", {\n\t\tdescription: \"Open or inspect the statusline settings\",\n\t\tgetArgumentCompletions: completeStatuslineArguments,\n\t\thandler: async (args, ctx) => {\n\t\t\tconst commands = await loadStatuslineCommands();\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tawait commands.handleStatuslineCommand(args, ctx, commandOptions);\n\t\t},\n\t});\n\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\truntime.turnCount = 0;\n\t\truntime.activeTools.clear();\n\t\truntime.isStreaming = false;\n\t\tloaded = loadStatuslineSettingsForAgent(agentDir);\n\t\tconst settingsNotice = consumeStatuslineSettingsNotice();\n\t\tif (settingsNotice) ctx.ui.notify(settingsNotice, \"warning\");\n\t\tif (loaded.diagnostics.length > 0) {\n\t\t\tctx.ui.notify(formatSettingsDiagnostics(loaded), \"warning\");\n\t\t}\n\t\truntime.thinkingLevel = pi.getThinkingLevel();\n\t\tinstallFooter(ctx);\n\t});\n\n\tpi.on(\"session_tree\", (_event, ctx) => {\n\t\tinstallFooter(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tsessionGeneration += 1;\n\t\tmenuController.abort(new DOMException(\"Statusline session shut down\", \"AbortError\"));\n\t\tactiveSessionManager = undefined;\n\t\tpreviewPalettePreset = undefined;\n\t\tactiveGitStatusTarget = undefined;\n\t\tabortGitStatusRefresh(\"Statusline session shut down\");\n\t\tclearGitStatusDebounce();\n\t\tpendingGitStatusRefresh = undefined;\n\t\truntime.gitStatus = undefined;\n\t\truntime.activeTools.clear();\n\t\truntime.isStreaming = false;\n\t\truntime.duplicateExtensions = [];\n\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\tctx.ui.setFooter(undefined);\n\t\tctx.ui.setStatus(STATUSLINE_KEY, undefined);\n\t\truntime.requestRender = undefined;\n\t});\n\n\tpi.on(\"model_select\", () => refresh());\n\n\tpi.on(\"thinking_level_select\", (event) => {\n\t\truntime.thinkingLevel = event.level;\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_start\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.isStreaming = true;\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_end\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.activeTools.clear();\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_settled\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.isStreaming = false;\n\t\truntime.activeTools.clear();\n\t\trefresh();\n\t});\n\n\tpi.on(\"turn_start\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.turnCount += 1;\n\t\truntime.isStreaming = true;\n\t\trefresh();\n\t});\n\n\tpi.on(\"turn_end\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"tool_execution_start\", (event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tconst currentCount = runtime.activeTools.get(event.toolName) ?? 0;\n\t\truntime.activeTools.set(event.toolName, currentCount + 1);\n\t\trefresh();\n\t});\n\n\tpi.on(\"tool_execution_end\", (event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tconst currentCount = runtime.activeTools.get(event.toolName) ?? 0;\n\t\tif (currentCount <= 1) runtime.activeTools.delete(event.toolName);\n\t\telse runtime.activeTools.set(event.toolName, currentCount - 1);\n\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n}\n\nfunction formatSettingsDiagnostics(loaded: LoadedStatuslineSettings): string {\n\tconst details = loaded.diagnostics.slice(0, 5).map((item) => item.message);\n\tconst remaining = loaded.diagnostics.length - details.length;\n\treturn [\n\t\t`pi-statusline settings: ${details.join(\"; \")}`,\n\t\t...(remaining > 0 ? [`+${remaining} more`] : []),\n\t].join(\" \");\n}\n\nexport {\n\tbuildExtensionStatusIconAliases,\n\ttype ExtensionStatusIconAliasMap,\n\textensionColor,\n\tformatExtensionStatus,\n\tnpmPackageName,\n\tsimplifyExtensionStatusText,\n\tsplitExtensionStatusIcon,\n\tstripExtensionStatusPrefix,\n\twrapExtensionStatusline,\n} from \"./extension-status.js\";\nexport {\n\tformatGitBranchText,\n\tformatGitBranchValue,\n\tformatGitStatusSummary,\n\ttype GitStatusSummary,\n\tparseGitRoot,\n\tparseGitStatusPorcelain,\n\treadGitStatus,\n} from \"./git-status.js\";\nexport {\n\tcontextColor,\n\tformatCount,\n\tformatToolActivity,\n\tprContextFromStatuses,\n\tprLinkFromStatuses,\n\tshortenModel,\n} from \"./render.js\";\nexport { normalizeStatuslineSettings, readStatuslineSettings } from \"./settings.js\";\n", "import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { getAgentDir, type Theme, type ThemeColor } from \"@earendil-works/pi-coding-agent\";\nimport { wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport { powerlineExtensionSeparator } from \"./powerline.js\";\nimport { DEFAULT_EXTENSION_STATUS_ICONS } from \"./settings.js\";\nimport type { StatuslineConfig } from \"./types.js\";\n\nexport type ExtensionStatusIconAliasMap = ReadonlyMap<string, readonly string[]>;\nexport interface ExtensionStatusRuntime {\n\tduplicateExtensions: string[];\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap;\n}\n\nconst STATUSLINE_KEY = \"statusline\";\nconst COMPATIBLE_STATUS_ICON_KEYS: Readonly<Record<string, string>> = {\n\tretry: \"unknown-error-retry\",\n\tsync: \"pisync\",\n\t\"unknown-error-retry\": \"retry\",\n\tpisync: \"sync\",\n};\nconst EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();\nfunction extensionStatusSeparator(config: StatuslineConfig, theme: Theme): string {\n\treturn powerlineExtensionSeparator(theme, config.palettePreset);\n}\n\nexport function formatExtensionStatuses(\n\tstatuses: ReadonlyMap<string, string>,\n\ttheme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: ExtensionStatusRuntime,\n\thiddenKeys: ReadonlySet<string> = new Set(),\n): string {\n\tconst separator = extensionStatusSeparator(config, theme);\n\tconst visibleStatuses = [\n\t\t...formatDuplicateExtensionStatus(runtime, theme),\n\t\t...[...statuses.entries()]\n\t\t\t.filter(\n\t\t\t\t([key, value]) => key !== STATUSLINE_KEY && !hiddenKeys.has(key) && value.trim().length > 0,\n\t\t\t)\n\t\t\t.map(([key, value]) =>\n\t\t\t\tformatExtensionStatus(key, value, theme, config, runtime.extensionStatusIconAliases),\n\t\t\t),\n\t].slice(0, 5);\n\n\treturn visibleStatuses.join(separator);\n}\n\nexport function formatExtensionStatus(\n\tkey: string,\n\tvalue: string,\n\ttheme: Theme,\n\tconfig: Pick<StatuslineConfig, \"extensionStatusIcons\">,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap = EMPTY_EXTENSION_STATUS_ICON_ALIASES,\n): string {\n\tconst status = splitExtensionStatusIcon(stripExtensionStatusPrefix(key, value));\n\tconst text = simplifyExtensionStatusText(status.text);\n\tconst color = extensionColor(key, value);\n\tconst textColor = color === \"warning\" ? \"warning\" : \"muted\";\n\tconst icon = extensionStatusIcon(\n\t\tkey,\n\t\tstatus.icon,\n\t\tconfig.extensionStatusIcons,\n\t\textensionStatusIconAliases,\n\t);\n\tconst renderedText = theme.fg(textColor, text);\n\treturn icon ? `${theme.fg(color, icon)} ${renderedText}` : renderedText;\n}\n\nfunction extensionStatusIcon(\n\tkey: string,\n\tleadingIcon: string | undefined,\n\tconfiguredIcons: Record<string, string>,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap,\n) {\n\tif (Object.hasOwn(configuredIcons, key)) return configuredIcons[key];\n\tconst namespaceIcon = configuredNamespaceIcon(key, configuredIcons);\n\tif (namespaceIcon !== undefined) return namespaceIcon;\n\tconst compatibleKey = COMPATIBLE_STATUS_ICON_KEYS[key];\n\tif (compatibleKey && Object.hasOwn(configuredIcons, compatibleKey)) {\n\t\treturn configuredIcons[compatibleKey];\n\t}\n\tfor (const alias of extensionStatusAliasesForKey(key, extensionStatusIconAliases)) {\n\t\tif (Object.hasOwn(configuredIcons, alias)) return configuredIcons[alias];\n\t}\n\treturn leadingIcon ?? DEFAULT_EXTENSION_STATUS_ICONS[key] ?? \"\uD83D\uDD0C\";\n}\n\nfunction configuredNamespaceIcon(\n\tkey: string,\n\tconfiguredIcons: Readonly<Record<string, string>>,\n): string | undefined {\n\tlet match: { baseLength: number; icon: string } | undefined;\n\tfor (const [selector, icon] of Object.entries(configuredIcons)) {\n\t\tif (!selector.endsWith(\":*\")) continue;\n\t\tconst base = selector.slice(0, -2);\n\t\tif (!base || !key.startsWith(`${base}:`)) continue;\n\t\tif (!match || base.length > match.baseLength) match = { baseLength: base.length, icon };\n\t}\n\treturn match?.icon;\n}\n\nfunction extensionStatusAliasesForKey(\n\tkey: string,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap,\n): readonly string[] {\n\tfor (const [statusBase, aliases] of extensionStatusIconAliases) {\n\t\tif (statusKeyMatchesStatusBase(key, statusBase)) return aliases;\n\t}\n\treturn [];\n}\n\nfunction statusKeyMatchesStatusBase(key: string, statusBase: string): boolean {\n\treturn key === statusBase || key.startsWith(`${statusBase}:`) || key.startsWith(`${statusBase}/`);\n}\n\nexport function wrapExtensionStatusline(status: string, width: number): string[] {\n\tif (!status || width <= 0) return [];\n\treturn wrapTextWithAnsi(status, width);\n}\n\nfunction formatDuplicateExtensionStatus(runtime: ExtensionStatusRuntime, theme: Theme): string[] {\n\tif (runtime.duplicateExtensions.length === 0) return [];\n\tconst names = runtime.duplicateExtensions.slice(0, 2).join(\", \");\n\tconst suffix =\n\t\truntime.duplicateExtensions.length > 2 ? ` +${runtime.duplicateExtensions.length - 2}` : \"\";\n\treturn [`${theme.fg(\"warning\", \"\u26A0\uFE0F\")} ${theme.fg(\"warning\", `dup ${names}${suffix}`)}`];\n}\n\nexport function splitExtensionStatusIcon(value: string): { icon?: string; text: string } {\n\tconst trimmed = value.trim();\n\tconst [firstToken, ...restTokens] = trimmed.split(/\\s+/);\n\tif (firstToken && isEmojiOnlyToken(firstToken)) {\n\t\treturn { icon: firstToken, text: restTokens.join(\" \") };\n\t}\n\treturn { text: trimmed };\n}\n\nfunction isEmojiOnlyToken(value: string): boolean {\n\treturn /^(?=.*(?:\\p{Extended_Pictographic}|\\p{Regional_Indicator}|[0-9#*]\\ufe0f?\\u20e3))(?:\\p{Extended_Pictographic}|\\p{Emoji_Modifier}|\\p{Regional_Indicator}|\\u200d|\\ufe0f|[0-9#*]\\ufe0f?\\u20e3)+$/u.test(\n\t\tvalue,\n\t);\n}\n\nexport function extensionColor(key: string, value: string): ThemeColor {\n\tconst normalized = `${key} ${value}`.toLowerCase();\n\tif (/missing|error|fail|conflict|duplicate|unavailable/.test(normalized)) return \"warning\";\n\tif (normalized.includes(\"codex\")) return \"accent\";\n\tif (/ready|active|running|enabled|awake|ok/.test(normalized)) return \"success\";\n\treturn \"muted\";\n}\n\nexport function stripExtensionStatusPrefix(key: string, value: string): string {\n\treturn value.trim().replace(new RegExp(`^${escapeRegExp(key)}\\\\s*:\\\\s*`, \"iu\"), \"\");\n}\n\nexport function simplifyExtensionStatusText(value: string): string {\n\treturn value\n\t\t.trim()\n\t\t.replace(/\\bready\\b/giu, \"\u2713\")\n\t\t.replace(/\\bmissing\\b/giu, \"\u2717\")\n\t\t.replace(/,\\s*/g, \" \")\n\t\t.replace(/\\s+\\([^)]*\\)\\s*$/, \"\")\n\t\t.replace(/\\s+/g, \" \");\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\ninterface InstalledExtensionPackage {\n\tpackageName: string;\n\tsource: string;\n\tidentity: string;\n}\n\nexport function readInstalledExtensionPackages(cwd: string): InstalledExtensionPackage[] {\n\tconst packages: InstalledExtensionPackage[] = [];\n\tconst settingsFiles = extensionSettingsFiles(cwd);\n\n\tfor (const settingsFile of settingsFiles) {\n\t\tconst baseDirectory = dirname(settingsFile);\n\t\tfor (const rawSource of readPackageSources(settingsFile)) {\n\t\t\tconst source = rawSource.trim();\n\t\t\tif (!source) continue;\n\t\t\tconst packageName = packageNameForSource(source, baseDirectory);\n\t\t\tif (!packageName) continue;\n\t\t\tpackages.push({ packageName, source, identity: sourceIdentity(source, baseDirectory) });\n\t\t}\n\t}\n\n\treturn packages;\n}\n\nfunction extensionSettingsFiles(cwd: string): string[] {\n\treturn [join(getAgentDir(), \"settings.json\"), join(cwd, \".pi\", \"settings.json\")].filter((file) =>\n\t\texistsSync(file),\n\t);\n}\n\nexport function findDuplicateExtensions(\n\tinstalledPackages: readonly InstalledExtensionPackage[],\n): string[] {\n\tconst sourcesByPackage = new Map<string, Set<string>>();\n\n\tfor (const extensionPackage of installedPackages) {\n\t\tconst sources = sourcesByPackage.get(extensionPackage.packageName) ?? new Set<string>();\n\t\tsources.add(extensionPackage.identity);\n\t\tsourcesByPackage.set(extensionPackage.packageName, sources);\n\t}\n\n\treturn [...sourcesByPackage.entries()]\n\t\t.filter(([, sources]) => sources.size > 1)\n\t\t.map(([packageName]) => packageName.replace(/^@[^/]+\\//, \"\").replace(/^pi-/, \"\"));\n}\n\nexport function buildExtensionStatusIconAliases(\n\tinstalledPackages: readonly { packageName: string; source?: string }[],\n): Map<string, string[]> {\n\tconst packageAliasesByStatusBase = new Map<string, Map<string, string[]>>();\n\n\tfor (const extensionPackage of installedPackages) {\n\t\tconst candidate = extensionStatusIconAliasCandidate(\n\t\t\textensionPackage.packageName,\n\t\t\textensionPackage.source,\n\t\t);\n\t\tif (!candidate) continue;\n\t\tconst aliasesByPackage =\n\t\t\tpackageAliasesByStatusBase.get(candidate.statusBase) ?? new Map<string, string[]>();\n\t\tconst existingAliases = aliasesByPackage.get(extensionPackage.packageName) ?? [];\n\t\taliasesByPackage.set(\n\t\t\textensionPackage.packageName,\n\t\t\tuniqueStrings([...existingAliases, ...candidate.aliases]),\n\t\t);\n\t\tpackageAliasesByStatusBase.set(candidate.statusBase, aliasesByPackage);\n\t}\n\n\tconst aliases = new Map<string, string[]>();\n\tfor (const [statusBase, aliasesByPackage] of packageAliasesByStatusBase) {\n\t\tif (aliasesByPackage.size === 1)\n\t\t\taliases.set(statusBase, [...aliasesByPackage.values()][0] ?? []);\n\t}\n\treturn aliases;\n}\n\nfunction extensionStatusIconAliasCandidate(\n\tpackageName: string,\n\tsource?: string,\n): { statusBase: string; aliases: string[] } | undefined {\n\tconst packageBase = packageBaseName(packageName);\n\tconst statusBase = statusBaseFromPackageBase(packageBase);\n\tif (!statusBase) return undefined;\n\n\tconst sourceAliases = source?.startsWith(\"npm:\") ? [source, `npm:${npmPackageName(source)}`] : [];\n\treturn {\n\t\tstatusBase,\n\t\taliases: uniqueStrings([...sourceAliases, packageName, packageBase, statusBase]),\n\t};\n}\n\nfunction packageBaseName(packageName: string): string {\n\tconst slashIndex = packageName.lastIndexOf(\"/\");\n\treturn slashIndex === -1 ? packageName : packageName.slice(slashIndex + 1);\n}\n\nfunction statusBaseFromPackageBase(packageBase: string): string {\n\treturn packageBase.startsWith(\"pi-\") && packageBase.length > \"pi-\".length\n\t\t? packageBase.slice(\"pi-\".length)\n\t\t: packageBase;\n}\n\nfunction uniqueStrings(values: readonly string[]): string[] {\n\treturn [...new Set(values.filter((value) => value.length > 0))];\n}\n\nfunction readPackageSources(settingsFile: string): string[] {\n\ttry {\n\t\tconst settings = JSON.parse(readFileSync(settingsFile, \"utf8\")) as { packages?: unknown[] };\n\t\treturn (settings.packages ?? [])\n\t\t\t.map((entry) => {\n\t\t\t\tif (typeof entry === \"string\") return entry;\n\t\t\t\tif (\n\t\t\t\t\tentry &&\n\t\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\t\ttypeof (entry as { source?: unknown }).source === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (entry as { source: string }).source;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter((source): source is string => source !== undefined);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction packageNameForSource(source: string, baseDirectory: string): string | undefined {\n\tif (source.startsWith(\"npm:\")) return npmPackageName(source);\n\tconst packageJson = join(resolveSourcePath(source, baseDirectory), \"package.json\");\n\ttry {\n\t\tconst packageData = JSON.parse(readFileSync(packageJson, \"utf8\")) as { name?: unknown };\n\t\treturn typeof packageData.name === \"string\" ? packageData.name : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function npmPackageName(source: string): string {\n\tconst spec = source.slice(\"npm:\".length);\n\tif (spec.startsWith(\"@\")) return spec.split(\"@\").slice(0, 2).join(\"@\");\n\treturn spec.split(\"@\")[0] ?? spec;\n}\n\nfunction sourceIdentity(source: string, baseDirectory: string): string {\n\tif (source.startsWith(\"npm:\")) return `npm:${npmPackageName(source)}`;\n\treturn resolveSourcePath(source, baseDirectory);\n}\n\nfunction resolveSourcePath(source: string, baseDirectory: string): string {\n\treturn isAbsolute(source) ? source : resolve(baseDirectory, source);\n}\n", "import type { Theme } from \"@earendil-works/pi-coding-agent\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { ansiStyle } from \"./ansi.js\";\nimport { resolvePreset } from \"./presets/index.js\";\nimport type { BlockColors, PowerlinePreset } from \"./presets/types.js\";\nimport {\n\tLINE_BREAK_SEGMENT_NAME,\n\ttype PalettePreset,\n\ttype PowerlineBlockName,\n\ttype RenderItem,\n\ttype RenderSegment,\n\ttype SegmentPalette,\n\ttype SeparatorName,\n\ttype StatuslineConfig,\n} from \"./types.js\";\n\ninterface PowerlineBlock {\n\tbaseBlock: PowerlineBlockName;\n\tcolors: BlockColors;\n\tsegments: RenderSegment[];\n}\n\nexport function renderPowerlineStatusline(\n\twidth: number,\n\titems: RenderItem[],\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n): string {\n\tif (items.length === 0 || width <= 0) return \"\";\n\treturn splitLines(items)\n\t\t.map((segments) => fitPowerlineSegments(segments, width, config))\n\t\t.join(\"\\n\");\n}\n\nfunction splitLines(items: RenderItem[]): RenderSegment[][] {\n\tconst lines: RenderSegment[][] = [[]];\n\tfor (const item of items) {\n\t\tif (item.name === LINE_BREAK_SEGMENT_NAME) lines.push([]);\n\t\telse lines.at(-1)?.push(item);\n\t}\n\treturn lines;\n}\n\nconst SEGMENT_RETENTION_PRIORITY: Readonly<Record<RenderSegment[\"name\"], number>> = {\n\tcontext: 120,\n\tmodel: 110,\n\tbranch: 100,\n\ttools: 90,\n\tcwd: 80,\n\tthinking: 70,\n\tcost: 60,\n\tprovider: 50,\n\tcache: 45,\n\ttokens: 40,\n\ttime: 30,\n\tturn: 20,\n\tbrand: 10,\n};\n\nfunction fitPowerlineSegments(\n\tsegments: readonly RenderSegment[],\n\twidth: number,\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n): string {\n\tif (segments.length === 0) return \"\";\n\tconst fitted = [...segments];\n\twhile (fitted.length > 1) {\n\t\tconst rendered = joinPowerlineSegments(fitted, config);\n\t\tif (visibleWidth(rendered) <= width) return rendered;\n\t\tlet removalIndex = 0;\n\t\tfor (let index = 1; index < fitted.length; index += 1) {\n\t\t\tconst candidate = fitted[index];\n\t\t\tconst current = fitted[removalIndex];\n\t\t\tif (\n\t\t\t\tcandidate &&\n\t\t\t\tcurrent &&\n\t\t\t\tSEGMENT_RETENTION_PRIORITY[candidate.name] < SEGMENT_RETENTION_PRIORITY[current.name]\n\t\t\t) {\n\t\t\t\tremovalIndex = index;\n\t\t\t}\n\t\t}\n\t\tfitted.splice(removalIndex, 1);\n\t}\n\tconst rendered = joinPowerlineSegments(fitted, config);\n\treturn visibleWidth(rendered) <= width ? rendered : \"\";\n}\n\nexport function powerlineExtensionSeparator(\n\t_theme: Theme,\n\tpalettePreset: PalettePreset = \"tokyo-night\",\n): string {\n\treturn ansiStyle(\" \u2022 \", { fg: resolvePreset(palettePreset).extensionSeparator });\n}\n\nfunction joinPowerlineSegments(\n\tsegments: RenderSegment[],\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n): string {\n\tconst preset = resolvePreset(config.palettePreset);\n\tconst blocks = contiguousBlocks(segments, preset, config.palettePreset, config.palette);\n\tlet line = ansiStyle(\"\u2591\u2592\u2593\", { fg: preset.lead });\n\n\tfor (const [index, block] of blocks.entries()) {\n\t\tconst previous = index === 0 ? undefined : blocks[index - 1]?.colors;\n\t\tif (previous) line += ansiStyle(\"\uE0B4\", { fg: previous.bg, bg: block.colors.bg });\n\t\tline += ansiStyle(formatBlockText(block, config), block.colors);\n\t}\n\n\tconst lastBlock = blocks.at(-1);\n\tif (lastBlock) line += ansiStyle(\"\uE0B4\", { fg: lastBlock.colors.bg });\n\treturn line;\n}\n\nfunction contiguousBlocks(\n\tsegments: RenderSegment[],\n\tpreset: PowerlinePreset,\n\tpalettePreset: PalettePreset,\n\tconfiguredPalette: SegmentPalette,\n): PowerlineBlock[] {\n\tconst blocks: PowerlineBlock[] = [];\n\tconst usesConfiguredColors = palettePreset === \"custom\";\n\tfor (const segment of segments) {\n\t\tconst colors = usesConfiguredColors\n\t\t\t? (configuredPalette[segment.name] ?? {})\n\t\t\t: preset.blocks[segment.block];\n\t\tconst previous = blocks.at(-1);\n\t\tconst matchesPrevious =\n\t\t\tprevious !== undefined &&\n\t\t\t(usesConfiguredColors\n\t\t\t\t? colorsEqual(previous.colors, colors)\n\t\t\t\t: previous.baseBlock === segment.block);\n\t\tif (matchesPrevious) previous.segments.push(segment);\n\t\telse blocks.push({ baseBlock: segment.block, colors, segments: [segment] });\n\t}\n\treturn blocks;\n}\n\nfunction colorsEqual(left: BlockColors, right: BlockColors): boolean {\n\treturn left.fg === right.fg && left.bg === right.bg;\n}\n\nfunction formatBlockText(\n\tblock: PowerlineBlock,\n\tconfig: Pick<StatuslineConfig, \"density\" | \"separator\">,\n): string {\n\tconst texts = block.segments.map(formatSegmentText);\n\tconst separator = separatorText(config.separator, config.density === \"cozy\");\n\tconst leading = config.density === \"cozy\" ? \" \" : \" \";\n\tconst trailing = config.density === \"cozy\" ? \" \" : \"\";\n\treturn `${leading}${texts.join(separator)}${trailing}`;\n}\n\nfunction formatSegmentText(segment: RenderSegment): string {\n\treturn segment.emphasis ? `\\u001b[1m${segment.text}\\u001b[22m` : segment.text;\n}\n\nfunction separatorText(separator: SeparatorName, cozy: boolean): string {\n\tconst padding = cozy ? \" \" : \" \";\n\tswitch (separator) {\n\t\tcase \"dot\":\n\t\t\treturn `${padding}\u2022${padding}`;\n\t\tcase \"bar\":\n\t\t\treturn `${padding}\u2502${padding}`;\n\t\tcase \"powerline\":\n\t\t\treturn `${padding}\uE0B1${padding}`;\n\t\tcase \"round\":\n\t\t\treturn `${padding}\u276F${padding}`;\n\t\tcase \"none\":\n\t\t\treturn padding;\n\t}\n}\n", "export function ansiStyle(text: string, colors: { fg?: string; bg?: string }): string {\n\tconst codes = [\n\t\tcolors.fg ? truecolorCode(\"38\", colors.fg) : undefined,\n\t\tcolors.bg ? truecolorCode(\"48\", colors.bg) : undefined,\n\t].filter((code): code is string => code !== undefined);\n\tif (codes.length === 0) return text;\n\treturn `\\u001b[${codes.join(\";\")}m${text}\\u001b[0m`;\n}\n\nexport function ansiFg(hex: string, text: string): string {\n\treturn ansiStyle(text, { fg: hex });\n}\n\nfunction truecolorCode(prefix: \"38\" | \"48\", hex: string): string {\n\tconst { red, green, blue } = hexToRgb(hex);\n\treturn `${prefix};2;${red};${green};${blue}`;\n}\n\nfunction hexToRgb(hex: string): { red: number; green: number; blue: number } {\n\tconst normalized = hex.replace(/^#/, \"\");\n\treturn {\n\t\tred: Number.parseInt(normalized.slice(0, 2), 16),\n\t\tgreen: Number.parseInt(normalized.slice(2, 4), 16),\n\t\tblue: Number.parseInt(normalized.slice(4, 6), 16),\n\t};\n}\n", "import { isAbsolute } from \"node:path\";\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nconst GIT_STATUS_TIMEOUT_MS = 3_000;\n\nexport interface GitStatusSummary {\n\troot?: string;\n\tahead: number;\n\tbehind: number;\n\tstaged: number;\n\tmodified: number;\n\tuntracked: number;\n\tconflicts: number;\n}\n\nexport async function readGitStatus(\n\tpi: ExtensionAPI,\n\tcwd: string,\n\tsignal?: AbortSignal,\n): Promise<GitStatusSummary | undefined> {\n\tconst [statusResult, rootResult] = await Promise.all([\n\t\tpi.exec(\n\t\t\t\"git\",\n\t\t\t[\"--no-optional-locks\", \"status\", \"--porcelain=v1\", \"--branch\", \"--untracked-files=normal\"],\n\t\t\t{ cwd, timeout: GIT_STATUS_TIMEOUT_MS, signal },\n\t\t),\n\t\tpi\n\t\t\t.exec(\"git\", [\"rev-parse\", \"--path-format=absolute\", \"--show-toplevel\"], {\n\t\t\t\tcwd,\n\t\t\t\ttimeout: GIT_STATUS_TIMEOUT_MS,\n\t\t\t\tsignal,\n\t\t\t})\n\t\t\t.catch(() => undefined),\n\t]);\n\tif (statusResult.code !== 0 || statusResult.killed) return undefined;\n\tconst summary = parseGitStatusPorcelain(statusResult.stdout);\n\tif (rootResult && rootResult.code === 0 && !rootResult.killed) {\n\t\tconst root = parseGitRoot(rootResult.stdout);\n\t\tif (root) summary.root = root;\n\t}\n\treturn summary;\n}\n\nexport function parseGitStatusPorcelain(output: string): GitStatusSummary {\n\tconst summary: GitStatusSummary = {\n\t\tahead: 0,\n\t\tbehind: 0,\n\t\tstaged: 0,\n\t\tmodified: 0,\n\t\tuntracked: 0,\n\t\tconflicts: 0,\n\t};\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tif (!line) continue;\n\t\tif (line.startsWith(\"## \")) {\n\t\t\tconst ahead = line.match(/\\bahead (\\d+)/u);\n\t\t\tconst behind = line.match(/\\bbehind (\\d+)/u);\n\t\t\tsummary.ahead = ahead ? Number(ahead[1]) : 0;\n\t\t\tsummary.behind = behind ? Number(behind[1]) : 0;\n\t\t\tcontinue;\n\t\t}\n\t\tconst indexStatus = line[0] ?? \" \";\n\t\tconst worktreeStatus = line[1] ?? \" \";\n\t\tif (indexStatus === \"?\" && worktreeStatus === \"?\") {\n\t\t\tsummary.untracked += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isConflictStatus(indexStatus, worktreeStatus)) {\n\t\t\tsummary.conflicts += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isChangedStatus(indexStatus)) summary.staged += 1;\n\t\tif (isChangedStatus(worktreeStatus)) summary.modified += 1;\n\t}\n\treturn summary;\n}\n\nfunction isConflictStatus(indexStatus: string, worktreeStatus: string): boolean {\n\treturn (\n\t\t(indexStatus === \"D\" && worktreeStatus === \"D\") ||\n\t\t(indexStatus === \"A\" && worktreeStatus === \"A\") ||\n\t\tindexStatus === \"U\" ||\n\t\tworktreeStatus === \"U\"\n\t);\n}\n\nfunction isChangedStatus(status: string): boolean {\n\treturn status !== \" \" && status !== \"?\" && status !== \"!\";\n}\n\nexport function parseGitRoot(output: string): string | undefined {\n\tconst root = output.split(/\\r?\\n/u)[0]?.trim();\n\treturn root && isAbsolute(root) ? root : undefined;\n}\n\nexport function formatGitStatusSummary(summary: GitStatusSummary | undefined): string {\n\tif (!summary) return \"\";\n\tconst tokens = [\n\t\t[\"\u21E1\", summary.ahead],\n\t\t[\"\u21E3\", summary.behind],\n\t\t[\"+\", summary.staged],\n\t\t[\"~\", summary.modified],\n\t\t[\"?\", summary.untracked],\n\t\t[\"!\", summary.conflicts],\n\t] as const;\n\treturn tokens\n\t\t.filter(([, count]) => count > 0)\n\t\t.map(([prefix, count]) => `${prefix}${formatCount(count)}`)\n\t\t.join(\" \");\n}\n\nexport function formatGitBranchValue(\n\tbranch: string | null,\n\tstatus: GitStatusSummary | undefined,\n\tpr?: string,\n): string {\n\tif (!branch) return \"no-git\";\n\tconst suffixes = [formatGitStatusSummary(status), pr ? `(${pr})` : \"\"].filter(Boolean);\n\treturn suffixes.length > 0 ? `${branch} ${suffixes.join(\" \")}` : branch;\n}\n\nexport function formatGitBranchText(\n\tbranch: string | null,\n\tstatus: GitStatusSummary | undefined,\n\tpr?: string,\n): string {\n\treturn `\uD83C\uDF3F ${formatGitBranchValue(branch, status, pr)}`;\n}\n\nexport function gitStatusSummaryEqual(\n\tleft: GitStatusSummary | undefined,\n\tright: GitStatusSummary | undefined,\n): boolean {\n\tif (!left || !right) return left === right;\n\treturn (\n\t\tleft.root === right.root &&\n\t\tleft.ahead === right.ahead &&\n\t\tleft.behind === right.behind &&\n\t\tleft.staged === right.staged &&\n\t\tleft.modified === right.modified &&\n\t\tleft.untracked === right.untracked &&\n\t\tleft.conflicts === right.conflicts\n\t);\n}\n\nfunction formatCount(value: number): string {\n\treturn Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 }).format(value);\n}\n", "import type {\n\tExtensionAPI,\n\tExtensionContext,\n\tReadonlyFooterDataProvider,\n\tTheme,\n\tThemeColor,\n} from \"@earendil-works/pi-coding-agent\";\nimport { sanitizeTerminalText } from \"@narumitw/pi-tui-kit/terminal-text\";\nimport { formatDirectoryPath } from \"./directory.js\";\nimport {\n\ttype ExtensionStatusRuntime,\n\tformatExtensionStatuses,\n\twrapExtensionStatusline,\n} from \"./extension-status.js\";\nimport { formatGitBranchValue, type GitStatusSummary } from \"./git-status.js\";\nimport { renderPowerlineStatusline } from \"./powerline.js\";\nimport {\n\tLINE_BREAK_SEGMENT_NAME,\n\ttype PowerlineBlockName,\n\ttype RenderItem,\n\ttype RenderSegment,\n\ttype SegmentName,\n\ttype StatuslineConfig,\n\ttype TruncationDirection,\n} from \"./types.js\";\nimport { type FooterUsageSummary, summarizeFooterUsage } from \"./usage.js\";\n\ntype ThinkingLevel = ReturnType<ExtensionAPI[\"getThinkingLevel\"]>;\nexport interface RuntimeState extends ExtensionStatusRuntime {\n\thomeDir?: string;\n\tturnCount: number;\n\tactiveTools: Map<string, number>;\n\tisStreaming: boolean;\n\tthinkingLevel: ThinkingLevel;\n\tgitStatus?: GitStatusSummary;\n\trequestRender?: () => void;\n}\nconst GITHUB_PR_KEY = \"github-pr\";\nconst GITHUB_PR_STATUS_KEYS = new Set([GITHUB_PR_KEY]);\nexport function renderStatusline(\n\twidth: number,\n\tctx: ExtensionContext,\n\tfooterData: ReadonlyFooterDataProvider,\n\t_theme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n): string {\n\tif (width <= 0) return \"\";\n\n\tconst usageSummary = summarizeFooterUsage(ctx.sessionManager.getEntries());\n\tconst rows: Array<{ configuredSegments: number; segments: RenderSegment[] }> = [\n\t\t{ configuredSegments: 0, segments: [] },\n\t];\n\tfor (const name of config.segments) {\n\t\tif (name === LINE_BREAK_SEGMENT_NAME) {\n\t\t\trows.push({ configuredSegments: 0, segments: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst row = rows.at(-1);\n\t\tif (!row) continue;\n\t\trow.configuredSegments += 1;\n\t\tconst rendered = buildSegment(name, ctx, footerData, config, runtime, usageSummary);\n\t\tif (rendered && rendered.text.length > 0) row.segments.push(rendered);\n\t}\n\n\tconst segments: RenderItem[] = [];\n\tconst renderedRows = rows.filter(\n\t\t(row) => row.configuredSegments === 0 || row.segments.length > 0,\n\t);\n\tfor (const [index, row] of renderedRows.entries()) {\n\t\tif (index > 0) segments.push({ name: LINE_BREAK_SEGMENT_NAME });\n\t\tsegments.push(...row.segments);\n\t}\n\n\treturn renderPowerlineStatusline(width, segments, config);\n}\n\nexport function renderExtensionStatusline(\n\twidth: number,\n\tfooterData: ReadonlyFooterDataProvider,\n\ttheme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n\tmainLine: string,\n): string[] {\n\tconst statuses = footerData.getExtensionStatuses();\n\tconst prContext = prContextFromStatuses(statuses);\n\tconst rendersPrInline = prContext !== undefined && mainLine.includes(prContext);\n\tconst status = formatExtensionStatuses(\n\t\tstatuses,\n\t\ttheme,\n\t\tconfig,\n\t\truntime,\n\t\trendersPrInline ? GITHUB_PR_STATUS_KEYS : undefined,\n\t);\n\treturn wrapExtensionStatusline(status, width);\n}\n\nfunction buildSegment(\n\tname: SegmentName,\n\tctx: ExtensionContext,\n\tfooterData: ReadonlyFooterDataProvider,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n\tusageSummary: FooterUsageSummary,\n): RenderSegment | undefined {\n\tswitch (name) {\n\t\tcase \"brand\":\n\t\t\treturn segment(name, \"\u03C0\", config, \"accent\", \"header\", true);\n\t\tcase \"provider\":\n\t\t\treturn segment(name, ctx.model?.provider ?? \"no-provider\", config, \"accent\", \"header\");\n\t\tcase \"model\": {\n\t\t\tconst presentation = config.segmentText.model;\n\t\t\tconst model = truncateModel(\n\t\t\t\tshortenModel(ctx.model?.id ?? \"no-model\"),\n\t\t\t\tpresentation.truncationLength,\n\t\t\t\tpresentation.truncationSymbol,\n\t\t\t\tpresentation.truncationDirection,\n\t\t\t);\n\t\t\treturn segment(name, model, config, \"accent\", \"header\");\n\t\t}\n\t\tcase \"thinking\":\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\truntime.thinkingLevel,\n\t\t\t\tconfig,\n\t\t\t\tthinkingColor(runtime.thinkingLevel),\n\t\t\t\t\"header\",\n\t\t\t);\n\t\tcase \"branch\": {\n\t\t\tconst branch = footerData.getGitBranch();\n\t\t\tconst pr = branch ? prContextFromStatuses(footerData.getExtensionStatuses()) : undefined;\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\tformatGitBranchValue(branch, runtime.gitStatus, pr),\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"git\",\n\t\t\t);\n\t\t}\n\t\tcase \"cwd\":\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\tformatDirectoryPath(ctx.cwd, runtime.homeDir, runtime.gitStatus?.root),\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"directory\",\n\t\t\t);\n\t\tcase \"tools\": {\n\t\t\tconst activity = formatToolActivity(runtime);\n\t\t\treturn activity ? segment(name, activity, config, \"accent\", \"runtime\") : undefined;\n\t\t}\n\t\tcase \"context\": {\n\t\t\tconst usage = ctx.getContextUsage();\n\t\t\tconst percentage =\n\t\t\t\tusage?.percent === null || usage?.percent === undefined\n\t\t\t\t\t? \"?\"\n\t\t\t\t\t: `${usage.percent.toFixed(1)}%`;\n\t\t\tconst contextWindow = usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\t`${percentage}/${formatCount(contextWindow)}`,\n\t\t\t\tconfig,\n\t\t\t\tcontextColor(usage?.percent),\n\t\t\t\t\"runtime\",\n\t\t\t);\n\t\t}\n\t\tcase \"tokens\": {\n\t\t\tconst value =\n\t\t\t\tusageSummary.input === 0 && usageSummary.output === 0\n\t\t\t\t\t? \"tok 0\"\n\t\t\t\t\t: `\u2191${formatCount(usageSummary.input)} \u2193${formatCount(usageSummary.output)}`;\n\t\t\treturn segment(name, value, config, \"accent\", \"runtime\");\n\t\t}\n\t\tcase \"cache\": {\n\t\t\tif (usageSummary.cacheRead === 0 && usageSummary.cacheWrite === 0) return undefined;\n\t\t\tconst values: string[] = [];\n\t\t\tif (usageSummary.cacheRead > 0) values.push(`R${formatCount(usageSummary.cacheRead)}`);\n\t\t\tif (usageSummary.cacheWrite > 0) values.push(`W${formatCount(usageSummary.cacheWrite)}`);\n\t\t\tif (usageSummary.latestCacheHitRate !== undefined) {\n\t\t\t\tvalues.push(`CH${usageSummary.latestCacheHitRate.toFixed(1)}%`);\n\t\t\t}\n\t\t\treturn segment(name, values.join(\" \"), config, \"accent\", \"runtime\");\n\t\t}\n\t\tcase \"cost\": {\n\t\t\tconst subscription = isSubscriptionBacked(ctx) ? \" (sub)\" : \"\";\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\t`${usageSummary.cost.toFixed(usageSummary.cost >= 1 ? 2 : 3)}${subscription}`,\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"meter\",\n\t\t\t);\n\t\t}\n\t\tcase \"time\":\n\t\t\treturn segment(name, formatTime(), config, \"accent\", \"meter\");\n\t\tcase \"turn\":\n\t\t\treturn segment(name, `${runtime.turnCount}`, config, \"accent\", \"meter\");\n\t}\n}\n\nfunction segment(\n\tname: SegmentName,\n\tvalue: string,\n\tconfig: StatuslineConfig,\n\tcolor: RenderSegment[\"color\"],\n\tblock: PowerlineBlockName,\n\temphasis = false,\n): RenderSegment {\n\treturn { name, text: formatConfiguredSegment(name, value, config), color, block, emphasis };\n}\n\nexport function formatConfiguredSegment(\n\tname: SegmentName,\n\tvalue: string,\n\tconfig: Pick<StatuslineConfig, \"segmentText\">,\n): string {\n\tconst presentation = config.segmentText[name];\n\treturn `${presentation.prefix}${value}${presentation.suffix}`;\n}\n\nfunction thinkingColor(level: ThinkingLevel): ThemeColor {\n\tswitch (level as string) {\n\t\tcase \"off\":\n\t\t\treturn \"dim\";\n\t\tcase \"minimal\":\n\t\t\treturn \"thinkingMinimal\";\n\t\tcase \"low\":\n\t\t\treturn \"thinkingLow\";\n\t\tcase \"medium\":\n\t\t\treturn \"thinkingMedium\";\n\t\tcase \"high\":\n\t\t\treturn \"thinkingHigh\";\n\t\tcase \"xhigh\":\n\t\t\treturn \"thinkingXhigh\";\n\t\tcase \"max\":\n\t\t\treturn \"thinkingMax\" as ThemeColor;\n\t\tdefault:\n\t\t\treturn \"dim\";\n\t}\n}\n\nexport function contextColor(percent: number | null | undefined): ThemeColor {\n\tif (percent === null || percent === undefined) return \"dim\";\n\tif (percent >= 90) return \"error\";\n\tif (percent >= 70) return \"warning\";\n\treturn \"success\";\n}\n\nexport function formatToolActivity(runtime: RuntimeState): string | undefined {\n\tconst active = [...runtime.activeTools.entries()];\n\tif (active.length > 0) {\n\t\tconst [name, count] = active[0] ?? [\"tool\", 1];\n\t\tconst suffix = count > 1 ? `\u00D7${count}` : active.length > 1 ? `+${active.length - 1}` : \"\";\n\t\treturn `\u2699 ${name}${suffix}`;\n\t}\n\n\treturn runtime.isStreaming ? \"\uD83D\uDCAD thinking\" : undefined;\n}\n\nexport function prLinkFromStatuses(statuses: ReadonlyMap<string, string>): string | undefined {\n\tconst value = statuses.get(GITHUB_PR_KEY);\n\tif (!value) return undefined;\n\t// Extract the OSC 8 hyperlink span (the clickable \"#123\"); skip non-PR states\n\t// like \"PR gh missing\" that carry no link. github-pr emits exactly one link, so the\n\t// first OSC 8 span is the PR number.\n\tconst open = value.indexOf(\"\\x1b]8;;\");\n\tif (open === -1) return undefined;\n\tconst closeMarker = \"\\x1b]8;;\\x07\";\n\tconst close = value.indexOf(closeMarker, open + 1);\n\treturn close === -1 ? undefined : value.slice(open, close + closeMarker.length);\n}\n\nexport function prContextFromStatuses(statuses: ReadonlyMap<string, string>): string | undefined {\n\tconst value = statuses.get(GITHUB_PR_KEY);\n\tconst link = prLinkFromStatuses(statuses);\n\tif (!value || !link) return undefined;\n\n\tconst state = compactPrState(value.replace(link, \"\"));\n\treturn state ? `${link} \u00B7 ${state}` : undefined;\n}\n\nfunction compactPrState(value: string): string | undefined {\n\tif (/:\\s*merged\\s*$/.test(value)) return \"merged\";\n\tif (/:\\s*closed\\s*$/.test(value)) return \"closed\";\n\tif (/\\bdraft\\b/.test(value)) return \"draft\";\n\n\tconst failing = /\\bchecks failing \\((\\d+)\\)/.exec(value);\n\tif (failing) return `${failing[1]} failing`;\n\tif (/\\bchanges requested\\b/.test(value)) return \"changes requested\";\n\n\tconst pending = /\\bchecks pending \\((\\d+)\\)/.exec(value);\n\tif (pending) return `${pending[1]} pending`;\n\tif (/\\bapproved\\b/.test(value)) return \"approved\";\n\tif (/\\breview required\\b/.test(value)) return \"review required\";\n\tif (/\\bchecks passing\\b/.test(value)) return \"checks passing\";\n\tif (/\\bno checks\\b/.test(value)) return \"no checks\";\n\treturn undefined;\n}\n\nfunction isSubscriptionBacked(ctx: ExtensionContext): boolean {\n\tconst model = ctx.model;\n\treturn (\n\t\tmodel !== undefined &&\n\t\t(model.provider === \"kimi-coding\" || ctx.modelRegistry.isUsingOAuth(model))\n\t);\n}\n\nexport function formatCount(value: number): string {\n\tif (value < 1000) return `${value}`;\n\tif (value < 1_000_000) return `${(value / 1000).toFixed(value < 10_000 ? 1 : 0)}k`;\n\treturn `${(value / 1_000_000).toFixed(1)}m`;\n}\n\nfunction formatTime(): string {\n\tconst now = new Date();\n\tconst hours = now.getHours().toString().padStart(2, \"0\");\n\tconst minutes = now.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function truncateModel(\n\tmodel: string,\n\tlength: number,\n\tsymbol: string,\n\tdirection: TruncationDirection,\n): string {\n\tconst safeModel = sanitizeTerminalText(model);\n\tif (length === 0) return safeModel;\n\tconst graphemes = [...graphemeSegmenter.segment(safeModel)].map(({ segment }) => segment);\n\tif (graphemes.length <= length) return safeModel;\n\tconst safeSymbol = sanitizeTerminalText(symbol);\n\n\tswitch (direction) {\n\t\tcase \"start\":\n\t\t\treturn `${safeSymbol}${graphemes.slice(-length).join(\"\")}`;\n\t\tcase \"middle\": {\n\t\t\tconst headLength = Math.ceil(length / 2);\n\t\t\tconst tailLength = Math.floor(length / 2);\n\t\t\tconst tail = tailLength > 0 ? graphemes.slice(-tailLength).join(\"\") : \"\";\n\t\t\treturn `${graphemes.slice(0, headLength).join(\"\")}${safeSymbol}${tail}`;\n\t\t}\n\t\tcase \"end\":\n\t\t\treturn `${graphemes.slice(0, length).join(\"\")}${safeSymbol}`;\n\t}\n}\n\nexport function shortenModel(model: string): string {\n\treturn model\n\t\t.replace(/^claude-/, \"\")\n\t\t.replace(/^gpt-/, \"gpt \")\n\t\t.replace(/-20\\d{6}$/, \"\")\n\t\t.replace(/-latest$/, \"\");\n}\n", "import { basename, isAbsolute, relative, sep } from \"node:path\";\nimport { sanitizeTerminalText } from \"@narumitw/pi-tui-kit/terminal-text\";\n\nconst DEFAULT_TRUNCATION_LENGTH = 3;\nconst DEFAULT_HOME_SYMBOL = \"~\";\n\n/** Apply Starship's default directory presentation without exposing a format language. */\nexport function formatDirectoryPath(\n\tcwd: string,\n\thomeDir: string | undefined,\n\tgitRoot: string | undefined,\n): string {\n\tconst contracted =\n\t\tgitRoot && (!homeDir || !samePath(gitRoot, homeDir))\n\t\t\t? (contractRepositoryPath(cwd, gitRoot) ?? contractPath(cwd, homeDir, DEFAULT_HOME_SYMBOL))\n\t\t\t: contractPath(cwd, homeDir, DEFAULT_HOME_SYMBOL);\n\tconst safeContracted = sanitizeTerminalText(contracted);\n\tconst components = safeContracted.split(\"/\").filter((component) => component.length > 0);\n\tconst displayed =\n\t\tcomponents.length > DEFAULT_TRUNCATION_LENGTH\n\t\t\t? components.slice(-DEFAULT_TRUNCATION_LENGTH).join(\"/\")\n\t\t\t: safeContracted;\n\tconst native = sep === \"/\" ? displayed : displayed.replaceAll(\"/\", sep);\n\treturn sanitizeTerminalText(native || basename(cwd) || cwd);\n}\n\nfunction toSlashPath(value: string): string {\n\treturn sep === \"\\\\\" ? value.replaceAll(\"\\\\\", \"/\") : value;\n}\n\nfunction contractPath(path: string, root: string | undefined, replacement: string): string {\n\tif (!root) return toSlashPath(path);\n\tconst child = relativeWithin(path, root);\n\tif (child === undefined) return toSlashPath(path);\n\treturn child ? `${replacement}/${child}` : replacement;\n}\n\nfunction contractRepositoryPath(path: string, root: string): string | undefined {\n\tconst child = relativeWithin(path, root);\n\tif (child === undefined) return undefined;\n\tconst name = basename(root) || toSlashPath(root);\n\treturn child ? `${name}/${child}` : name;\n}\n\nfunction relativeWithin(path: string, root: string): string | undefined {\n\tconst child = relative(root, path);\n\tif (child === \"\") return \"\";\n\tif (child === \"..\" || child.startsWith(`..${sep}`) || isAbsolute(child)) return undefined;\n\treturn toSlashPath(child);\n}\n\nfunction samePath(left: string, right: string): boolean {\n\treturn relative(left, right) === \"\";\n}\n", "import type { SessionEntry } from \"@earendil-works/pi-coding-agent\";\n\ninterface UsageLike {\n\tinput?: number;\n\toutput?: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\tcost?: { total?: number };\n}\n\nexport interface FooterUsageSummary {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n\tlatestCacheHitRate?: number;\n}\n\nexport function summarizeFooterUsage(entries: readonly SessionEntry[]): FooterUsageSummary {\n\tconst totals: FooterUsageSummary = {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n\n\tfor (const entry of entries) {\n\t\tlet usage: UsageLike | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tusage = entry.message.usage;\n\t\t\tconst input = usage.input ?? 0;\n\t\t\tconst cacheRead = usage.cacheRead ?? 0;\n\t\t\tconst cacheWrite = usage.cacheWrite ?? 0;\n\t\t\tconst promptTokens = input + cacheRead + cacheWrite;\n\t\t\ttotals.latestCacheHitRate = promptTokens > 0 ? (cacheRead / promptTokens) * 100 : undefined;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\") {\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"compaction\" || entry.type === \"branch_summary\") {\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!usage) continue;\n\n\t\ttotals.input += usage.input ?? 0;\n\t\ttotals.output += usage.output ?? 0;\n\t\ttotals.cacheRead += usage.cacheRead ?? 0;\n\t\ttotals.cacheWrite += usage.cacheWrite ?? 0;\n\t\ttotals.cost += usage.cost?.total ?? 0;\n\t}\n\n\treturn totals;\n}\n"],
5
- "mappings": "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",
6
- "names": ["getAgentDir", "rendered", "segment", "isAbsolute", "sanitizeTerminalText", "isAbsolute", "formatCount", "sanitizeTerminalText", "segment", "STATUSLINE_KEY", "EMPTY_EXTENSION_STATUS_ICON_ALIASES", "getAgentDir"]
4
+ "sourcesContent": ["import { homedir } from \"node:os\";\nimport {\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\tgetAgentDir,\n} from \"@earendil-works/pi-coding-agent\";\nimport { getCapabilities } from \"@earendil-works/pi-tui\";\nimport { completeStatuslineArguments } from \"./command-contract.js\";\nimport type { StatuslineCommandOptions } from \"./commands.js\";\nimport {\n\tbuildExtensionStatusIconAliases,\n\ttype ExtensionStatusIconAliasMap,\n\tfindDuplicateExtensions,\n\treadInstalledExtensionPackages,\n} from \"./extension-status.js\";\nimport { type GitStatusSummary, gitStatusSummaryEqual, readGitStatus } from \"./git-status.js\";\nimport { type RuntimeState, renderExtensionStatusline, renderStatusline } from \"./render.js\";\nimport {\n\tconsumeStatuslineSettingsNotice,\n\ttype LoadedStatuslineSettings,\n\tloadStatuslineSettings,\n\tloadStatuslineSettingsForAgent,\n\tsettingsFilePath,\n} from \"./settings.js\";\nimport type { PalettePreset } from \"./types.js\";\n\nconst STATUSLINE_KEY = \"statusline\";\nconst GIT_STATUS_REFRESH_INTERVAL_MS = 30_000;\nconst GIT_STATUS_EVENT_DEBOUNCE_MS = 250;\nconst EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();\n\ntype StatuslineCommands = typeof import(\"./commands.js\");\nlet statuslineCommandsPromise: Promise<StatuslineCommands> | undefined;\n\nfunction loadStatuslineCommands(): Promise<StatuslineCommands> {\n\tif (!statuslineCommandsPromise) {\n\t\tstatuslineCommandsPromise = import(\"./commands.js\").catch((error) => {\n\t\t\tstatuslineCommandsPromise = undefined;\n\t\t\tthrow error;\n\t\t});\n\t}\n\treturn statuslineCommandsPromise;\n}\n\nexport default function statusline(pi: ExtensionAPI) {\n\tlet loaded: LoadedStatuslineSettings | undefined;\n\tlet previewPalettePreset: PalettePreset | undefined;\n\tlet activeSessionManager: ExtensionContext[\"sessionManager\"] | undefined;\n\tconst runtime: RuntimeState = {\n\t\tturnCount: 0,\n\t\tactiveTools: new Map(),\n\t\tisStreaming: false,\n\t\tthinkingLevel: \"off\",\n\t\tduplicateExtensions: [],\n\t\textensionStatusIconAliases: EMPTY_EXTENSION_STATUS_ICON_ALIASES,\n\t};\n\n\tlet sessionGeneration = 0;\n\tlet menuController = new AbortController();\n\tlet gitStatusRequestId = 0;\n\tlet activeGitStatusTarget: { cwd: string; generation: number } | undefined;\n\tlet gitStatusRefreshInFlight = false;\n\tlet gitStatusAbortController: AbortController | undefined;\n\tlet gitStatusDebounceTimer: ReturnType<typeof setTimeout> | undefined;\n\tlet pendingGitStatusRefresh: { cwd: string; generation: number; requestId: number } | undefined;\n\n\tconst refresh = () => runtime.requestRender?.();\n\tconst ownsRuntime = (ctx: ExtensionContext) => ctx.sessionManager === activeSessionManager;\n\n\tconst setGitStatus = (summary: GitStatusSummary | undefined) => {\n\t\tif (gitStatusSummaryEqual(runtime.gitStatus, summary)) return;\n\t\truntime.gitStatus = summary;\n\t\trefresh();\n\t};\n\n\tconst clearGitStatusDebounce = () => {\n\t\tif (!gitStatusDebounceTimer) return;\n\t\tclearTimeout(gitStatusDebounceTimer);\n\t\tgitStatusDebounceTimer = undefined;\n\t};\n\n\tconst abortGitStatusRefresh = (reason: string) => {\n\t\tgitStatusAbortController?.abort(new DOMException(reason, \"AbortError\"));\n\t};\n\n\tconst isActiveGitStatusTarget = (cwd: string, generation: number) =>\n\t\tactiveGitStatusTarget?.cwd === cwd &&\n\t\tactiveGitStatusTarget.generation === generation &&\n\t\tgeneration === sessionGeneration;\n\n\tconst isCurrentGitStatusRequest = (cwd: string, generation: number, requestId: number) =>\n\t\tisActiveGitStatusTarget(cwd, generation) && requestId === gitStatusRequestId;\n\n\tconst runGitStatusRefresh = (cwd: string, generation: number, requestId: number) => {\n\t\tif (!isCurrentGitStatusRequest(cwd, generation, requestId)) return;\n\t\tif (gitStatusRefreshInFlight) {\n\t\t\tpendingGitStatusRefresh = { cwd, generation, requestId };\n\t\t\treturn;\n\t\t}\n\n\t\tgitStatusRefreshInFlight = true;\n\t\tconst abortController = new AbortController();\n\t\tgitStatusAbortController = abortController;\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst summary = await readGitStatus(pi, cwd, abortController.signal);\n\t\t\t\tif (isCurrentGitStatusRequest(cwd, generation, requestId)) setGitStatus(summary);\n\t\t\t} catch {\n\t\t\t\tif (isCurrentGitStatusRequest(cwd, generation, requestId)) setGitStatus(undefined);\n\t\t\t} finally {\n\t\t\t\tgitStatusRefreshInFlight = false;\n\t\t\t\tif (gitStatusAbortController === abortController) gitStatusAbortController = undefined;\n\t\t\t\tconst pending = pendingGitStatusRefresh;\n\t\t\t\tpendingGitStatusRefresh = undefined;\n\t\t\t\tif (pending) runGitStatusRefresh(pending.cwd, pending.generation, pending.requestId);\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst refreshGitStatus = (cwd: string, generation = sessionGeneration) => {\n\t\tif (!isActiveGitStatusTarget(cwd, generation)) return;\n\t\trunGitStatusRefresh(cwd, generation, ++gitStatusRequestId);\n\t};\n\n\tconst scheduleGitStatusRefresh = (cwd: string, generation = sessionGeneration) => {\n\t\tif (!isActiveGitStatusTarget(cwd, generation)) return;\n\t\tconst requestId = ++gitStatusRequestId;\n\t\tclearGitStatusDebounce();\n\t\tgitStatusDebounceTimer = setTimeout(() => {\n\t\t\tgitStatusDebounceTimer = undefined;\n\t\t\trunGitStatusRefresh(cwd, generation, requestId);\n\t\t}, GIT_STATUS_EVENT_DEBOUNCE_MS);\n\t};\n\n\tconst scheduleGitStatusRefreshForContext = (ctx: ExtensionContext) => {\n\t\tif (!activeGitStatusTarget || activeGitStatusTarget.cwd !== ctx.cwd) return;\n\t\tscheduleGitStatusRefresh(activeGitStatusTarget.cwd, activeGitStatusTarget.generation);\n\t};\n\n\tconst installFooter = (ctx: ExtensionContext) => {\n\t\tconst generation = ++sessionGeneration;\n\t\tmenuController.abort(new DOMException(\"Statusline session context replaced\", \"AbortError\"));\n\t\tmenuController = new AbortController();\n\t\tconst cwd = ctx.cwd;\n\t\tactiveSessionManager = ctx.sessionManager;\n\t\truntime.homeDir = homedir();\n\t\tpreviewPalettePreset = undefined;\n\t\tabortGitStatusRefresh(\"Statusline session context replaced\");\n\t\tclearGitStatusDebounce();\n\t\tactiveGitStatusTarget = ctx.mode === \"tui\" ? { cwd, generation } : undefined;\n\t\truntime.gitStatus = undefined;\n\t\truntime.duplicateExtensions = [];\n\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\tctx.ui.setStatus(STATUSLINE_KEY, undefined);\n\t\tif (!activeGitStatusTarget || !loaded) return;\n\t\tconst installedPackages = readInstalledExtensionPackages(cwd);\n\t\truntime.duplicateExtensions = findDuplicateExtensions(installedPackages);\n\t\truntime.extensionStatusIconAliases = buildExtensionStatusIconAliases(installedPackages);\n\t\tctx.ui.setFooter((tui, theme, footerData) => {\n\t\t\truntime.requestRender = () => tui.requestRender();\n\n\t\t\tconst refreshFooterGitStatus = () => refreshGitStatus(cwd, generation);\n\t\t\tconst branchUnsubscribe = footerData.onBranchChange(() => {\n\t\t\t\truntime.gitStatus = undefined;\n\t\t\t\tabortGitStatusRefresh(\"Statusline Git branch changed\");\n\t\t\t\tclearGitStatusDebounce();\n\t\t\t\trefreshFooterGitStatus();\n\t\t\t\ttui.requestRender();\n\t\t\t});\n\t\t\tconst clock = setInterval(() => {\n\t\t\t\tclearGitStatusDebounce();\n\t\t\t\trefreshFooterGitStatus();\n\t\t\t\ttui.requestRender();\n\t\t\t}, GIT_STATUS_REFRESH_INTERVAL_MS);\n\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\tbranchUnsubscribe();\n\t\t\t\t\tclearInterval(clock);\n\t\t\t\t\tif (isActiveGitStatusTarget(cwd, generation)) {\n\t\t\t\t\t\tactiveGitStatusTarget = undefined;\n\t\t\t\t\t\tabortGitStatusRefresh(\"Statusline footer disposed\");\n\t\t\t\t\t\tclearGitStatusDebounce();\n\t\t\t\t\t\tpendingGitStatusRefresh = undefined;\n\t\t\t\t\t\truntime.gitStatus = undefined;\n\t\t\t\t\t\truntime.duplicateExtensions = [];\n\t\t\t\t\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\t\t\t\t\truntime.requestRender = undefined;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tinvalidate() {},\n\t\t\t\trender(width: number): string[] {\n\t\t\t\t\tif (!loaded) return [];\n\t\t\t\t\tconst config = previewPalettePreset\n\t\t\t\t\t\t? { ...loaded.config, palettePreset: previewPalettePreset }\n\t\t\t\t\t\t: loaded.config;\n\t\t\t\t\tconst trueColor = getCapabilities().trueColor;\n\t\t\t\t\tconst mainLine = renderStatusline(\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tfooterData,\n\t\t\t\t\t\ttheme,\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\truntime,\n\t\t\t\t\t\ttrueColor,\n\t\t\t\t\t);\n\t\t\t\t\tconst lines = mainLine ? mainLine.split(\"\\n\") : [];\n\t\t\t\t\tlines.push(\n\t\t\t\t\t\t...renderExtensionStatusline(\n\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\tfooterData,\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tconfig,\n\t\t\t\t\t\t\truntime,\n\t\t\t\t\t\t\tmainLine,\n\t\t\t\t\t\t\ttrueColor,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\treturn lines;\n\t\t\t\t},\n\t\t\t};\n\t\t});\n\t\trefreshGitStatus(cwd, generation);\n\t};\n\n\tconst agentDir = getAgentDir();\n\tconst configPath = settingsFilePath(agentDir);\n\tconst commandOptions: StatuslineCommandOptions = {\n\t\tsettingsPath: configPath,\n\t\tgetLoaded: () => loaded ?? loadStatuslineSettings(configPath),\n\t\tgetMenuOwner: () => {\n\t\t\tconst generation = sessionGeneration;\n\t\t\treturn {\n\t\t\t\tsignal: menuController.signal,\n\t\t\t\tisCurrent: () => generation === sessionGeneration && !menuController.signal.aborted,\n\t\t\t};\n\t\t},\n\t\tapply(next, ctx) {\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tpreviewPalettePreset = undefined;\n\t\t\tloaded = next;\n\t\t\trefresh();\n\t\t},\n\t\tpreview(palettePreset, ctx) {\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tpreviewPalettePreset = palettePreset;\n\t\t\trefresh();\n\t\t},\n\t};\n\tpi.registerCommand(\"statusline\", {\n\t\tdescription: \"Open or inspect the statusline settings\",\n\t\tgetArgumentCompletions: completeStatuslineArguments,\n\t\thandler: async (args, ctx) => {\n\t\t\tconst commands = await loadStatuslineCommands();\n\t\t\tif (ctx.sessionManager !== activeSessionManager) return;\n\t\t\tawait commands.handleStatuslineCommand(args, ctx, commandOptions);\n\t\t},\n\t});\n\n\tpi.on(\"session_start\", (_event, ctx) => {\n\t\truntime.turnCount = 0;\n\t\truntime.activeTools.clear();\n\t\truntime.isStreaming = false;\n\t\truntime.uiPrompt = undefined;\n\t\tloaded = loadStatuslineSettingsForAgent(agentDir);\n\t\tconst settingsNotice = consumeStatuslineSettingsNotice();\n\t\tif (settingsNotice) ctx.ui.notify(settingsNotice, \"warning\");\n\t\tif (loaded.diagnostics.length > 0) {\n\t\t\tctx.ui.notify(formatSettingsDiagnostics(loaded), \"warning\");\n\t\t}\n\t\truntime.thinkingLevel = pi.getThinkingLevel();\n\t\tinstallFooter(ctx);\n\t});\n\n\tpi.on(\"session_tree\", (_event, ctx) => {\n\t\tinstallFooter(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"session_shutdown\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tsessionGeneration += 1;\n\t\tmenuController.abort(new DOMException(\"Statusline session shut down\", \"AbortError\"));\n\t\tactiveSessionManager = undefined;\n\t\tpreviewPalettePreset = undefined;\n\t\tactiveGitStatusTarget = undefined;\n\t\tabortGitStatusRefresh(\"Statusline session shut down\");\n\t\tclearGitStatusDebounce();\n\t\tpendingGitStatusRefresh = undefined;\n\t\truntime.gitStatus = undefined;\n\t\truntime.activeTools.clear();\n\t\truntime.isStreaming = false;\n\t\truntime.uiPrompt = undefined;\n\t\truntime.duplicateExtensions = [];\n\t\truntime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;\n\t\tctx.ui.setFooter(undefined);\n\t\tctx.ui.setStatus(STATUSLINE_KEY, undefined);\n\t\truntime.requestRender = undefined;\n\t});\n\n\tpi.on(\"model_select\", () => refresh());\n\n\tpi.on(\"thinking_level_select\", (event) => {\n\t\truntime.thinkingLevel = event.level;\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_start\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.isStreaming = true;\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_end\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.activeTools.clear();\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"agent_settled\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.isStreaming = false;\n\t\truntime.activeTools.clear();\n\t\trefresh();\n\t});\n\n\tpi.on(\"ui_prompt_start\", (event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.uiPrompt = { kind: event.kind, title: event.title };\n\t\trefresh();\n\t});\n\n\tpi.on(\"ui_prompt_end\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.uiPrompt = undefined;\n\t\trefresh();\n\t});\n\n\tpi.on(\"turn_start\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\truntime.turnCount += 1;\n\t\truntime.isStreaming = true;\n\t\trefresh();\n\t});\n\n\tpi.on(\"turn_end\", (_event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n\n\tpi.on(\"tool_execution_start\", (event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tconst currentCount = runtime.activeTools.get(event.toolName) ?? 0;\n\t\truntime.activeTools.set(event.toolName, currentCount + 1);\n\t\trefresh();\n\t});\n\n\tpi.on(\"tool_execution_end\", (event, ctx) => {\n\t\tif (!ownsRuntime(ctx)) return;\n\t\tconst currentCount = runtime.activeTools.get(event.toolName) ?? 0;\n\t\tif (currentCount <= 1) runtime.activeTools.delete(event.toolName);\n\t\telse runtime.activeTools.set(event.toolName, currentCount - 1);\n\n\t\tscheduleGitStatusRefreshForContext(ctx);\n\t\trefresh();\n\t});\n}\n\nfunction formatSettingsDiagnostics(loaded: LoadedStatuslineSettings): string {\n\tconst details = loaded.diagnostics.slice(0, 5).map((item) => item.message);\n\tconst remaining = loaded.diagnostics.length - details.length;\n\treturn [\n\t\t`pi-statusline settings: ${details.join(\"; \")}`,\n\t\t...(remaining > 0 ? [`+${remaining} more`] : []),\n\t].join(\" \");\n}\n\nexport {\n\tbuildExtensionStatusIconAliases,\n\ttype ExtensionStatusIconAliasMap,\n\textensionColor,\n\tformatExtensionStatus,\n\tnpmPackageName,\n\tsimplifyExtensionStatusText,\n\tsplitExtensionStatusIcon,\n\tstripExtensionStatusPrefix,\n\twrapExtensionStatusline,\n} from \"./extension-status.js\";\nexport {\n\tformatGitBranchText,\n\tformatGitBranchValue,\n\tformatGitStatusSummary,\n\ttype GitStatusSummary,\n\tparseGitRoot,\n\tparseGitStatusPorcelain,\n\treadGitStatus,\n} from \"./git-status.js\";\nexport {\n\tcontextColor,\n\tformatCount,\n\tformatToolActivity,\n\tprContextFromStatuses,\n\tprLinkFromStatuses,\n\tshortenModel,\n} from \"./render.js\";\nexport { normalizeStatuslineSettings, readStatuslineSettings } from \"./settings.js\";\n", "import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { getAgentDir, type Theme, type ThemeColor } from \"@earendil-works/pi-coding-agent\";\nimport { wrapTextWithAnsi } from \"@earendil-works/pi-tui\";\nimport { powerlineExtensionSeparator } from \"./powerline.js\";\nimport { DEFAULT_EXTENSION_STATUS_ICONS } from \"./settings.js\";\nimport type { StatuslineConfig } from \"./types.js\";\n\nexport type ExtensionStatusIconAliasMap = ReadonlyMap<string, readonly string[]>;\nexport interface ExtensionStatusRuntime {\n\tduplicateExtensions: string[];\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap;\n}\n\nconst STATUSLINE_KEY = \"statusline\";\nconst COMPATIBLE_STATUS_ICON_KEYS: Readonly<Record<string, string>> = {\n\tretry: \"unknown-error-retry\",\n\tsync: \"pisync\",\n\t\"unknown-error-retry\": \"retry\",\n\tpisync: \"sync\",\n};\nconst EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();\nfunction extensionStatusSeparator(\n\tconfig: StatuslineConfig,\n\ttheme: Theme,\n\ttrueColor: boolean,\n): string {\n\treturn powerlineExtensionSeparator(theme, config.palettePreset, trueColor);\n}\n\nexport function formatExtensionStatuses(\n\tstatuses: ReadonlyMap<string, string>,\n\ttheme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: ExtensionStatusRuntime,\n\thiddenKeys: ReadonlySet<string> = new Set(),\n\ttrueColor = true,\n): string {\n\tconst separator = extensionStatusSeparator(config, theme, trueColor);\n\tconst visibleStatuses = [\n\t\t...formatDuplicateExtensionStatus(runtime, theme),\n\t\t...[...statuses.entries()]\n\t\t\t.filter(\n\t\t\t\t([key, value]) => key !== STATUSLINE_KEY && !hiddenKeys.has(key) && value.trim().length > 0,\n\t\t\t)\n\t\t\t.map(([key, value]) =>\n\t\t\t\tformatExtensionStatus(key, value, theme, config, runtime.extensionStatusIconAliases),\n\t\t\t),\n\t].slice(0, 5);\n\n\treturn visibleStatuses.join(separator);\n}\n\nexport function formatExtensionStatus(\n\tkey: string,\n\tvalue: string,\n\ttheme: Theme,\n\tconfig: Pick<StatuslineConfig, \"extensionStatusIcons\">,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap = EMPTY_EXTENSION_STATUS_ICON_ALIASES,\n): string {\n\tconst status = splitExtensionStatusIcon(stripExtensionStatusPrefix(key, value));\n\tconst text = simplifyExtensionStatusText(status.text);\n\tconst color = extensionColor(key, value);\n\tconst textColor = color === \"warning\" ? \"warning\" : \"muted\";\n\tconst icon = extensionStatusIcon(\n\t\tkey,\n\t\tstatus.icon,\n\t\tconfig.extensionStatusIcons,\n\t\textensionStatusIconAliases,\n\t);\n\tconst renderedText = theme.fg(textColor, text);\n\treturn icon ? `${theme.fg(color, icon)} ${renderedText}` : renderedText;\n}\n\nfunction extensionStatusIcon(\n\tkey: string,\n\tleadingIcon: string | undefined,\n\tconfiguredIcons: Record<string, string>,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap,\n) {\n\tif (Object.hasOwn(configuredIcons, key)) return configuredIcons[key];\n\tconst namespaceIcon = configuredNamespaceIcon(key, configuredIcons);\n\tif (namespaceIcon !== undefined) return namespaceIcon;\n\tconst compatibleKey = COMPATIBLE_STATUS_ICON_KEYS[key];\n\tif (compatibleKey && Object.hasOwn(configuredIcons, compatibleKey)) {\n\t\treturn configuredIcons[compatibleKey];\n\t}\n\tfor (const alias of extensionStatusAliasesForKey(key, extensionStatusIconAliases)) {\n\t\tif (Object.hasOwn(configuredIcons, alias)) return configuredIcons[alias];\n\t}\n\treturn leadingIcon ?? DEFAULT_EXTENSION_STATUS_ICONS[key] ?? \"\uD83D\uDD0C\";\n}\n\nfunction configuredNamespaceIcon(\n\tkey: string,\n\tconfiguredIcons: Readonly<Record<string, string>>,\n): string | undefined {\n\tlet match: { baseLength: number; icon: string } | undefined;\n\tfor (const [selector, icon] of Object.entries(configuredIcons)) {\n\t\tif (!selector.endsWith(\":*\")) continue;\n\t\tconst base = selector.slice(0, -2);\n\t\tif (!base || !key.startsWith(`${base}:`)) continue;\n\t\tif (!match || base.length > match.baseLength) match = { baseLength: base.length, icon };\n\t}\n\treturn match?.icon;\n}\n\nfunction extensionStatusAliasesForKey(\n\tkey: string,\n\textensionStatusIconAliases: ExtensionStatusIconAliasMap,\n): readonly string[] {\n\tfor (const [statusBase, aliases] of extensionStatusIconAliases) {\n\t\tif (statusKeyMatchesStatusBase(key, statusBase)) return aliases;\n\t}\n\treturn [];\n}\n\nfunction statusKeyMatchesStatusBase(key: string, statusBase: string): boolean {\n\treturn key === statusBase || key.startsWith(`${statusBase}:`) || key.startsWith(`${statusBase}/`);\n}\n\nexport function wrapExtensionStatusline(status: string, width: number): string[] {\n\tif (!status || width <= 0) return [];\n\treturn wrapTextWithAnsi(status, width);\n}\n\nfunction formatDuplicateExtensionStatus(runtime: ExtensionStatusRuntime, theme: Theme): string[] {\n\tif (runtime.duplicateExtensions.length === 0) return [];\n\tconst names = runtime.duplicateExtensions.slice(0, 2).join(\", \");\n\tconst suffix =\n\t\truntime.duplicateExtensions.length > 2 ? ` +${runtime.duplicateExtensions.length - 2}` : \"\";\n\treturn [`${theme.fg(\"warning\", \"\u26A0\uFE0F\")} ${theme.fg(\"warning\", `dup ${names}${suffix}`)}`];\n}\n\nexport function splitExtensionStatusIcon(value: string): { icon?: string; text: string } {\n\tconst trimmed = value.trim();\n\tconst [firstToken, ...restTokens] = trimmed.split(/\\s+/);\n\tif (firstToken && isEmojiOnlyToken(firstToken)) {\n\t\treturn { icon: firstToken, text: restTokens.join(\" \") };\n\t}\n\treturn { text: trimmed };\n}\n\nfunction isEmojiOnlyToken(value: string): boolean {\n\treturn /^(?=.*(?:\\p{Extended_Pictographic}|\\p{Regional_Indicator}|[0-9#*]\\ufe0f?\\u20e3))(?:\\p{Extended_Pictographic}|\\p{Emoji_Modifier}|\\p{Regional_Indicator}|\\u200d|\\ufe0f|[0-9#*]\\ufe0f?\\u20e3)+$/u.test(\n\t\tvalue,\n\t);\n}\n\nexport function extensionColor(key: string, value: string): ThemeColor {\n\tconst normalized = `${key} ${value}`.toLowerCase();\n\tif (/missing|error|fail|conflict|duplicate|unavailable/.test(normalized)) return \"warning\";\n\tif (normalized.includes(\"codex\")) return \"accent\";\n\tif (/ready|active|running|enabled|awake|ok/.test(normalized)) return \"success\";\n\treturn \"muted\";\n}\n\nexport function stripExtensionStatusPrefix(key: string, value: string): string {\n\treturn value.trim().replace(new RegExp(`^${escapeRegExp(key)}\\\\s*:\\\\s*`, \"iu\"), \"\");\n}\n\nexport function simplifyExtensionStatusText(value: string): string {\n\treturn value\n\t\t.trim()\n\t\t.replace(/\\bready\\b/giu, \"\u2713\")\n\t\t.replace(/\\bmissing\\b/giu, \"\u2717\")\n\t\t.replace(/,\\s*/g, \" \")\n\t\t.replace(/\\s+\\([^)]*\\)\\s*$/, \"\")\n\t\t.replace(/\\s+/g, \" \");\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\ninterface InstalledExtensionPackage {\n\tpackageName: string;\n\tsource: string;\n\tidentity: string;\n}\n\nexport function readInstalledExtensionPackages(cwd: string): InstalledExtensionPackage[] {\n\tconst packages: InstalledExtensionPackage[] = [];\n\tconst settingsFiles = extensionSettingsFiles(cwd);\n\n\tfor (const settingsFile of settingsFiles) {\n\t\tconst baseDirectory = dirname(settingsFile);\n\t\tfor (const rawSource of readPackageSources(settingsFile)) {\n\t\t\tconst source = rawSource.trim();\n\t\t\tif (!source) continue;\n\t\t\tconst packageName = packageNameForSource(source, baseDirectory);\n\t\t\tif (!packageName) continue;\n\t\t\tpackages.push({ packageName, source, identity: sourceIdentity(source, baseDirectory) });\n\t\t}\n\t}\n\n\treturn packages;\n}\n\nfunction extensionSettingsFiles(cwd: string): string[] {\n\treturn [join(getAgentDir(), \"settings.json\"), join(cwd, \".pi\", \"settings.json\")].filter((file) =>\n\t\texistsSync(file),\n\t);\n}\n\nexport function findDuplicateExtensions(\n\tinstalledPackages: readonly InstalledExtensionPackage[],\n): string[] {\n\tconst sourcesByPackage = new Map<string, Set<string>>();\n\n\tfor (const extensionPackage of installedPackages) {\n\t\tconst sources = sourcesByPackage.get(extensionPackage.packageName) ?? new Set<string>();\n\t\tsources.add(extensionPackage.identity);\n\t\tsourcesByPackage.set(extensionPackage.packageName, sources);\n\t}\n\n\treturn [...sourcesByPackage.entries()]\n\t\t.filter(([, sources]) => sources.size > 1)\n\t\t.map(([packageName]) => packageName.replace(/^@[^/]+\\//, \"\").replace(/^pi-/, \"\"));\n}\n\nexport function buildExtensionStatusIconAliases(\n\tinstalledPackages: readonly { packageName: string; source?: string }[],\n): Map<string, string[]> {\n\tconst packageAliasesByStatusBase = new Map<string, Map<string, string[]>>();\n\n\tfor (const extensionPackage of installedPackages) {\n\t\tconst candidate = extensionStatusIconAliasCandidate(\n\t\t\textensionPackage.packageName,\n\t\t\textensionPackage.source,\n\t\t);\n\t\tif (!candidate) continue;\n\t\tconst aliasesByPackage =\n\t\t\tpackageAliasesByStatusBase.get(candidate.statusBase) ?? new Map<string, string[]>();\n\t\tconst existingAliases = aliasesByPackage.get(extensionPackage.packageName) ?? [];\n\t\taliasesByPackage.set(\n\t\t\textensionPackage.packageName,\n\t\t\tuniqueStrings([...existingAliases, ...candidate.aliases]),\n\t\t);\n\t\tpackageAliasesByStatusBase.set(candidate.statusBase, aliasesByPackage);\n\t}\n\n\tconst aliases = new Map<string, string[]>();\n\tfor (const [statusBase, aliasesByPackage] of packageAliasesByStatusBase) {\n\t\tif (aliasesByPackage.size === 1)\n\t\t\taliases.set(statusBase, [...aliasesByPackage.values()][0] ?? []);\n\t}\n\treturn aliases;\n}\n\nfunction extensionStatusIconAliasCandidate(\n\tpackageName: string,\n\tsource?: string,\n): { statusBase: string; aliases: string[] } | undefined {\n\tconst packageBase = packageBaseName(packageName);\n\tconst statusBase = statusBaseFromPackageBase(packageBase);\n\tif (!statusBase) return undefined;\n\n\tconst sourceAliases = source?.startsWith(\"npm:\") ? [source, `npm:${npmPackageName(source)}`] : [];\n\treturn {\n\t\tstatusBase,\n\t\taliases: uniqueStrings([...sourceAliases, packageName, packageBase, statusBase]),\n\t};\n}\n\nfunction packageBaseName(packageName: string): string {\n\tconst slashIndex = packageName.lastIndexOf(\"/\");\n\treturn slashIndex === -1 ? packageName : packageName.slice(slashIndex + 1);\n}\n\nfunction statusBaseFromPackageBase(packageBase: string): string {\n\treturn packageBase.startsWith(\"pi-\") && packageBase.length > \"pi-\".length\n\t\t? packageBase.slice(\"pi-\".length)\n\t\t: packageBase;\n}\n\nfunction uniqueStrings(values: readonly string[]): string[] {\n\treturn [...new Set(values.filter((value) => value.length > 0))];\n}\n\nfunction readPackageSources(settingsFile: string): string[] {\n\ttry {\n\t\tconst settings = JSON.parse(readFileSync(settingsFile, \"utf8\")) as { packages?: unknown[] };\n\t\treturn (settings.packages ?? [])\n\t\t\t.map((entry) => {\n\t\t\t\tif (typeof entry === \"string\") return entry;\n\t\t\t\tif (\n\t\t\t\t\tentry &&\n\t\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\t\ttypeof (entry as { source?: unknown }).source === \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn (entry as { source: string }).source;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t})\n\t\t\t.filter((source): source is string => source !== undefined);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction packageNameForSource(source: string, baseDirectory: string): string | undefined {\n\tif (source.startsWith(\"npm:\")) return npmPackageName(source);\n\tconst packageJson = join(resolveSourcePath(source, baseDirectory), \"package.json\");\n\ttry {\n\t\tconst packageData = JSON.parse(readFileSync(packageJson, \"utf8\")) as { name?: unknown };\n\t\treturn typeof packageData.name === \"string\" ? packageData.name : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function npmPackageName(source: string): string {\n\tconst spec = source.slice(\"npm:\".length);\n\tif (spec.startsWith(\"@\")) return spec.split(\"@\").slice(0, 2).join(\"@\");\n\treturn spec.split(\"@\")[0] ?? spec;\n}\n\nfunction sourceIdentity(source: string, baseDirectory: string): string {\n\tif (source.startsWith(\"npm:\")) return `npm:${npmPackageName(source)}`;\n\treturn resolveSourcePath(source, baseDirectory);\n}\n\nfunction resolveSourcePath(source: string, baseDirectory: string): string {\n\treturn isAbsolute(source) ? source : resolve(baseDirectory, source);\n}\n", "import type { Theme } from \"@earendil-works/pi-coding-agent\";\nimport { visibleWidth } from \"@earendil-works/pi-tui\";\nimport { ansiStyle } from \"./ansi.js\";\nimport { resolvePreset } from \"./presets/index.js\";\nimport type { BlockColors, PowerlinePreset } from \"./presets/types.js\";\nimport {\n\tLINE_BREAK_SEGMENT_NAME,\n\ttype PalettePreset,\n\ttype PowerlineBlockName,\n\ttype RenderItem,\n\ttype RenderSegment,\n\ttype SegmentPalette,\n\ttype SeparatorName,\n\ttype StatuslineConfig,\n} from \"./types.js\";\n\ninterface PowerlineBlock {\n\tbaseBlock: PowerlineBlockName;\n\tcolors: BlockColors;\n\tsegments: RenderSegment[];\n}\n\nexport function renderPowerlineStatusline(\n\twidth: number,\n\titems: RenderItem[],\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n\ttrueColor = true,\n): string {\n\tif (items.length === 0 || width <= 0) return \"\";\n\treturn splitLines(items)\n\t\t.map((segments) => fitPowerlineSegments(segments, width, config, trueColor))\n\t\t.join(\"\\n\");\n}\n\nfunction splitLines(items: RenderItem[]): RenderSegment[][] {\n\tconst lines: RenderSegment[][] = [[]];\n\tfor (const item of items) {\n\t\tif (item.name === LINE_BREAK_SEGMENT_NAME) lines.push([]);\n\t\telse lines.at(-1)?.push(item);\n\t}\n\treturn lines;\n}\n\nconst SEGMENT_RETENTION_PRIORITY: Readonly<Record<RenderSegment[\"name\"], number>> = {\n\tcontext: 120,\n\tmodel: 110,\n\tbranch: 100,\n\ttools: 90,\n\tcwd: 80,\n\tthinking: 70,\n\tcost: 60,\n\tprovider: 50,\n\tcache: 45,\n\ttokens: 40,\n\ttime: 30,\n\tturn: 20,\n\tbrand: 10,\n};\n\nfunction fitPowerlineSegments(\n\tsegments: readonly RenderSegment[],\n\twidth: number,\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n\ttrueColor: boolean,\n): string {\n\tif (segments.length === 0) return \"\";\n\tconst fitted = [...segments];\n\twhile (fitted.length > 1) {\n\t\tconst rendered = joinPowerlineSegments(fitted, config, trueColor);\n\t\tif (visibleWidth(rendered) <= width) return rendered;\n\t\tlet removalIndex = 0;\n\t\tfor (let index = 1; index < fitted.length; index += 1) {\n\t\t\tconst candidate = fitted[index];\n\t\t\tconst current = fitted[removalIndex];\n\t\t\tif (\n\t\t\t\tcandidate &&\n\t\t\t\tcurrent &&\n\t\t\t\tSEGMENT_RETENTION_PRIORITY[candidate.name] < SEGMENT_RETENTION_PRIORITY[current.name]\n\t\t\t) {\n\t\t\t\tremovalIndex = index;\n\t\t\t}\n\t\t}\n\t\tfitted.splice(removalIndex, 1);\n\t}\n\tconst rendered = joinPowerlineSegments(fitted, config, trueColor);\n\treturn visibleWidth(rendered) <= width ? rendered : \"\";\n}\n\nexport function powerlineExtensionSeparator(\n\t_theme: Theme,\n\tpalettePreset: PalettePreset = \"tokyo-night\",\n\ttrueColor = true,\n): string {\n\treturn ansiStyle(\" \u2022 \", { fg: resolvePreset(palettePreset).extensionSeparator }, trueColor);\n}\n\nfunction joinPowerlineSegments(\n\tsegments: RenderSegment[],\n\tconfig: Pick<StatuslineConfig, \"palettePreset\" | \"palette\" | \"density\" | \"separator\">,\n\ttrueColor: boolean,\n): string {\n\tconst preset = resolvePreset(config.palettePreset);\n\tconst blocks = contiguousBlocks(segments, preset, config.palettePreset, config.palette);\n\tlet line = ansiStyle(\"\u2591\u2592\u2593\", { fg: preset.lead }, trueColor);\n\n\tfor (const [index, block] of blocks.entries()) {\n\t\tconst previous = index === 0 ? undefined : blocks[index - 1]?.colors;\n\t\tif (previous) {\n\t\t\tline += ansiStyle(\"\uE0B4\", { fg: previous.bg, bg: block.colors.bg }, trueColor);\n\t\t}\n\t\tline += ansiStyle(formatBlockText(block, config), block.colors, trueColor);\n\t}\n\n\tconst lastBlock = blocks.at(-1);\n\tif (lastBlock) line += ansiStyle(\"\uE0B4\", { fg: lastBlock.colors.bg }, trueColor);\n\treturn line;\n}\n\nfunction contiguousBlocks(\n\tsegments: RenderSegment[],\n\tpreset: PowerlinePreset,\n\tpalettePreset: PalettePreset,\n\tconfiguredPalette: SegmentPalette,\n): PowerlineBlock[] {\n\tconst blocks: PowerlineBlock[] = [];\n\tconst usesConfiguredColors = palettePreset === \"custom\";\n\tfor (const segment of segments) {\n\t\tconst colors = usesConfiguredColors\n\t\t\t? (configuredPalette[segment.name] ?? {})\n\t\t\t: preset.blocks[segment.block];\n\t\tconst previous = blocks.at(-1);\n\t\tconst matchesPrevious =\n\t\t\tprevious !== undefined &&\n\t\t\t(usesConfiguredColors\n\t\t\t\t? colorsEqual(previous.colors, colors)\n\t\t\t\t: previous.baseBlock === segment.block);\n\t\tif (matchesPrevious) previous.segments.push(segment);\n\t\telse blocks.push({ baseBlock: segment.block, colors, segments: [segment] });\n\t}\n\treturn blocks;\n}\n\nfunction colorsEqual(left: BlockColors, right: BlockColors): boolean {\n\treturn left.fg === right.fg && left.bg === right.bg;\n}\n\nfunction formatBlockText(\n\tblock: PowerlineBlock,\n\tconfig: Pick<StatuslineConfig, \"density\" | \"separator\">,\n): string {\n\tconst texts = block.segments.map(formatSegmentText);\n\tconst separator = separatorText(config.separator, config.density === \"cozy\");\n\tconst leading = config.density === \"cozy\" ? \" \" : \" \";\n\tconst trailing = config.density === \"cozy\" ? \" \" : \"\";\n\treturn `${leading}${texts.join(separator)}${trailing}`;\n}\n\nfunction formatSegmentText(segment: RenderSegment): string {\n\treturn segment.emphasis ? `\\u001b[1m${segment.text}\\u001b[22m` : segment.text;\n}\n\nfunction separatorText(separator: SeparatorName, cozy: boolean): string {\n\tconst padding = cozy ? \" \" : \" \";\n\tswitch (separator) {\n\t\tcase \"dot\":\n\t\t\treturn `${padding}\u2022${padding}`;\n\t\tcase \"bar\":\n\t\t\treturn `${padding}\u2502${padding}`;\n\t\tcase \"powerline\":\n\t\t\treturn `${padding}\uE0B1${padding}`;\n\t\tcase \"round\":\n\t\t\treturn `${padding}\u276F${padding}`;\n\t\tcase \"none\":\n\t\t\treturn padding;\n\t}\n}\n", "export function ansiStyle(\n\ttext: string,\n\tcolors: { fg?: string; bg?: string },\n\ttrueColor = true,\n): string {\n\tconst codes = [\n\t\tcolors.fg ? colorCode(\"38\", colors.fg, trueColor) : undefined,\n\t\tcolors.bg ? colorCode(\"48\", colors.bg, trueColor) : undefined,\n\t].filter((code): code is string => code !== undefined);\n\tif (codes.length === 0) return text;\n\treturn `\\u001b[${codes.join(\";\")}m${text}\\u001b[0m`;\n}\n\nexport function ansiFg(hex: string, text: string, trueColor = true): string {\n\treturn ansiStyle(text, { fg: hex }, trueColor);\n}\n\nfunction colorCode(prefix: \"38\" | \"48\", hex: string, trueColor: boolean): string {\n\tconst { red, green, blue } = hexToRgb(hex);\n\treturn trueColor\n\t\t? `${prefix};2;${red};${green};${blue}`\n\t\t: `${prefix};5;${rgbToAnsi256(red, green, blue)}`;\n}\n\nfunction rgbToAnsi256(red: number, green: number, blue: number): number {\n\tconst channels = [red, green, blue].map((value) => Math.round((value / 255) * 5));\n\treturn 16 + 36 * (channels[0] ?? 0) + 6 * (channels[1] ?? 0) + (channels[2] ?? 0);\n}\n\nfunction hexToRgb(hex: string): { red: number; green: number; blue: number } {\n\tconst normalized = hex.replace(/^#/, \"\");\n\treturn {\n\t\tred: Number.parseInt(normalized.slice(0, 2), 16),\n\t\tgreen: Number.parseInt(normalized.slice(2, 4), 16),\n\t\tblue: Number.parseInt(normalized.slice(4, 6), 16),\n\t};\n}\n", "import { isAbsolute } from \"node:path\";\nimport type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\n\nconst GIT_STATUS_TIMEOUT_MS = 3_000;\n\nexport interface GitStatusSummary {\n\troot?: string;\n\tahead: number;\n\tbehind: number;\n\tstaged: number;\n\tmodified: number;\n\tuntracked: number;\n\tconflicts: number;\n}\n\nexport async function readGitStatus(\n\tpi: ExtensionAPI,\n\tcwd: string,\n\tsignal?: AbortSignal,\n): Promise<GitStatusSummary | undefined> {\n\tconst [statusResult, rootResult] = await Promise.all([\n\t\tpi.exec(\n\t\t\t\"git\",\n\t\t\t[\"--no-optional-locks\", \"status\", \"--porcelain=v1\", \"--branch\", \"--untracked-files=normal\"],\n\t\t\t{ cwd, timeout: GIT_STATUS_TIMEOUT_MS, signal },\n\t\t),\n\t\tpi\n\t\t\t.exec(\"git\", [\"rev-parse\", \"--path-format=absolute\", \"--show-toplevel\"], {\n\t\t\t\tcwd,\n\t\t\t\ttimeout: GIT_STATUS_TIMEOUT_MS,\n\t\t\t\tsignal,\n\t\t\t})\n\t\t\t.catch(() => undefined),\n\t]);\n\tif (statusResult.code !== 0 || statusResult.killed) return undefined;\n\tconst summary = parseGitStatusPorcelain(statusResult.stdout);\n\tif (rootResult && rootResult.code === 0 && !rootResult.killed) {\n\t\tconst root = parseGitRoot(rootResult.stdout);\n\t\tif (root) summary.root = root;\n\t}\n\treturn summary;\n}\n\nexport function parseGitStatusPorcelain(output: string): GitStatusSummary {\n\tconst summary: GitStatusSummary = {\n\t\tahead: 0,\n\t\tbehind: 0,\n\t\tstaged: 0,\n\t\tmodified: 0,\n\t\tuntracked: 0,\n\t\tconflicts: 0,\n\t};\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tif (!line) continue;\n\t\tif (line.startsWith(\"## \")) {\n\t\t\tconst ahead = line.match(/\\bahead (\\d+)/u);\n\t\t\tconst behind = line.match(/\\bbehind (\\d+)/u);\n\t\t\tsummary.ahead = ahead ? Number(ahead[1]) : 0;\n\t\t\tsummary.behind = behind ? Number(behind[1]) : 0;\n\t\t\tcontinue;\n\t\t}\n\t\tconst indexStatus = line[0] ?? \" \";\n\t\tconst worktreeStatus = line[1] ?? \" \";\n\t\tif (indexStatus === \"?\" && worktreeStatus === \"?\") {\n\t\t\tsummary.untracked += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isConflictStatus(indexStatus, worktreeStatus)) {\n\t\t\tsummary.conflicts += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isChangedStatus(indexStatus)) summary.staged += 1;\n\t\tif (isChangedStatus(worktreeStatus)) summary.modified += 1;\n\t}\n\treturn summary;\n}\n\nfunction isConflictStatus(indexStatus: string, worktreeStatus: string): boolean {\n\treturn (\n\t\t(indexStatus === \"D\" && worktreeStatus === \"D\") ||\n\t\t(indexStatus === \"A\" && worktreeStatus === \"A\") ||\n\t\tindexStatus === \"U\" ||\n\t\tworktreeStatus === \"U\"\n\t);\n}\n\nfunction isChangedStatus(status: string): boolean {\n\treturn status !== \" \" && status !== \"?\" && status !== \"!\";\n}\n\nexport function parseGitRoot(output: string): string | undefined {\n\tconst root = output.split(/\\r?\\n/u)[0]?.trim();\n\treturn root && isAbsolute(root) ? root : undefined;\n}\n\nexport function formatGitStatusSummary(summary: GitStatusSummary | undefined): string {\n\tif (!summary) return \"\";\n\tconst tokens = [\n\t\t[\"\u21E1\", summary.ahead],\n\t\t[\"\u21E3\", summary.behind],\n\t\t[\"+\", summary.staged],\n\t\t[\"~\", summary.modified],\n\t\t[\"?\", summary.untracked],\n\t\t[\"!\", summary.conflicts],\n\t] as const;\n\treturn tokens\n\t\t.filter(([, count]) => count > 0)\n\t\t.map(([prefix, count]) => `${prefix}${formatCount(count)}`)\n\t\t.join(\" \");\n}\n\nexport function formatGitBranchValue(\n\tbranch: string | null,\n\tstatus: GitStatusSummary | undefined,\n\tpr?: string,\n): string {\n\tif (!branch) return \"no-git\";\n\tconst suffixes = [formatGitStatusSummary(status), pr ? `(${pr})` : \"\"].filter(Boolean);\n\treturn suffixes.length > 0 ? `${branch} ${suffixes.join(\" \")}` : branch;\n}\n\nexport function formatGitBranchText(\n\tbranch: string | null,\n\tstatus: GitStatusSummary | undefined,\n\tpr?: string,\n): string {\n\treturn `\uD83C\uDF3F ${formatGitBranchValue(branch, status, pr)}`;\n}\n\nexport function gitStatusSummaryEqual(\n\tleft: GitStatusSummary | undefined,\n\tright: GitStatusSummary | undefined,\n): boolean {\n\tif (!left || !right) return left === right;\n\treturn (\n\t\tleft.root === right.root &&\n\t\tleft.ahead === right.ahead &&\n\t\tleft.behind === right.behind &&\n\t\tleft.staged === right.staged &&\n\t\tleft.modified === right.modified &&\n\t\tleft.untracked === right.untracked &&\n\t\tleft.conflicts === right.conflicts\n\t);\n}\n\nfunction formatCount(value: number): string {\n\treturn Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 }).format(value);\n}\n", "import type {\n\tExtensionAPI,\n\tExtensionContext,\n\tReadonlyFooterDataProvider,\n\tTheme,\n\tThemeColor,\n\tUIPromptKind,\n} from \"@earendil-works/pi-coding-agent\";\nimport { sliceByColumn, visibleWidth } from \"@earendil-works/pi-tui\";\nimport { sanitizeTerminalText } from \"@narumitw/pi-tui-kit/terminal-text\";\nimport { formatDirectoryPath } from \"./directory.js\";\nimport {\n\ttype ExtensionStatusRuntime,\n\tformatExtensionStatuses,\n\twrapExtensionStatusline,\n} from \"./extension-status.js\";\nimport { formatGitBranchValue, type GitStatusSummary } from \"./git-status.js\";\nimport { renderPowerlineStatusline } from \"./powerline.js\";\nimport {\n\tLINE_BREAK_SEGMENT_NAME,\n\ttype PowerlineBlockName,\n\ttype RenderItem,\n\ttype RenderSegment,\n\ttype SegmentName,\n\ttype StatuslineConfig,\n\ttype TruncationDirection,\n} from \"./types.js\";\nimport { type FooterUsageSummary, summarizeFooterUsage } from \"./usage.js\";\n\ntype ThinkingLevel = ReturnType<ExtensionAPI[\"getThinkingLevel\"]>;\nexport interface RuntimeState extends ExtensionStatusRuntime {\n\thomeDir?: string;\n\tturnCount: number;\n\tactiveTools: Map<string, number>;\n\tisStreaming: boolean;\n\tuiPrompt?: { kind: UIPromptKind; title?: string };\n\tthinkingLevel: ThinkingLevel;\n\tgitStatus?: GitStatusSummary;\n\trequestRender?: () => void;\n}\nconst GITHUB_PR_KEY = \"github-pr\";\nconst GITHUB_PR_STATUS_KEYS = new Set([GITHUB_PR_KEY]);\nexport function renderStatusline(\n\twidth: number,\n\tctx: ExtensionContext,\n\tfooterData: ReadonlyFooterDataProvider,\n\t_theme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n\ttrueColor = true,\n): string {\n\tif (width <= 0) return \"\";\n\n\tconst usageSummary = summarizeFooterUsage(ctx.sessionManager.getEntries());\n\tconst rows: Array<{ configuredSegments: number; segments: RenderSegment[] }> = [\n\t\t{ configuredSegments: 0, segments: [] },\n\t];\n\tfor (const name of config.segments) {\n\t\tif (name === LINE_BREAK_SEGMENT_NAME) {\n\t\t\trows.push({ configuredSegments: 0, segments: [] });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst row = rows.at(-1);\n\t\tif (!row) continue;\n\t\trow.configuredSegments += 1;\n\t\tconst rendered = buildSegment(name, ctx, footerData, config, runtime, usageSummary);\n\t\tif (rendered && rendered.text.length > 0) row.segments.push(rendered);\n\t}\n\n\tconst segments: RenderItem[] = [];\n\tconst renderedRows = rows.filter(\n\t\t(row) => row.configuredSegments === 0 || row.segments.length > 0,\n\t);\n\tfor (const [index, row] of renderedRows.entries()) {\n\t\tif (index > 0) segments.push({ name: LINE_BREAK_SEGMENT_NAME });\n\t\tsegments.push(...row.segments);\n\t}\n\n\treturn renderPowerlineStatusline(width, segments, config, trueColor);\n}\n\nexport function renderExtensionStatusline(\n\twidth: number,\n\tfooterData: ReadonlyFooterDataProvider,\n\ttheme: Theme,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n\tmainLine: string,\n\ttrueColor = true,\n): string[] {\n\tconst statuses = footerData.getExtensionStatuses();\n\tconst prContext = prContextFromStatuses(statuses);\n\tconst rendersPrInline = prContext !== undefined && mainLine.includes(prContext);\n\tconst status = formatExtensionStatuses(\n\t\tstatuses,\n\t\ttheme,\n\t\tconfig,\n\t\truntime,\n\t\trendersPrInline ? GITHUB_PR_STATUS_KEYS : undefined,\n\t\ttrueColor,\n\t);\n\treturn wrapExtensionStatusline(status, width);\n}\n\nfunction buildSegment(\n\tname: SegmentName,\n\tctx: ExtensionContext,\n\tfooterData: ReadonlyFooterDataProvider,\n\tconfig: StatuslineConfig,\n\truntime: RuntimeState,\n\tusageSummary: FooterUsageSummary,\n): RenderSegment | undefined {\n\tswitch (name) {\n\t\tcase \"brand\":\n\t\t\treturn segment(name, \"\u03C0\", config, \"accent\", \"header\", true);\n\t\tcase \"provider\":\n\t\t\treturn segment(name, ctx.model?.provider ?? \"no-provider\", config, \"accent\", \"header\");\n\t\tcase \"model\": {\n\t\t\tconst presentation = config.segmentText.model;\n\t\t\tconst model = truncateModel(\n\t\t\t\tshortenModel(ctx.model?.id ?? \"no-model\"),\n\t\t\t\tpresentation.truncationLength,\n\t\t\t\tpresentation.truncationSymbol,\n\t\t\t\tpresentation.truncationDirection,\n\t\t\t);\n\t\t\treturn segment(name, model, config, \"accent\", \"header\");\n\t\t}\n\t\tcase \"thinking\":\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\truntime.thinkingLevel,\n\t\t\t\tconfig,\n\t\t\t\tthinkingColor(runtime.thinkingLevel),\n\t\t\t\t\"header\",\n\t\t\t);\n\t\tcase \"branch\": {\n\t\t\tconst branch = footerData.getGitBranch();\n\t\t\tconst pr = branch ? prContextFromStatuses(footerData.getExtensionStatuses()) : undefined;\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\tformatGitBranchValue(branch, runtime.gitStatus, pr),\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"git\",\n\t\t\t);\n\t\t}\n\t\tcase \"cwd\":\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\tformatDirectoryPath(ctx.cwd, runtime.homeDir, runtime.gitStatus?.root),\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"directory\",\n\t\t\t);\n\t\tcase \"tools\": {\n\t\t\tconst activity = formatToolActivity(runtime);\n\t\t\treturn activity ? segment(name, activity, config, \"accent\", \"runtime\") : undefined;\n\t\t}\n\t\tcase \"context\": {\n\t\t\tconst usage = ctx.getContextUsage();\n\t\t\tconst percentage =\n\t\t\t\tusage?.percent === null || usage?.percent === undefined\n\t\t\t\t\t? \"?\"\n\t\t\t\t\t: `${usage.percent.toFixed(1)}%`;\n\t\t\tconst contextWindow = usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\t`${percentage}/${formatCount(contextWindow)}`,\n\t\t\t\tconfig,\n\t\t\t\tcontextColor(usage?.percent),\n\t\t\t\t\"runtime\",\n\t\t\t);\n\t\t}\n\t\tcase \"tokens\": {\n\t\t\tconst value =\n\t\t\t\tusageSummary.input === 0 && usageSummary.output === 0\n\t\t\t\t\t? \"tok 0\"\n\t\t\t\t\t: `\u2191${formatCount(usageSummary.input)} \u2193${formatCount(usageSummary.output)}`;\n\t\t\treturn segment(name, value, config, \"accent\", \"runtime\");\n\t\t}\n\t\tcase \"cache\": {\n\t\t\tif (usageSummary.cacheRead === 0 && usageSummary.cacheWrite === 0) return undefined;\n\t\t\tconst values: string[] = [];\n\t\t\tif (usageSummary.cacheRead > 0) values.push(`R${formatCount(usageSummary.cacheRead)}`);\n\t\t\tif (usageSummary.cacheWrite > 0) values.push(`W${formatCount(usageSummary.cacheWrite)}`);\n\t\t\tif (usageSummary.latestCacheHitRate !== undefined) {\n\t\t\t\tvalues.push(`CH${usageSummary.latestCacheHitRate.toFixed(1)}%`);\n\t\t\t}\n\t\t\treturn segment(name, values.join(\" \"), config, \"accent\", \"runtime\");\n\t\t}\n\t\tcase \"cost\": {\n\t\t\tconst subscription = isSubscriptionBacked(ctx) ? \" (sub)\" : \"\";\n\t\t\treturn segment(\n\t\t\t\tname,\n\t\t\t\t`${usageSummary.cost.toFixed(usageSummary.cost >= 1 ? 2 : 3)}${subscription}`,\n\t\t\t\tconfig,\n\t\t\t\t\"accent\",\n\t\t\t\t\"meter\",\n\t\t\t);\n\t\t}\n\t\tcase \"time\":\n\t\t\treturn segment(name, formatTime(), config, \"accent\", \"meter\");\n\t\tcase \"turn\":\n\t\t\treturn segment(name, `${runtime.turnCount}`, config, \"accent\", \"meter\");\n\t}\n}\n\nfunction segment(\n\tname: SegmentName,\n\tvalue: string,\n\tconfig: StatuslineConfig,\n\tcolor: RenderSegment[\"color\"],\n\tblock: PowerlineBlockName,\n\temphasis = false,\n): RenderSegment {\n\treturn { name, text: formatConfiguredSegment(name, value, config), color, block, emphasis };\n}\n\nexport function formatConfiguredSegment(\n\tname: SegmentName,\n\tvalue: string,\n\tconfig: Pick<StatuslineConfig, \"segmentText\">,\n): string {\n\tconst presentation = config.segmentText[name];\n\treturn `${presentation.prefix}${value}${presentation.suffix}`;\n}\n\nfunction thinkingColor(level: ThinkingLevel): ThemeColor {\n\tswitch (level as string) {\n\t\tcase \"off\":\n\t\t\treturn \"dim\";\n\t\tcase \"minimal\":\n\t\t\treturn \"thinkingMinimal\";\n\t\tcase \"low\":\n\t\t\treturn \"thinkingLow\";\n\t\tcase \"medium\":\n\t\t\treturn \"thinkingMedium\";\n\t\tcase \"high\":\n\t\t\treturn \"thinkingHigh\";\n\t\tcase \"xhigh\":\n\t\t\treturn \"thinkingXhigh\";\n\t\tcase \"max\":\n\t\t\treturn \"thinkingMax\" as ThemeColor;\n\t\tdefault:\n\t\t\treturn \"dim\";\n\t}\n}\n\nexport function contextColor(percent: number | null | undefined): ThemeColor {\n\tif (percent === null || percent === undefined) return \"dim\";\n\tif (percent >= 90) return \"error\";\n\tif (percent >= 70) return \"warning\";\n\treturn \"success\";\n}\n\nconst MAX_UI_PROMPT_TITLE_CODE_POINTS = 256;\nconst MAX_UI_PROMPT_TITLE_WIDTH = 40;\n\nfunction boundUIPromptTitleLength(title: string): string {\n\tlet end = 0;\n\tlet ellipsisEnd = 0;\n\tlet codePoints = 0;\n\twhile (end < title.length && codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) {\n\t\tconst codePoint = title.codePointAt(end) ?? 0;\n\t\tend += codePoint > 0xffff ? 2 : 1;\n\t\tcodePoints += 1;\n\t\tif (codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) ellipsisEnd = end;\n\t}\n\treturn end < title.length ? `${title.slice(0, ellipsisEnd)}\u2026` : title;\n}\n\nfunction formatUIPromptTitle(title: string | undefined): string {\n\tconst safeTitle = title ? sanitizeTerminalText(title).trim() : \"\";\n\tconst boundedTitle = boundUIPromptTitleLength(safeTitle);\n\tif (visibleWidth(boundedTitle) <= MAX_UI_PROMPT_TITLE_WIDTH) return boundedTitle;\n\treturn `${sliceByColumn(boundedTitle, 0, MAX_UI_PROMPT_TITLE_WIDTH - 1, true)}\u2026`;\n}\n\nexport function formatToolActivity(runtime: RuntimeState): string | undefined {\n\tif (runtime.uiPrompt) {\n\t\tconst title = formatUIPromptTitle(runtime.uiPrompt.title);\n\t\treturn `\u2328 waiting for ${runtime.uiPrompt.kind}${title ? ` \u00B7 ${title}` : \"\"}`;\n\t}\n\n\tconst active = [...runtime.activeTools.entries()];\n\tif (active.length > 0) {\n\t\tconst [name, count] = active[0] ?? [\"tool\", 1];\n\t\tconst suffix = count > 1 ? `\u00D7${count}` : active.length > 1 ? `+${active.length - 1}` : \"\";\n\t\treturn `\u2699\uFE0F ${name}${suffix}`;\n\t}\n\n\treturn runtime.isStreaming ? \"\uD83D\uDCAD thinking\" : undefined;\n}\n\nexport function prLinkFromStatuses(statuses: ReadonlyMap<string, string>): string | undefined {\n\tconst value = statuses.get(GITHUB_PR_KEY);\n\tif (!value) return undefined;\n\t// Extract the OSC 8 hyperlink span (the clickable \"#123\"); skip non-PR states\n\t// like \"PR gh missing\" that carry no link. github-pr emits exactly one link, so the\n\t// first OSC 8 span is the PR number.\n\tconst open = value.indexOf(\"\\x1b]8;;\");\n\tif (open === -1) return undefined;\n\tconst closeMarker = \"\\x1b]8;;\\x07\";\n\tconst close = value.indexOf(closeMarker, open + 1);\n\treturn close === -1 ? undefined : value.slice(open, close + closeMarker.length);\n}\n\nexport function prContextFromStatuses(statuses: ReadonlyMap<string, string>): string | undefined {\n\tconst value = statuses.get(GITHUB_PR_KEY);\n\tif (!value) return undefined;\n\tconst link = prLinkFromStatuses(statuses);\n\tconst reference = link ?? plainPrReference(value);\n\tif (!reference) return undefined;\n\n\tconst state = compactPrState(link ? value.replace(link, \"\") : value);\n\treturn state ? `${reference} \u00B7 ${state}` : undefined;\n}\n\nfunction plainPrReference(value: string): string | undefined {\n\treturn /^PR\\s+(#\\d+):/u.exec(value)?.[1];\n}\n\nfunction compactPrState(value: string): string | undefined {\n\tif (/:\\s*merged\\s*$/.test(value)) return \"merged\";\n\tif (/:\\s*closed\\s*$/.test(value)) return \"closed\";\n\tif (/\\bdraft\\b/.test(value)) return \"draft\";\n\n\tconst failing = /\\bchecks failing \\((\\d+)\\)/.exec(value);\n\tif (failing) return `${failing[1]} failing`;\n\tif (/\\bchanges requested\\b/.test(value)) return \"changes requested\";\n\n\tconst pending = /\\bchecks pending \\((\\d+)\\)/.exec(value);\n\tif (pending) return `${pending[1]} pending`;\n\tif (/\\bapproved\\b/.test(value)) return \"approved\";\n\tif (/\\breview required\\b/.test(value)) return \"review required\";\n\tif (/\\bchecks passing\\b/.test(value)) return \"checks passing\";\n\tif (/\\bno checks\\b/.test(value)) return \"no checks\";\n\treturn undefined;\n}\n\nfunction isSubscriptionBacked(ctx: ExtensionContext): boolean {\n\tconst model = ctx.model;\n\treturn (\n\t\tmodel !== undefined &&\n\t\t(model.provider === \"kimi-coding\" || ctx.modelRegistry.isUsingOAuth(model))\n\t);\n}\n\nexport function formatCount(value: number): string {\n\tif (value < 1000) return `${value}`;\n\tif (value < 1_000_000) return `${(value / 1000).toFixed(value < 10_000 ? 1 : 0)}k`;\n\treturn `${(value / 1_000_000).toFixed(1)}m`;\n}\n\nfunction formatTime(): string {\n\tconst now = new Date();\n\tconst hours = now.getHours().toString().padStart(2, \"0\");\n\tconst minutes = now.getMinutes().toString().padStart(2, \"0\");\n\treturn `${hours}:${minutes}`;\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function truncateModel(\n\tmodel: string,\n\tlength: number,\n\tsymbol: string,\n\tdirection: TruncationDirection,\n): string {\n\tconst safeModel = sanitizeTerminalText(model);\n\tif (length === 0) return safeModel;\n\tconst graphemes = [...graphemeSegmenter.segment(safeModel)].map(({ segment }) => segment);\n\tif (graphemes.length <= length) return safeModel;\n\tconst safeSymbol = sanitizeTerminalText(symbol);\n\n\tswitch (direction) {\n\t\tcase \"start\":\n\t\t\treturn `${safeSymbol}${graphemes.slice(-length).join(\"\")}`;\n\t\tcase \"middle\": {\n\t\t\tconst headLength = Math.ceil(length / 2);\n\t\t\tconst tailLength = Math.floor(length / 2);\n\t\t\tconst tail = tailLength > 0 ? graphemes.slice(-tailLength).join(\"\") : \"\";\n\t\t\treturn `${graphemes.slice(0, headLength).join(\"\")}${safeSymbol}${tail}`;\n\t\t}\n\t\tcase \"end\":\n\t\t\treturn `${graphemes.slice(0, length).join(\"\")}${safeSymbol}`;\n\t}\n}\n\nexport function shortenModel(model: string): string {\n\treturn model\n\t\t.replace(/^claude-/, \"\")\n\t\t.replace(/^gpt-/, \"gpt \")\n\t\t.replace(/-20\\d{6}$/, \"\")\n\t\t.replace(/-latest$/, \"\");\n}\n", "import { basename, isAbsolute, relative, sep } from \"node:path\";\nimport { sanitizeTerminalText } from \"@narumitw/pi-tui-kit/terminal-text\";\n\nconst DEFAULT_TRUNCATION_LENGTH = 3;\nconst DEFAULT_HOME_SYMBOL = \"~\";\n\n/** Apply Starship's default directory presentation without exposing a format language. */\nexport function formatDirectoryPath(\n\tcwd: string,\n\thomeDir: string | undefined,\n\tgitRoot: string | undefined,\n): string {\n\tconst contracted =\n\t\tgitRoot && (!homeDir || !samePath(gitRoot, homeDir))\n\t\t\t? (contractRepositoryPath(cwd, gitRoot) ?? contractPath(cwd, homeDir, DEFAULT_HOME_SYMBOL))\n\t\t\t: contractPath(cwd, homeDir, DEFAULT_HOME_SYMBOL);\n\tconst safeContracted = sanitizeTerminalText(contracted);\n\tconst components = safeContracted.split(\"/\").filter((component) => component.length > 0);\n\tconst displayed =\n\t\tcomponents.length > DEFAULT_TRUNCATION_LENGTH\n\t\t\t? components.slice(-DEFAULT_TRUNCATION_LENGTH).join(\"/\")\n\t\t\t: safeContracted;\n\tconst native = sep === \"/\" ? displayed : displayed.replaceAll(\"/\", sep);\n\treturn sanitizeTerminalText(native || basename(cwd) || cwd);\n}\n\nfunction toSlashPath(value: string): string {\n\treturn sep === \"\\\\\" ? value.replaceAll(\"\\\\\", \"/\") : value;\n}\n\nfunction contractPath(path: string, root: string | undefined, replacement: string): string {\n\tif (!root) return toSlashPath(path);\n\tconst child = relativeWithin(path, root);\n\tif (child === undefined) return toSlashPath(path);\n\treturn child ? `${replacement}/${child}` : replacement;\n}\n\nfunction contractRepositoryPath(path: string, root: string): string | undefined {\n\tconst child = relativeWithin(path, root);\n\tif (child === undefined) return undefined;\n\tconst name = basename(root) || toSlashPath(root);\n\treturn child ? `${name}/${child}` : name;\n}\n\nfunction relativeWithin(path: string, root: string): string | undefined {\n\tconst child = relative(root, path);\n\tif (child === \"\") return \"\";\n\tif (child === \"..\" || child.startsWith(`..${sep}`) || isAbsolute(child)) return undefined;\n\treturn toSlashPath(child);\n}\n\nfunction samePath(left: string, right: string): boolean {\n\treturn relative(left, right) === \"\";\n}\n", "import type { SessionEntry } from \"@earendil-works/pi-coding-agent\";\n\ninterface UsageLike {\n\tinput?: number;\n\toutput?: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\tcost?: { total?: number };\n}\n\nexport interface FooterUsageSummary {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n\tlatestCacheHitRate?: number;\n}\n\nexport function summarizeFooterUsage(entries: readonly SessionEntry[]): FooterUsageSummary {\n\tconst totals: FooterUsageSummary = {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n\n\tfor (const entry of entries) {\n\t\tlet usage: UsageLike | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tusage = entry.message.usage;\n\t\t\tconst input = usage.input ?? 0;\n\t\t\tconst cacheRead = usage.cacheRead ?? 0;\n\t\t\tconst cacheWrite = usage.cacheWrite ?? 0;\n\t\t\tconst promptTokens = input + cacheRead + cacheWrite;\n\t\t\ttotals.latestCacheHitRate = promptTokens > 0 ? (cacheRead / promptTokens) * 100 : undefined;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\") {\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"compaction\" || entry.type === \"branch_summary\") {\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!usage) continue;\n\n\t\ttotals.input += usage.input ?? 0;\n\t\ttotals.output += usage.output ?? 0;\n\t\ttotals.cacheRead += usage.cacheRead ?? 0;\n\t\ttotals.cacheWrite += usage.cacheWrite ?? 0;\n\t\ttotals.cost += usage.cost?.total ?? 0;\n\t}\n\n\treturn totals;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["getAgentDir", "rendered", "segment", "isAbsolute", "visibleWidth", "sanitizeTerminalText", "isAbsolute", "formatCount", "sanitizeTerminalText", "visibleWidth", "segment", "STATUSLINE_KEY", "EMPTY_EXTENSION_STATUS_ICON_ALIASES", "getAgentDir"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-statusline",
3
- "version": "0.49.15",
3
+ "version": "0.50.0",
4
4
  "description": "Pi extension that replaces the footer with an information-rich statusline.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,9 +23,6 @@
23
23
  "./dist/index.ts"
24
24
  ]
25
25
  },
26
- "piExtension": {
27
- "lifecycle": "stable"
28
- },
29
26
  "scripts": {
30
27
  "build": "node scripts/build-runtime.mjs",
31
28
  "check": "npm run build && biome check --vcs-use-ignore-file=false src test scripts package.json tsconfig.json README.md && npm run typecheck",
@@ -38,10 +35,10 @@
38
35
  "@earendil-works/pi-tui": "*"
39
36
  },
40
37
  "devDependencies": {
41
- "@biomejs/biome": "2.5.10",
42
- "@earendil-works/pi-coding-agent": "0.84.3",
43
- "@earendil-works/pi-tui": "0.84.3",
44
- "@types/node": "26.2.0",
38
+ "@biomejs/biome": "2.5.11",
39
+ "@earendil-works/pi-coding-agent": "0.84.4",
40
+ "@earendil-works/pi-tui": "0.84.4",
41
+ "@types/node": "26.4.0",
45
42
  "esbuild": "0.28.2",
46
43
  "typescript": "7.0.2"
47
44
  },
package/src/ansi.ts CHANGED
@@ -1,19 +1,30 @@
1
- export function ansiStyle(text: string, colors: { fg?: string; bg?: string }): string {
1
+ export function ansiStyle(
2
+ text: string,
3
+ colors: { fg?: string; bg?: string },
4
+ trueColor = true,
5
+ ): string {
2
6
  const codes = [
3
- colors.fg ? truecolorCode("38", colors.fg) : undefined,
4
- colors.bg ? truecolorCode("48", colors.bg) : undefined,
7
+ colors.fg ? colorCode("38", colors.fg, trueColor) : undefined,
8
+ colors.bg ? colorCode("48", colors.bg, trueColor) : undefined,
5
9
  ].filter((code): code is string => code !== undefined);
6
10
  if (codes.length === 0) return text;
7
11
  return `\u001b[${codes.join(";")}m${text}\u001b[0m`;
8
12
  }
9
13
 
10
- export function ansiFg(hex: string, text: string): string {
11
- return ansiStyle(text, { fg: hex });
14
+ export function ansiFg(hex: string, text: string, trueColor = true): string {
15
+ return ansiStyle(text, { fg: hex }, trueColor);
12
16
  }
13
17
 
14
- function truecolorCode(prefix: "38" | "48", hex: string): string {
18
+ function colorCode(prefix: "38" | "48", hex: string, trueColor: boolean): string {
15
19
  const { red, green, blue } = hexToRgb(hex);
16
- return `${prefix};2;${red};${green};${blue}`;
20
+ return trueColor
21
+ ? `${prefix};2;${red};${green};${blue}`
22
+ : `${prefix};5;${rgbToAnsi256(red, green, blue)}`;
23
+ }
24
+
25
+ function rgbToAnsi256(red: number, green: number, blue: number): number {
26
+ const channels = [red, green, blue].map((value) => Math.round((value / 255) * 5));
27
+ return 16 + 36 * (channels[0] ?? 0) + 6 * (channels[1] ?? 0) + (channels[2] ?? 0);
17
28
  }
18
29
 
19
30
  function hexToRgb(hex: string): { red: number; green: number; blue: number } {
@@ -20,8 +20,12 @@ const COMPATIBLE_STATUS_ICON_KEYS: Readonly<Record<string, string>> = {
20
20
  pisync: "sync",
21
21
  };
22
22
  const EMPTY_EXTENSION_STATUS_ICON_ALIASES: ExtensionStatusIconAliasMap = new Map();
23
- function extensionStatusSeparator(config: StatuslineConfig, theme: Theme): string {
24
- return powerlineExtensionSeparator(theme, config.palettePreset);
23
+ function extensionStatusSeparator(
24
+ config: StatuslineConfig,
25
+ theme: Theme,
26
+ trueColor: boolean,
27
+ ): string {
28
+ return powerlineExtensionSeparator(theme, config.palettePreset, trueColor);
25
29
  }
26
30
 
27
31
  export function formatExtensionStatuses(
@@ -30,8 +34,9 @@ export function formatExtensionStatuses(
30
34
  config: StatuslineConfig,
31
35
  runtime: ExtensionStatusRuntime,
32
36
  hiddenKeys: ReadonlySet<string> = new Set(),
37
+ trueColor = true,
33
38
  ): string {
34
- const separator = extensionStatusSeparator(config, theme);
39
+ const separator = extensionStatusSeparator(config, theme, trueColor);
35
40
  const visibleStatuses = [
36
41
  ...formatDuplicateExtensionStatus(runtime, theme),
37
42
  ...[...statuses.entries()]
package/src/powerline.ts CHANGED
@@ -24,10 +24,11 @@ export function renderPowerlineStatusline(
24
24
  width: number,
25
25
  items: RenderItem[],
26
26
  config: Pick<StatuslineConfig, "palettePreset" | "palette" | "density" | "separator">,
27
+ trueColor = true,
27
28
  ): string {
28
29
  if (items.length === 0 || width <= 0) return "";
29
30
  return splitLines(items)
30
- .map((segments) => fitPowerlineSegments(segments, width, config))
31
+ .map((segments) => fitPowerlineSegments(segments, width, config, trueColor))
31
32
  .join("\n");
32
33
  }
33
34
 
@@ -60,11 +61,12 @@ function fitPowerlineSegments(
60
61
  segments: readonly RenderSegment[],
61
62
  width: number,
62
63
  config: Pick<StatuslineConfig, "palettePreset" | "palette" | "density" | "separator">,
64
+ trueColor: boolean,
63
65
  ): string {
64
66
  if (segments.length === 0) return "";
65
67
  const fitted = [...segments];
66
68
  while (fitted.length > 1) {
67
- const rendered = joinPowerlineSegments(fitted, config);
69
+ const rendered = joinPowerlineSegments(fitted, config, trueColor);
68
70
  if (visibleWidth(rendered) <= width) return rendered;
69
71
  let removalIndex = 0;
70
72
  for (let index = 1; index < fitted.length; index += 1) {
@@ -80,33 +82,37 @@ function fitPowerlineSegments(
80
82
  }
81
83
  fitted.splice(removalIndex, 1);
82
84
  }
83
- const rendered = joinPowerlineSegments(fitted, config);
85
+ const rendered = joinPowerlineSegments(fitted, config, trueColor);
84
86
  return visibleWidth(rendered) <= width ? rendered : "";
85
87
  }
86
88
 
87
89
  export function powerlineExtensionSeparator(
88
90
  _theme: Theme,
89
91
  palettePreset: PalettePreset = "tokyo-night",
92
+ trueColor = true,
90
93
  ): string {
91
- return ansiStyle(" โ€ข ", { fg: resolvePreset(palettePreset).extensionSeparator });
94
+ return ansiStyle(" โ€ข ", { fg: resolvePreset(palettePreset).extensionSeparator }, trueColor);
92
95
  }
93
96
 
94
97
  function joinPowerlineSegments(
95
98
  segments: RenderSegment[],
96
99
  config: Pick<StatuslineConfig, "palettePreset" | "palette" | "density" | "separator">,
100
+ trueColor: boolean,
97
101
  ): string {
98
102
  const preset = resolvePreset(config.palettePreset);
99
103
  const blocks = contiguousBlocks(segments, preset, config.palettePreset, config.palette);
100
- let line = ansiStyle("โ–‘โ–’โ–“", { fg: preset.lead });
104
+ let line = ansiStyle("โ–‘โ–’โ–“", { fg: preset.lead }, trueColor);
101
105
 
102
106
  for (const [index, block] of blocks.entries()) {
103
107
  const previous = index === 0 ? undefined : blocks[index - 1]?.colors;
104
- if (previous) line += ansiStyle("๎‚ด", { fg: previous.bg, bg: block.colors.bg });
105
- line += ansiStyle(formatBlockText(block, config), block.colors);
108
+ if (previous) {
109
+ line += ansiStyle("๎‚ด", { fg: previous.bg, bg: block.colors.bg }, trueColor);
110
+ }
111
+ line += ansiStyle(formatBlockText(block, config), block.colors, trueColor);
106
112
  }
107
113
 
108
114
  const lastBlock = blocks.at(-1);
109
- if (lastBlock) line += ansiStyle("๎‚ด", { fg: lastBlock.colors.bg });
115
+ if (lastBlock) line += ansiStyle("๎‚ด", { fg: lastBlock.colors.bg }, trueColor);
110
116
  return line;
111
117
  }
112
118
 
package/src/render.ts CHANGED
@@ -4,7 +4,9 @@ import type {
4
4
  ReadonlyFooterDataProvider,
5
5
  Theme,
6
6
  ThemeColor,
7
+ UIPromptKind,
7
8
  } from "@earendil-works/pi-coding-agent";
9
+ import { sliceByColumn, visibleWidth } from "@earendil-works/pi-tui";
8
10
  import { sanitizeTerminalText } from "@narumitw/pi-tui-kit/terminal-text";
9
11
  import { formatDirectoryPath } from "./directory.js";
10
12
  import {
@@ -31,6 +33,7 @@ export interface RuntimeState extends ExtensionStatusRuntime {
31
33
  turnCount: number;
32
34
  activeTools: Map<string, number>;
33
35
  isStreaming: boolean;
36
+ uiPrompt?: { kind: UIPromptKind; title?: string };
34
37
  thinkingLevel: ThinkingLevel;
35
38
  gitStatus?: GitStatusSummary;
36
39
  requestRender?: () => void;
@@ -44,6 +47,7 @@ export function renderStatusline(
44
47
  _theme: Theme,
45
48
  config: StatuslineConfig,
46
49
  runtime: RuntimeState,
50
+ trueColor = true,
47
51
  ): string {
48
52
  if (width <= 0) return "";
49
53
 
@@ -73,7 +77,7 @@ export function renderStatusline(
73
77
  segments.push(...row.segments);
74
78
  }
75
79
 
76
- return renderPowerlineStatusline(width, segments, config);
80
+ return renderPowerlineStatusline(width, segments, config, trueColor);
77
81
  }
78
82
 
79
83
  export function renderExtensionStatusline(
@@ -83,6 +87,7 @@ export function renderExtensionStatusline(
83
87
  config: StatuslineConfig,
84
88
  runtime: RuntimeState,
85
89
  mainLine: string,
90
+ trueColor = true,
86
91
  ): string[] {
87
92
  const statuses = footerData.getExtensionStatuses();
88
93
  const prContext = prContextFromStatuses(statuses);
@@ -93,6 +98,7 @@ export function renderExtensionStatusline(
93
98
  config,
94
99
  runtime,
95
100
  rendersPrInline ? GITHUB_PR_STATUS_KEYS : undefined,
101
+ trueColor,
96
102
  );
97
103
  return wrapExtensionStatusline(status, width);
98
104
  }
@@ -248,12 +254,40 @@ export function contextColor(percent: number | null | undefined): ThemeColor {
248
254
  return "success";
249
255
  }
250
256
 
257
+ const MAX_UI_PROMPT_TITLE_CODE_POINTS = 256;
258
+ const MAX_UI_PROMPT_TITLE_WIDTH = 40;
259
+
260
+ function boundUIPromptTitleLength(title: string): string {
261
+ let end = 0;
262
+ let ellipsisEnd = 0;
263
+ let codePoints = 0;
264
+ while (end < title.length && codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) {
265
+ const codePoint = title.codePointAt(end) ?? 0;
266
+ end += codePoint > 0xffff ? 2 : 1;
267
+ codePoints += 1;
268
+ if (codePoints < MAX_UI_PROMPT_TITLE_CODE_POINTS) ellipsisEnd = end;
269
+ }
270
+ return end < title.length ? `${title.slice(0, ellipsisEnd)}โ€ฆ` : title;
271
+ }
272
+
273
+ function formatUIPromptTitle(title: string | undefined): string {
274
+ const safeTitle = title ? sanitizeTerminalText(title).trim() : "";
275
+ const boundedTitle = boundUIPromptTitleLength(safeTitle);
276
+ if (visibleWidth(boundedTitle) <= MAX_UI_PROMPT_TITLE_WIDTH) return boundedTitle;
277
+ return `${sliceByColumn(boundedTitle, 0, MAX_UI_PROMPT_TITLE_WIDTH - 1, true)}โ€ฆ`;
278
+ }
279
+
251
280
  export function formatToolActivity(runtime: RuntimeState): string | undefined {
281
+ if (runtime.uiPrompt) {
282
+ const title = formatUIPromptTitle(runtime.uiPrompt.title);
283
+ return `โŒจ waiting for ${runtime.uiPrompt.kind}${title ? ` ยท ${title}` : ""}`;
284
+ }
285
+
252
286
  const active = [...runtime.activeTools.entries()];
253
287
  if (active.length > 0) {
254
288
  const [name, count] = active[0] ?? ["tool", 1];
255
289
  const suffix = count > 1 ? `ร—${count}` : active.length > 1 ? `+${active.length - 1}` : "";
256
- return `โš™ ${name}${suffix}`;
290
+ return `โš™๏ธ ${name}${suffix}`;
257
291
  }
258
292
 
259
293
  return runtime.isStreaming ? "๐Ÿ’ญ thinking" : undefined;
@@ -274,11 +308,17 @@ export function prLinkFromStatuses(statuses: ReadonlyMap<string, string>): strin
274
308
 
275
309
  export function prContextFromStatuses(statuses: ReadonlyMap<string, string>): string | undefined {
276
310
  const value = statuses.get(GITHUB_PR_KEY);
311
+ if (!value) return undefined;
277
312
  const link = prLinkFromStatuses(statuses);
278
- if (!value || !link) return undefined;
313
+ const reference = link ?? plainPrReference(value);
314
+ if (!reference) return undefined;
315
+
316
+ const state = compactPrState(link ? value.replace(link, "") : value);
317
+ return state ? `${reference} ยท ${state}` : undefined;
318
+ }
279
319
 
280
- const state = compactPrState(value.replace(link, ""));
281
- return state ? `${link} ยท ${state}` : undefined;
320
+ function plainPrReference(value: string): string | undefined {
321
+ return /^PR\s+(#\d+):/u.exec(value)?.[1];
282
322
  }
283
323
 
284
324
  function compactPrState(value: string): string | undefined {
package/src/statusline.ts CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  type ExtensionContext,
5
5
  getAgentDir,
6
6
  } from "@earendil-works/pi-coding-agent";
7
+ import { getCapabilities } from "@earendil-works/pi-tui";
7
8
  import { completeStatuslineArguments } from "./command-contract.js";
8
9
  import type { StatuslineCommandOptions } from "./commands.js";
9
10
  import {
@@ -193,10 +194,27 @@ export default function statusline(pi: ExtensionAPI) {
193
194
  const config = previewPalettePreset
194
195
  ? { ...loaded.config, palettePreset: previewPalettePreset }
195
196
  : loaded.config;
196
- const mainLine = renderStatusline(width, ctx, footerData, theme, config, runtime);
197
+ const trueColor = getCapabilities().trueColor;
198
+ const mainLine = renderStatusline(
199
+ width,
200
+ ctx,
201
+ footerData,
202
+ theme,
203
+ config,
204
+ runtime,
205
+ trueColor,
206
+ );
197
207
  const lines = mainLine ? mainLine.split("\n") : [];
198
208
  lines.push(
199
- ...renderExtensionStatusline(width, footerData, theme, config, runtime, mainLine),
209
+ ...renderExtensionStatusline(
210
+ width,
211
+ footerData,
212
+ theme,
213
+ config,
214
+ runtime,
215
+ mainLine,
216
+ trueColor,
217
+ ),
200
218
  );
201
219
  return lines;
202
220
  },
@@ -243,6 +261,7 @@ export default function statusline(pi: ExtensionAPI) {
243
261
  runtime.turnCount = 0;
244
262
  runtime.activeTools.clear();
245
263
  runtime.isStreaming = false;
264
+ runtime.uiPrompt = undefined;
246
265
  loaded = loadStatuslineSettingsForAgent(agentDir);
247
266
  const settingsNotice = consumeStatuslineSettingsNotice();
248
267
  if (settingsNotice) ctx.ui.notify(settingsNotice, "warning");
@@ -271,6 +290,7 @@ export default function statusline(pi: ExtensionAPI) {
271
290
  runtime.gitStatus = undefined;
272
291
  runtime.activeTools.clear();
273
292
  runtime.isStreaming = false;
293
+ runtime.uiPrompt = undefined;
274
294
  runtime.duplicateExtensions = [];
275
295
  runtime.extensionStatusIconAliases = EMPTY_EXTENSION_STATUS_ICON_ALIASES;
276
296
  ctx.ui.setFooter(undefined);
@@ -305,6 +325,18 @@ export default function statusline(pi: ExtensionAPI) {
305
325
  refresh();
306
326
  });
307
327
 
328
+ pi.on("ui_prompt_start", (event, ctx) => {
329
+ if (!ownsRuntime(ctx)) return;
330
+ runtime.uiPrompt = { kind: event.kind, title: event.title };
331
+ refresh();
332
+ });
333
+
334
+ pi.on("ui_prompt_end", (_event, ctx) => {
335
+ if (!ownsRuntime(ctx)) return;
336
+ runtime.uiPrompt = undefined;
337
+ refresh();
338
+ });
339
+
308
340
  pi.on("turn_start", (_event, ctx) => {
309
341
  if (!ownsRuntime(ctx)) return;
310
342
  runtime.turnCount += 1;