pi-minimalist 0.1.0 → 0.1.2

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
@@ -1,24 +1,60 @@
1
1
  # pi-minimalist
2
2
 
3
- Make Pi's tool calls and optional thinking previews quieter: compact, one-line rows without losing access to the original tool output.
3
+ **Less scrolling. More room for the answer.**
4
4
 
5
- ## What does minimalist mode look like
5
+ A quieter transcript for [Pi](https://pi.dev): turn bulky tool calls into one-line summaries, and open the full output whenever you need it.
6
6
 
7
- Before pi-minimalist:
7
+ ## See the difference
8
8
 
9
- <img width="656" height="550" alt="before" src="https://github.com/user-attachments/assets/aa1602f7-5db1-49b8-a4d3-cbd1aef69ea0" />
9
+ **Before:** one tool call takes up most of the screen.
10
10
 
11
+ <img width="656" height="550" alt="before" src="https://github.com/user-attachments/assets/aa1602f7-5db1-49b8-a4d3-cbd1aef69ea0" />
11
12
 
12
- After pi-minimalist:
13
+ **After:** the same call, one line.
13
14
 
14
15
  <img width="699" height="50" alt="after" src="https://github.com/user-attachments/assets/c0e8bca4-afa7-42c1-9bf0-69f267d18d9f" />
15
16
 
16
- ## Installation
17
- Install with npm:
17
+ Press **Ctrl+O** to expand tool output—including diffs and syntax highlighting. Nothing is removed from the session or hidden from the model; only the display changes.
18
+
19
+ ## Install
20
+
18
21
  ```bash
19
- pi install npm:pi-minimalist
22
+ pi install npm:pi-minimalist
20
23
  ```
21
24
 
22
- ## Configuration
25
+ Restart Pi, and tool calls appear as compact rows. No configuration needed.
26
+
27
+ ## Choose how quiet you want it
28
+
29
+ Run **`/minimalist`** to change settings live. Start with compact tool rows, or go further:
30
+
31
+ - **Combine consecutive tool calls** into a single summary, such as `read ×2, edit ×1`.
32
+ - **Collapse earlier activity** so the latest reply stays in focus. Replace the preceding activity with elapsed work time or tool counts.
33
+ - **Compact thinking rows**, or keep thinking visible as it arrives.
34
+ - **Keep running tools visible** while grouping other calls, with an elapsed timer to show how long they take.
35
+
36
+ Compact tool rows and consecutive-call grouping are **on by default**. Activity folding and compact thinking are opt-in. Disable grouping if you prefer to see each call separately.
37
+
38
+ ### Everyday controls
39
+
40
+ | Control | Action |
41
+ | --- | --- |
42
+ | `/minimalist` | Open settings (`/minimalist config` also works) |
43
+ | `/minimalist status` | Show current settings |
44
+ | Ctrl+O | Expand or collapse tool output |
45
+ | Ctrl+T | Expand or collapse thinking |
46
+ | Restore defaults | Reset display settings in the editor |
47
+
48
+ Settings apply to existing conversation history and are saved globally. If a symbol looks wrong in your terminal, choose **Symbols → ASCII**. No Nerd Font required.
49
+
50
+ ## Go back to Pi's usual view
51
+
52
+ Turn off **Compact tool rows** to restore native tool cards. Other folding options are independent; **Restore defaults** returns to the extension's initial settings, not native Pi.
53
+
54
+ To disable the extension completely, run `pi config`, disable pi-minimalist, and restart Pi. To uninstall:
55
+
56
+ ## Compatibility
57
+
58
+ Tested with Pi **1.0.0**. Pi updates can affect rendering compatibility; [report a problem](https://github.com/EviHex/pi-minimalist/issues) with your Pi version, terminal, and a screenshot.
23
59
 
24
- You may configure different collapse options / verbosity levels with the slash command `/minimalist config`.
60
+ [MIT licensed](LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-minimalist",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Compact one-line tool and thinking rows for Pi's interactive transcript",
5
5
  "keywords": ["pi-package"],
6
6
  "license": "MIT",
package/src/components.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { truncateToWidth } from "@earendil-works/pi-tui";
10
- import type { Component } from "@earendil-works/pi-tui";
10
+ import type { Component, TuiMouseEvent, TuiMouseEventResult } from "@earendil-works/pi-tui";
11
11
  import { gutterWidth, type Row } from "./row.ts";
12
12
 
13
13
  /**
@@ -50,6 +50,7 @@ export type ResolveRow = (width: number) => Row | null;
50
50
  */
51
51
  export class CompactLine implements Component {
52
52
  private resolve: ResolveRow = () => null;
53
+ private click?: () => boolean;
53
54
  private ticker: unknown;
54
55
  private timers: Timers;
55
56
 
@@ -57,9 +58,20 @@ export class CompactLine implements Component {
57
58
  this.timers = timers;
58
59
  }
59
60
 
60
- /** Install the row resolver. Called on every updateDisplay with fresh state. */
61
- setRow(resolve: ResolveRow): void {
61
+ /**
62
+ * Install the row resolver. Called on every updateDisplay with fresh state.
63
+ * `click` returning true stops Pi's own left-click (expand) handler.
64
+ */
65
+ setRow(resolve: ResolveRow, click?: () => boolean): void {
62
66
  this.resolve = resolve;
67
+ this.click = click;
68
+ }
69
+
70
+ // Pi's MouseRegion asks its child first, so a handled click never reaches
71
+ // the region's own expand/collapse toggle.
72
+ handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined {
73
+ if (event.type !== "click" || event.button !== "left") return undefined;
74
+ return this.click?.() ? { handled: true } : undefined;
63
75
  }
64
76
 
65
77
  /**
package/src/config.ts CHANGED
@@ -128,7 +128,7 @@ export type Settings = BasicSettings & AdvancedSettings;
128
128
 
129
129
  export const DEFAULT_BASIC: BasicSettings = {
130
130
  compactToolRows: true,
131
- groupToolRuns: false,
131
+ groupToolRuns: true,
132
132
  foldIntermediateActivity: false,
133
133
  foldActivityOnFinalAnswer: false,
134
134
  activitySummary: "elapsed",
@@ -55,6 +55,8 @@ export class RunGrouping {
55
55
  private cycle = 0;
56
56
  private cycles = new Map<number, Cycle>();
57
57
  private agentActive = false;
58
+ /** Rows the user opened out of a summary by clicking it. Never fold again. */
59
+ private opened = new Set<string>();
58
60
  private version = 0;
59
61
  private cache?: ViewCache;
60
62
 
@@ -226,6 +228,33 @@ export class RunGrouping {
226
228
  return painter.summary(view);
227
229
  }
228
230
 
231
+ /**
232
+ * Open the summary this row draws back into separate rows, after a click.
233
+ *
234
+ * Needed because the summary is drawn by ONE member (the tail) and the others
235
+ * draw zero lines: Pi's own click handler would expand only the tail.
236
+ * Returns false when the row draws no summary, so Pi's click still applies.
237
+ */
238
+ open(id: string): boolean {
239
+ const entry = this.byId.get(id);
240
+ if (!entry) return false;
241
+ const { activity, grouped } = this.views();
242
+ const members = [entry];
243
+ if (activity.get(id) === "summary") {
244
+ members.push(...this.entries.filter((e) => e.cycle === entry.cycle && activity.get(e.id) === "hide"));
245
+ } else if (typeof grouped.get(id) === "object") {
246
+ // A run's hidden members are the contiguous "hide" rows before its tail.
247
+ for (let i = this.entries.indexOf(entry) - 1; i >= 0 && grouped.get(this.entries[i].id) === "hide"; i--) {
248
+ members.push(this.entries[i]);
249
+ }
250
+ } else {
251
+ return false;
252
+ }
253
+ for (const member of members) this.opened.add(member.id);
254
+ this.invalidateViews();
255
+ return true;
256
+ }
257
+
229
258
  view(id: string): RowView {
230
259
  return this.views().grouped.get(id) ?? "show";
231
260
  }
@@ -320,7 +349,7 @@ export class RunGrouping {
320
349
  }
321
350
 
322
351
  private activityFoldable(entry: Entry): boolean {
323
- if (entry.expanded) return false;
352
+ if (entry.expanded || this.opened.has(entry.id)) return false;
324
353
  if (entry.outcome === "pending" && entry.kind !== "prose" && this.config.get("keepActiveToolsExpanded")) {
325
354
  return false;
326
355
  }
@@ -328,7 +357,7 @@ export class RunGrouping {
328
357
  }
329
358
 
330
359
  private foldable(entry: Entry | undefined): boolean {
331
- if (!entry?.foldable || entry.expanded) return false;
360
+ if (!entry?.foldable || entry.expanded || this.opened.has(entry.id)) return false;
332
361
  if (entry.kind === "thinking" && !this.config.get("thinkingAsToolCall")) return false;
333
362
  if (entry.outcome === "pending" && this.config.get("keepActiveToolsExpanded")) return false;
334
363
  return true;
package/src/thinking.ts CHANGED
@@ -59,7 +59,7 @@ export function createThinkingPreview(deps: ThinkingDeps): ThinkingPreview {
59
59
 
60
60
  if (owner && runIndex !== undefined) {
61
61
  const id = grouping.thinkingId(owner, runIndex);
62
- line.setRow(() => grouping.rowFor(id, new Painter(theme, config), paint));
62
+ line.setRow(() => grouping.rowFor(id, new Painter(theme, config), paint), () => grouping.open(id));
63
63
  } else {
64
64
  line.setRow(paint);
65
65
  }
@@ -194,7 +194,10 @@ export function createToolRenderer(deps: RendererDeps): ToolRenderer {
194
194
  return component;
195
195
  }
196
196
  grouping.observe(id, summaryName(name, args), status.outcome, context.expanded === true);
197
- component.setRow((width) => grouping.rowFor(id, new Painter(theme, config), () => paint(width)));
197
+ component.setRow(
198
+ (width) => grouping.rowFor(id, new Painter(theme, config), () => paint(width)),
199
+ () => grouping.open(id),
200
+ );
198
201
  return component;
199
202
  },
200
203