pi-compact-tools 0.16.0 → 0.16.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,8 +1,10 @@
|
|
|
1
1
|
# pi-compact-tools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Three tool-row styles for Pi: **Claude**, **Codex**, and **Compact**. Switch styles live, hide tool noise with silent mode, and see what codemode scripts actually called.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**UI only:** no changes to tool execution, model input, or session records. Includes custom-tool rendering and a GitHub Dark theme.
|
|
6
|
+
|
|
7
|
+

|
|
6
8
|
|
|
7
9
|
## Install
|
|
8
10
|
|
|
@@ -10,131 +12,92 @@ Tool rows for Pi in three styles: **Claude**, **Codex**, and **Compact**. Pick t
|
|
|
10
12
|
pi install npm:pi-compact-tools
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
Run `/reload` or restart Pi, then `/compact-tools` to choose a style. Try without installing: `pi -e npm:pi-compact-tools`.
|
|
14
16
|
|
|
15
|
-
Requires Node.js 22.19+ and Pi 0.85.1+. **Pi 1.2
|
|
17
|
+
Requires Node.js 22.19+ and Pi 0.85.1+. **Pi 1.0.2+ recommended** for native renderer integration and styled HTML exports.
|
|
16
18
|
|
|
17
19
|
## Styles
|
|
18
20
|
|
|
19
|
-
| Style |
|
|
21
|
+
| Style | What you see | Command |
|
|
20
22
|
|---|---|---|
|
|
21
|
-
| **Claude** |
|
|
22
|
-
| **Codex** |
|
|
23
|
-
| **Compact** |
|
|
23
|
+
| **Claude** | Grouped reads/searches, `⎿` results, edit previews | `/compact-tools claude` |
|
|
24
|
+
| **Codex** | `• Explored` groups, `• Ran` output, highlighted diffs | `/compact-tools codex` |
|
|
25
|
+
| **Compact** (default) | One row per call: status, duration, line count, and diff | `/compact-tools compact` |
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
Switching redraws existing rows, even while tools run. Only read-only exploration is grouped; commands that write or execute work keep separate rows.
|
|
26
28
|
|
|
27
29
|
### Claude
|
|
28
30
|
|
|
29
|
-

|
|
34
32
|
|
|
35
33
|
### Codex
|
|
36
34
|
|
|
37
|
-

|
|
43
36
|
|
|
44
37
|
### Compact
|
|
45
38
|
|
|
46
|
-

|
|
40
|
+
|
|
41
|
+
## Silent mode
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
- Edits show a highlighted diff with `(+3 -1)`; reads and writes show numbered code.
|
|
43
|
+
Toggle with **`Ctrl+'`** or `/silent`; use `/silent on` and `/silent off` explicitly. Works with any style. It also hides thinking, intermediate assistant turns, and error/status notices; turn it off to inspect them.
|
|
50
44
|
|
|
51
|
-
|
|
45
|
+
**During work:** hide tool rows while the activity light keeps moving and the answer still arrives. Turn it off to restore every row.
|
|
52
46
|
|
|
53
|
-
|
|
47
|
+

|
|
54
48
|
|
|
55
|
-
|
|
49
|
+
**In a resumed session:** hide pages of completed tool calls to see the conversation at a glance.
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
This changes the display only—not the saved history or the model's context. Set `"mode": "silent"` to start sessions with it on.
|
|
54
|
+
|
|
55
|
+
## Codemode summaries
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
Codemode is Pi's tool for scripts that call other tools. Enable it for a session with `pi --tools +codemode`; use Pi 1.2+ for the native summaries shown here. This extension only renders it.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Completed scripts show outcomes in all three styles: `read 3 · bash 1 · edit 3 2`. Counts use your theme's success, error, and warning colors—green, red, and yellow in the included theme. Each tool appears once; edits come last.
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
The two failed edits are intentional. Reload/resume preserves summaries from nested-call records; older hosts without those records keep normal previews. See [compatibility details](https://github.com/nedleeds/pi-compact-tools/blob/main/docs/development.md#ui-only-integration-and-compatibility).
|
|
64
|
+
|
|
65
|
+
## Commands and controls
|
|
60
66
|
|
|
61
67
|
```text
|
|
62
|
-
/compact-tools # choose
|
|
63
|
-
/compact-tools codex # switch style, at once, even while tools run
|
|
68
|
+
/compact-tools # choose style and save scope
|
|
64
69
|
/compact-tools claude project # save for this trusted project
|
|
65
|
-
/compact-tools
|
|
66
|
-
/compact-tools status # effective
|
|
70
|
+
/compact-tools codex global # save globally
|
|
71
|
+
/compact-tools status # effective settings and paths
|
|
72
|
+
/compact-tools off # restore Pi's native rows (reloads Pi)
|
|
67
73
|
```
|
|
68
74
|
|
|
69
|
-
Without a scope,
|
|
75
|
+
Without a scope, changes are saved where the style is configured: project or global. A trusted project's own style overrides a global save. Turning rows off or back on waits for the current response to finish and reloads Pi.
|
|
76
|
+
|
|
77
|
+
- Click a row/group or press `Ctrl+O` to expand/collapse.
|
|
78
|
+
- `Ctrl+T` changes the thinking display, not the model's reasoning effort.
|
|
79
|
+
- Choose `github-dark-pro` in Pi's `/settings` for the included theme.
|
|
70
80
|
|
|
71
81
|
## Configuration
|
|
72
82
|
|
|
73
|
-
Optional
|
|
83
|
+
Optional: `~/.pi/agent/compact-tools.json` or `<project>/.pi/compact-tools.json`. Trusted project settings override global settings field by field.
|
|
74
84
|
|
|
75
85
|
```json
|
|
76
86
|
{
|
|
87
|
+
"$schema": "https://raw.githubusercontent.com/nedleeds/pi-compact-tools/main/schemas/compact-tools.schema.json",
|
|
77
88
|
"style": "compact",
|
|
78
89
|
"mode": "normal",
|
|
79
|
-
"tools": ["read", "write", "edit", "bash"],
|
|
80
90
|
"previewLines": 10,
|
|
81
91
|
"auto_compact": { "read": true, "write": true, "edit": false, "bash": true },
|
|
82
92
|
"custom_tools": { "enabled": true, "auto_compact": true, "exclude": [] }
|
|
83
93
|
}
|
|
84
94
|
```
|
|
85
95
|
|
|
86
|
-
|
|
87
|
-
- `tools`: built-ins drawn in the style. Also `grep`, `find`, `ls`, `powershell`.
|
|
88
|
-
- `auto_compact`: `true` starts a Compact row collapsed; `false` shows up to `previewLines` rows. Custom tool names work too.
|
|
89
|
-
- `custom_tools`: rows for tools from other packages. `exclude` keeps a tool's own look.
|
|
90
|
-
|
|
91
|
-
## Codemode summaries
|
|
92
|
-
|
|
93
|
-
Completed `codemode` rows in **Compact, Claude, and Codex** list the outcomes of the tools the script actually called, beside the duration and output-line count:
|
|
94
|
-
|
|
95
|
-
```text
|
|
96
|
-
Done in 1.234s (42 lines) · ✓ read(3) ✗ bash(1) edit(3) [+10 -3|✗|+5 -7]
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Most calls are grouped by tool and outcome, in first-call order. A script that catches a failed call can finish successfully while still showing `✗ bash(1)`. Edits instead use one ordered list with the total attempt count: each successful call shows its actual diff without a checkmark, each failed call shows `✗`, and an unfinished call shows `?`. A successful edit without a saved diff shows `ok`; it does not hide other calls’ known changes. Diff entries use a dim `|` separator with no surrounding whitespace; added and removed counts keep their diff colors. Collapsed rows show the first three edit attempts and `… +N more`; omitted failures or unfinished calls are counted beside that marker so the preview cannot hide them. Expanded rows show every recorded edit attempt. Incomplete records show `(partial)`. Long summaries wrap to the pane width. Previews and author-provided expanded views remain available. Claude and Codex place the `Done` / `Failed` summary after the output, without another branch marker and aligned with the output continuation rows. The disclosure stays last: Claude’s `… +N lines (ctrl+o to expand)` or Codex’s `+ Show details` / `− Show less`. Completion rows do not consume Claude’s output-preview limit.
|
|
100
|
-
|
|
101
|
-
The summary uses the host’s nested-call events and saved records when available, without changing what the model sees. Exact per-call edit diffs survive an in-process `/reload`. After restarting or resuming, Pi’s saved nested records restore call counts, but do not contain edit result diffs, so edits show per-call statuses such as `edit(3) [ok|✗|ok]` rather than invented changes. `/tree` navigation restores the selected branch’s records. Hosts without nested-call data keep the previous row rendering.
|
|
102
|
-
|
|
103
|
-
## UI-only behavior
|
|
104
|
-
|
|
105
|
-
This package never registers or activates agent tools and does not add model-facing
|
|
106
|
-
messages, tool schemas, or prompt text. Host execution settings (including shell
|
|
107
|
-
prefixes and image resizing) remain untouched. Renderer-bearing overrides of names
|
|
108
|
-
such as `read` or `bash` follow `custom_tools`, including its exclusions.
|
|
109
|
-
|
|
110
|
-
On Pi 1.0.2 and newer, the public renderer API also applies compact rendering to HTML
|
|
111
|
-
exports. Older hosts use a terminal-only compatibility patch; HTML exports keep
|
|
112
|
-
Pi's native renderers. On Pi 1.1 and newer, final durations use the host's recorded
|
|
113
|
-
`durationMs`, including restored sessions, and tool rows follow `outputPad` (0 or 1)
|
|
114
|
-
without changing their internal style indentation. Older hosts keep event-based
|
|
115
|
-
timing and the original margins; the minimum supported Pi version is unchanged.
|
|
116
|
-
When custom compact rendering is enabled, it intentionally takes precedence over
|
|
117
|
-
fallback renderers supplied by earlier `next() ?? mine` resolvers for unknown tools.
|
|
118
|
-
Disable `custom_tools` or exclude the tool to preserve those fallback renderers.
|
|
119
|
-
|
|
120
|
-
## Controls
|
|
121
|
-
|
|
122
|
-
- Click a row or group, or press `Ctrl+O`, to expand and collapse.
|
|
123
|
-
- `Ctrl+T` cycles thinking: summary → detail → summary → hidden.
|
|
96
|
+
`auto_compact` entries set to `true` start Compact rows collapsed. Add tool names to `custom_tools.exclude` to keep their own rendering. All options are described in the linked schema.
|
|
124
97
|
|
|
125
98
|
## Development
|
|
126
99
|
|
|
127
|
-
|
|
128
|
-
npm install
|
|
129
|
-
npm run check
|
|
130
|
-
pi -e .
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Development dependencies are pinned to Pi 1.2.0; the peer minimum remains Pi 0.85.1. CI checks Pi 0.85.1, 0.99.1, 1.0.0, 1.0.2, 1.1.0, and 1.2.0 on Node 22.19.0 and 24. Schema validation and deterministic test clocks are development-only dependencies, not runtime dependencies. Development scripts and tests are not included in the published package. `npm test` runs the rendering tests first and the resource/packaging checks separately so their subprocesses do not disturb animation tests.
|
|
134
|
-
|
|
135
|
-
For a local before/after performance comparison, run `npx tsx tests/benchmark.ts <clean-baseline-directory>` with the same host dependencies in both directories. Measurements are informational, not timing-sensitive test assertions.
|
|
136
|
-
|
|
137
|
-
Renders are pinned in `tests/golden/`. After an intended change to the output, record it with `UPDATE_GOLDEN=1 npm test` and review the diff. The Claude and Codex styles are checked against references captured from the real tools in `tests/fixtures/`. The README's GIFs are recorded with `scripts/record-demos.sh` (needs `vhs` and `ffmpeg`). Before publishing, add the version's notes to `release-notes.json` (`[]` for none).
|
|
100
|
+
See [development, compatibility, and demo recording](https://github.com/nedleeds/pi-compact-tools/blob/main/docs/development.md). Run `npm ci` and `npm run check` before contributing.
|
|
138
101
|
|
|
139
102
|
## License
|
|
140
103
|
|
|
@@ -141,7 +141,7 @@ export function paletteOf(theme: Theme): object {
|
|
|
141
141
|
|
|
142
142
|
/** Every token the derived colors are made from. */
|
|
143
143
|
const PALETTE_TOKENS: readonly ThemeColor[] = [
|
|
144
|
-
"text", "dim", "muted", "toolDiffAdded", "toolDiffRemoved",
|
|
144
|
+
"text", "dim", "muted", "toolTitle", "success", "error", "warning", "toolDiffAdded", "toolDiffRemoved",
|
|
145
145
|
"thinkingOff", "thinkingMinimal", "thinkingLow", "thinkingMedium", "thinkingHigh", "thinkingXhigh",
|
|
146
146
|
];
|
|
147
147
|
/** One object per palette seen; a session switches among a handful of themes at most. */
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { stripTerminalSequences } from "@earendil-works/pi-tui";
|
|
3
|
-
import {
|
|
3
|
+
import { chromePainter, nestedCountPainter, nestedTitlePainter } from "./compact-tools-palette.ts";
|
|
4
4
|
|
|
5
5
|
const SUMMARY_KEY = Symbol.for("pi-compact-tools.nested-summaries.v1");
|
|
6
6
|
const MAX_PARENTS = 2_000;
|
|
7
7
|
const MAX_CALLS = 256;
|
|
8
|
-
const EDIT_PREVIEW_CALLS = 3;
|
|
9
8
|
const MAX_NAME_LENGTH = 256;
|
|
10
9
|
const MAX_ID_LENGTH = 1_024;
|
|
11
10
|
type Status = "ok" | "error" | "unfinished";
|
|
12
|
-
type Call = { name: string; status: Status
|
|
11
|
+
type Call = { name: string; status: Status };
|
|
13
12
|
type Summary = { calls: Map<string, Call>; partial: boolean; finished: boolean; live: boolean; revision: object };
|
|
14
13
|
type Shared = typeof globalThis & { [SUMMARY_KEY]?: Map<string, Summary> };
|
|
15
14
|
type NestedEvent = { toolCallId: string; toolName: string; parentToolCallId?: string; isError?: boolean; result?: unknown };
|
|
@@ -78,12 +77,8 @@ export class NestedCallSummaries {
|
|
|
78
77
|
return summary.finished;
|
|
79
78
|
}
|
|
80
79
|
const status = ended ? event.isError ? "error" : "ok" : "unfinished";
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
? countEditChanges(result as AgentToolResult<unknown>) : undefined;
|
|
84
|
-
if (previous?.name === event.toolName && previous.status === status
|
|
85
|
-
&& previous.changes?.added === changes?.added && previous.changes?.removed === changes?.removed) return false;
|
|
86
|
-
summary.calls.set(event.toolCallId, { name: event.toolName, status, ...(changes ? { changes } : {}) });
|
|
80
|
+
if (previous?.name === event.toolName && previous.status === status) return false;
|
|
81
|
+
summary.calls.set(event.toolCallId, { name: event.toolName, status });
|
|
87
82
|
summary.live = true;
|
|
88
83
|
summary.revision = {};
|
|
89
84
|
return summary.finished;
|
|
@@ -95,7 +90,7 @@ export class NestedCallSummaries {
|
|
|
95
90
|
const value = message as { role?: string; toolName?: string; toolCallId?: string; nestedCalls?: { calls?: unknown; complete?: unknown } };
|
|
96
91
|
if (value.role !== "toolResult" || value.toolName !== "codemode" || typeof value.toolCallId !== "string"
|
|
97
92
|
|| value.toolCallId.length > MAX_ID_LENGTH || !Array.isArray(value.nestedCalls?.calls)) return false;
|
|
98
|
-
// A bounded persisted snapshot must not
|
|
93
|
+
// A bounded persisted snapshot must not drop observed live calls.
|
|
99
94
|
const existing = this.summaries.get(value.toolCallId);
|
|
100
95
|
if (existing?.live && existing.calls.size > 0) return false;
|
|
101
96
|
const summary: Summary = { calls: new Map(), partial: value.nestedCalls.complete !== true, finished: true, live: false, revision: {} };
|
|
@@ -122,48 +117,45 @@ export class NestedCallSummaries {
|
|
|
122
117
|
}
|
|
123
118
|
}
|
|
124
119
|
|
|
125
|
-
/**
|
|
126
|
-
format(id: string, theme: Theme,
|
|
120
|
+
/** Other tool groups keep first-occurrence order; edit counts always come last. */
|
|
121
|
+
format(id: string, theme: Theme, _expanded = false): string | undefined {
|
|
127
122
|
const summary = this.summaries.get(id);
|
|
128
123
|
if (!summary || (summary.calls.size === 0 && !summary.partial)) return undefined;
|
|
129
|
-
|
|
124
|
+
type Group = { name: string; calls: Call[] };
|
|
125
|
+
const groups: Group[] = [];
|
|
126
|
+
const byTool = new Map<string, Group>();
|
|
130
127
|
for (const call of summary.calls.values()) {
|
|
131
|
-
const key =
|
|
132
|
-
let group =
|
|
133
|
-
if (!group)
|
|
128
|
+
const key = call.name;
|
|
129
|
+
let group = byTool.get(key);
|
|
130
|
+
if (!group) {
|
|
131
|
+
group = { name: call.name, calls: [] };
|
|
132
|
+
byTool.set(key, group);
|
|
133
|
+
groups.push(group);
|
|
134
|
+
}
|
|
134
135
|
group.calls.push(call);
|
|
135
136
|
}
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
const editIndex = groups.findIndex((group) => group.name === "edit");
|
|
138
|
+
if (editIndex >= 0) groups.push(...groups.splice(editIndex, 1));
|
|
139
|
+
const title = nestedTitlePainter(theme);
|
|
140
|
+
const chrome = chromePainter(theme);
|
|
141
|
+
const success = nestedCountPainter(theme, "success");
|
|
142
|
+
const error = nestedCountPainter(theme, "error");
|
|
143
|
+
const warning = nestedCountPainter(theme, "warning");
|
|
144
|
+
const parts = groups.map((group) => {
|
|
140
145
|
const name = stripTerminalSequences(group.name).replace(/[\x00-\x20\x7f-\x9f]/gu, " ").replace(/[\u200b-\u200f\u202a-\u202e\u2060-\u206f\ufeff]/gu, "").trim() || "tool";
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// The preview must not hide that an omitted edit failed or is unfinished.
|
|
155
|
-
const failed = hidden.filter((call) => call.status === "error").length;
|
|
156
|
-
const unfinished = hidden.filter((call) => call.status === "unfinished").length;
|
|
157
|
-
let more = theme.fg("dim", `… +${hidden.length} more`);
|
|
158
|
-
const statuses = [failed ? theme.fg("error", `${failed} failed`) : "", unfinished ? theme.fg("warning", `${unfinished} unfinished`) : ""].filter(Boolean);
|
|
159
|
-
if (statuses.length > 0) more += " (" + statuses.join(", ") + ")";
|
|
160
|
-
entries.push(more);
|
|
161
|
-
}
|
|
162
|
-
parts.push(`${name}(${group.calls.length}) [` + entries.join(theme.fg("dim", "|")) + "]");
|
|
163
|
-
} else parts.push(theme.fg(color, glyph) + ` ${name}(${group.calls.length})`);
|
|
164
|
-
}
|
|
165
|
-
if (summary.partial || [...summary.calls.values()].some((call) => call.status === "unfinished")) parts.push(theme.fg("warning", "(partial)"));
|
|
166
|
-
return parts.join(" ");
|
|
146
|
+
|
|
147
|
+
const successes = group.calls.filter((call) => call.status === "ok").length;
|
|
148
|
+
const failures = group.calls.filter((call) => call.status === "error").length;
|
|
149
|
+
const unfinished = group.calls.filter((call) => call.status === "unfinished").length;
|
|
150
|
+
const counts = [successes ? success(String(successes)) : "",
|
|
151
|
+
failures ? error(String(failures)) : ""].filter(Boolean);
|
|
152
|
+
const settled = counts.length > 0;
|
|
153
|
+
if (!settled) counts.push(warning(String(unfinished)));
|
|
154
|
+
return title(name) + chrome(" ") + counts.join(chrome(" "))
|
|
155
|
+
+ (settled && unfinished ? chrome(" ") + warning(`${unfinished} unfinished`) : "");
|
|
156
|
+
});
|
|
157
|
+
const partial = summary.partial || [...summary.calls.values()].some((call) => call.status === "unfinished");
|
|
158
|
+
return parts.join(chrome(" · ")) + (partial ? (parts.length ? " " : "") + warning("(partial)") : "");
|
|
167
159
|
}
|
|
168
160
|
|
|
169
161
|
private trim(): void {
|
|
@@ -38,10 +38,11 @@ type ContrastBand = { color: ThemeColor; keepHue: number; minimum: number; maxim
|
|
|
38
38
|
type ContrastRange = { minimum: number; maximum: number };
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* A quiet frame tone for rails, connectors, and separators. Completion metadata
|
|
42
|
+
* sits one small brightness step above it so duration and line counts remain legible.
|
|
43
43
|
*/
|
|
44
44
|
const CHROME: ContrastBand = { color: "dim", keepHue: 0.35, minimum: 0.22, maximum: 0.28 };
|
|
45
|
+
const COMPLETION: ContrastBand = { ...CHROME, minimum: 0.26, maximum: 0.32 };
|
|
45
46
|
/** The indicator breathes either side of the chrome tone, dipping below it and peaking above. */
|
|
46
47
|
const PULSE_LOW: ContrastBand = { color: "dim", keepHue: 0.4, minimum: 0.18, maximum: 0.3 };
|
|
47
48
|
const PULSE_HIGH: ContrastBand = { color: "muted", keepHue: 0.4, minimum: 0.4, maximum: 0.6 };
|
|
@@ -105,7 +106,34 @@ export function chromePainter(theme: Theme): (text: string) => string {
|
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
/**
|
|
109
|
+
/** Duration and line-count metadata is slightly brighter than rails and separators. */
|
|
110
|
+
export function completionPainter(theme: Theme): (text: string) => string {
|
|
111
|
+
return perPalette(theme, "completion-metadata", () => {
|
|
112
|
+
const color = bandedRgb(theme, COMPLETION);
|
|
113
|
+
return color ? rgbPainter(theme, color) : (text: string) => theme.fg("dim", text);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Nested names keep the title hue, slightly darker than ordinary titles, without bold. */
|
|
118
|
+
export function nestedTitlePainter(theme: Theme): (text: string) => string {
|
|
119
|
+
return perPalette(theme, "nested-title", () => {
|
|
120
|
+
const title = themeColorRgb(theme, "toolTitle");
|
|
121
|
+
const paint = title ? rgbPainter(theme, interpolateRgb(title, { r: 0, g: 0, b: 0 }, 0.25))
|
|
122
|
+
: (text: string) => theme.fg("toolTitle", text);
|
|
123
|
+
return paint;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Quiet summary numbers retain outcome hues at 80% brightness. */
|
|
128
|
+
export function nestedCountPainter(theme: Theme, color: "success" | "error" | "warning"): (text: string) => string {
|
|
129
|
+
return perPalette(theme, `nested-count:${color}`, () => {
|
|
130
|
+
const rgb = themeColorRgb(theme, color);
|
|
131
|
+
return rgb ? rgbPainter(theme, interpolateRgb(rgb, { r: 0, g: 0, b: 0 }, 0.20))
|
|
132
|
+
: (text: string) => theme.fg(color, text);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Paint frame rails, connectors, separators, or running status in the quiet chrome tone. */
|
|
109
137
|
export function paintChrome(theme: Theme, text: string): string {
|
|
110
138
|
return chromePainter(theme)(text);
|
|
111
139
|
}
|
|
@@ -52,7 +52,7 @@ import { CODEX_BULLET, CODEX_INDENT } from "./compact-tools-codex.ts";
|
|
|
52
52
|
import { NestedCallSummaries } from "./compact-tools-nested.ts";
|
|
53
53
|
import { renderCodexCall, renderCodexResult } from "./compact-tools-codex-rows.ts";
|
|
54
54
|
import { ToolGroupController } from "./compact-tools-grouping.ts";
|
|
55
|
-
import { chromePainter, paintIndicator } from "./compact-tools-palette.ts";
|
|
55
|
+
import { chromePainter, completionPainter, paintIndicator } from "./compact-tools-palette.ts";
|
|
56
56
|
import { ProgressController } from "./compact-tools-progress.ts";
|
|
57
57
|
import { showReleaseNotice } from "./compact-tools-release.ts";
|
|
58
58
|
import { ToolRuntime } from "./compact-tools-runtime.ts";
|
|
@@ -190,9 +190,10 @@ function renderControls(
|
|
|
190
190
|
? (duration ?? "Running")
|
|
191
191
|
: `${isError ? "Failed" : "Done"}${duration ? ` in ${duration}` : ""}`;
|
|
192
192
|
// A failed row already reads as an error through its output color and Pi's row
|
|
193
|
-
// background, so
|
|
193
|
+
// background, so completion metadata stays neutral rather than repeating that signal.
|
|
194
194
|
const chrome = chromePainter(theme);
|
|
195
|
-
|
|
195
|
+
const metadata = running ? chrome : completionPainter(theme);
|
|
196
|
+
let details = metadata(status);
|
|
196
197
|
if (failureReason && isError && !running) details += chrome(" · ") + theme.fg("error", failureReason);
|
|
197
198
|
// An edit reports what it changed the way a diff does: lines added and removed.
|
|
198
199
|
else if (changes && !running && !isError) {
|
|
@@ -200,7 +201,7 @@ function renderControls(
|
|
|
200
201
|
+ theme.fg("toolDiffRemoved", `-${changes.removed}`) + chrome(")");
|
|
201
202
|
}
|
|
202
203
|
// A failed call produced no result worth counting; "(0 lines)" would only mislead.
|
|
203
|
-
else if (state.resultLineSummary && !running && !isError) details +=
|
|
204
|
+
else if (state.resultLineSummary && !running && !isError) details += metadata(` (${state.resultLineSummary})`);
|
|
204
205
|
if (nestedSummary && !running) details += chrome(" · ") + nestedSummary;
|
|
205
206
|
return nestedSummary ? prefixedSentence(details, chrome(prefix), indent, true) : prefixedText(details, chrome(prefix), indent);
|
|
206
207
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-compact-tools",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"description": "Tool rows for Pi in three styles: Claude, Codex, and Compact. Switch with /compact-tools; includes silent mode and a GitHub Dark theme.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/release-notes.json
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
+
"0.16.2": {
|
|
3
|
+
"New": [
|
|
4
|
+
"A concise README and a separate development guide",
|
|
5
|
+
"Seven refreshed real-time demos, including silent mode during work and in resumed sessions"
|
|
6
|
+
],
|
|
7
|
+
"Fix": [],
|
|
8
|
+
"Deprecated": []
|
|
9
|
+
},
|
|
10
|
+
"0.16.1": {
|
|
11
|
+
"New": [
|
|
12
|
+
"Minimal codemode summaries show each tool once: read 3 · bash 1 · edit 3 2; non-edit tools keep first-call order and edit always comes last",
|
|
13
|
+
"Plain counts use green for success, red for failure, and yellow for unfinished calls, without zero placeholders, count parentheses, status icons, pipes, or edit diff lists",
|
|
14
|
+
"Summary names retain their theme title hue at 75% brightness without bold; outcome counts retain their hues at 80% brightness",
|
|
15
|
+
"Completion duration and output-line metadata is one step brighter; rails, connectors, separators, main tool titles, and code previews are unchanged"
|
|
16
|
+
],
|
|
17
|
+
"Fix": [
|
|
18
|
+
"Interleaved nested calls aggregate into one group per tool, with success counts before failure counts",
|
|
19
|
+
"Reloads, resumed sessions, and /tree navigation preserve or restore nested counts and outcomes without retaining tool arguments, results, or edit diff bookkeeping",
|
|
20
|
+
"Unfinished calls and incomplete records remain visible, including when mixed with settled outcomes"
|
|
21
|
+
],
|
|
22
|
+
"Deprecated": []
|
|
23
|
+
},
|
|
2
24
|
"0.16.0": {
|
|
3
25
|
"New": [
|
|
4
26
|
"Completed codemode rows summarize nested tool successes and failures beside their duration and output-line count without changing model input",
|