pi-quiet 0.1.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 +53 -0
- package/package.json +37 -0
- package/src/index.ts +76 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# pi-quiet
|
|
2
|
+
|
|
3
|
+
Calm tool rendering for the [pi](https://pi.dev) coding agent.
|
|
4
|
+
|
|
5
|
+
pi renders every bash call with the full command text, a multi-line output
|
|
6
|
+
preview, and timing — useful when you're debugging a command, noisy when the
|
|
7
|
+
agent is doing routine work. `pi-quiet` collapses each bash call to two lines:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
$ ls -la /tmp | head -20
|
|
11
|
+
→ ok · 15 lines · … -rw-r--r-- 1 user staff 5742 Aug 26 22:17 README.md
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Multi-line commands show `(+N lines)`. Failures show a red `error`. Streaming
|
|
15
|
+
shows `… running`.
|
|
16
|
+
|
|
17
|
+
Press **ctrl+o** (pi's `app.tools.expand` binding) and the stock built-in
|
|
18
|
+
rendering returns in full — complete commands, full output, truncation
|
|
19
|
+
warnings. Press it again to re-collapse. It's a live toggle over the whole
|
|
20
|
+
transcript: work collapsed, expand when something looks off.
|
|
21
|
+
|
|
22
|
+
## Display-only, by construction
|
|
23
|
+
|
|
24
|
+
The extension re-registers the built-in `bash` tool via pi's own
|
|
25
|
+
`createBashToolDefinition` and overrides only the two render slots. Execution
|
|
26
|
+
*is* the built-in tool:
|
|
27
|
+
|
|
28
|
+
- the model receives the full, untruncated-by-us output;
|
|
29
|
+
- permission systems, reviewers, and sandboxes that hook execution are
|
|
30
|
+
unaffected;
|
|
31
|
+
- session logs store the full result.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pi install npm:pi-quiet
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or try it for one session:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pi -e npm:pi-quiet
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
pi shows a one-time notice that the built-in `bash` tool was overridden —
|
|
46
|
+
that's this extension, and it's expected.
|
|
47
|
+
|
|
48
|
+
## Caveats
|
|
49
|
+
|
|
50
|
+
- Covers `bash` only (the dominant chatter source). `read`/`grep`/`find`/`ls`
|
|
51
|
+
may follow.
|
|
52
|
+
- The expanded path delegates to pi's built-in renderer, so a pi upgrade that
|
|
53
|
+
reshapes renderer internals can require a patch release here.
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-quiet",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Calm tool rendering for the pi coding agent: each bash call collapses to one line; ctrl+o brings back full built-in rendering. Display-only — execution, permissions, and model context are untouched.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/schuettc/pi-extensions.git",
|
|
10
|
+
"directory": "packages/pi-quiet"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"pi-package",
|
|
14
|
+
"pi-extension",
|
|
15
|
+
"pi-coding-agent",
|
|
16
|
+
"tui",
|
|
17
|
+
"tool-output",
|
|
18
|
+
"quiet"
|
|
19
|
+
],
|
|
20
|
+
"files": [
|
|
21
|
+
"src",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"pi": {
|
|
25
|
+
"extensions": [
|
|
26
|
+
"./src/index.ts"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@earendil-works/pi-coding-agent": "^0.84.3",
|
|
34
|
+
"@earendil-works/pi-tui": "^0.84.3",
|
|
35
|
+
"typescript": "^5.6.0"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* quiet-tools: collapse bash tool chatter to one line per call.
|
|
3
|
+
*
|
|
4
|
+
* Re-registers the built-in bash tool (execution untouched — it IS the
|
|
5
|
+
* built-in, via createBashToolDefinition) and overrides only the two render
|
|
6
|
+
* slots. Collapsed (the default): the call renders as a single truncated
|
|
7
|
+
* `$ command` line and the result as a single muted summary line. Expanded
|
|
8
|
+
* (ctrl+o / app.tools.expand): both slots defer to the built-in renderer,
|
|
9
|
+
* so the full command, streamed output, truncation warnings, and duration
|
|
10
|
+
* come back exactly as stock pi shows them.
|
|
11
|
+
*
|
|
12
|
+
* Display-only by design: permission gating, auto-review, and the sandbox
|
|
13
|
+
* all hook execution, which this file never touches.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
createBashToolDefinition,
|
|
18
|
+
type ExtensionAPI,
|
|
19
|
+
} from "@earendil-works/pi-coding-agent";
|
|
20
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
21
|
+
|
|
22
|
+
function firstLine(command: string): { line: string; more: number } {
|
|
23
|
+
const lines = command.split("\n");
|
|
24
|
+
return { line: lines[0] ?? "", more: lines.length - 1 };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function resultText(result: { content?: { type: string; text?: string }[] }): string {
|
|
28
|
+
return (result.content ?? [])
|
|
29
|
+
.filter((c) => c.type === "text")
|
|
30
|
+
.map((c) => c.text ?? "")
|
|
31
|
+
.join("\n");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default function quietTools(pi: ExtensionAPI) {
|
|
35
|
+
const builtin = createBashToolDefinition(process.cwd());
|
|
36
|
+
|
|
37
|
+
pi.registerTool({
|
|
38
|
+
...builtin,
|
|
39
|
+
|
|
40
|
+
renderCall(args: any, theme: any, context: any) {
|
|
41
|
+
if (context.expanded && builtin.renderCall) {
|
|
42
|
+
return builtin.renderCall(args, theme, context);
|
|
43
|
+
}
|
|
44
|
+
const command = typeof args?.command === "string" ? args.command : "...";
|
|
45
|
+
const { line, more } = firstLine(command.trim());
|
|
46
|
+
const suffix = more > 0 ? theme.fg("muted", ` (+${more} lines)`) : "";
|
|
47
|
+
// Text handles width truncation; keep the line itself short anyway so
|
|
48
|
+
// narrow panes stay one visual row.
|
|
49
|
+
const shown = line.length > 200 ? `${line.slice(0, 200)}…` : line;
|
|
50
|
+
return new Text(
|
|
51
|
+
theme.fg("toolTitle", theme.bold(`$ ${shown}`)) + suffix,
|
|
52
|
+
0,
|
|
53
|
+
0,
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
renderResult(result: any, options: any, theme: any, context: any) {
|
|
58
|
+
if (options.expanded && builtin.renderResult) {
|
|
59
|
+
return builtin.renderResult(result, options, theme, context);
|
|
60
|
+
}
|
|
61
|
+
if (options.isPartial) {
|
|
62
|
+
return new Text(theme.fg("muted", " … running"), 0, 0);
|
|
63
|
+
}
|
|
64
|
+
const text = resultText(result).trim();
|
|
65
|
+
const lineCount = text ? text.split("\n").length : 0;
|
|
66
|
+
const status = result.isError ? theme.fg("error", "error") : "ok";
|
|
67
|
+
const tail = text ? text.split("\n").at(-1) ?? "" : "";
|
|
68
|
+
const tailShown = tail.length > 120 ? `${tail.slice(0, 120)}…` : tail;
|
|
69
|
+
const summary =
|
|
70
|
+
lineCount <= 1
|
|
71
|
+
? ` → ${status}${tailShown ? theme.fg("toolOutput", ` · ${tailShown}`) : ""}`
|
|
72
|
+
: ` → ${status} · ${lineCount} lines${tailShown ? theme.fg("toolOutput", ` · … ${tailShown}`) : ""}`;
|
|
73
|
+
return new Text(theme.fg("muted", summary), 0, 0);
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|