pi-compact-transcript 0.1.0 → 0.2.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 +3 -2
- package/extensions/compact-transcript.ts +57 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
A compact transcript extension for [pi](https://pi.dev):
|
|
4
4
|
|
|
5
5
|
- Collapses hidden thinking blocks into `Thinking...` and consecutive thinking blocks into `Thinking... (Nx)`.
|
|
6
|
+
- Adds a short, visible next-step summary to collapsed thinking rows without exposing raw chain-of-thought.
|
|
6
7
|
- Collapses built-in tool calls/results into one-line previews.
|
|
7
|
-
- Consecutive tool uses are summarized as `Used N tools <latest tool preview>`.
|
|
8
|
+
- Consecutive tool uses in the same agent run are summarized as `Used N tools <latest tool preview>`.
|
|
8
9
|
- Minimizes vertical space so long agent runs do not scroll away as quickly.
|
|
9
10
|
|
|
10
11
|
## Install from GitHub
|
|
@@ -50,4 +51,4 @@ Set these in `~/.pi/agent/settings.json`, or use `/settings` in pi.
|
|
|
50
51
|
|
|
51
52
|
This extension overrides the built-in tool renderers for `bash`, `read`, `write`, `edit`, `grep`, `find`, and `ls`. It delegates execution to pi's original built-in tools; only display is changed.
|
|
52
53
|
|
|
53
|
-
The consecutive-thinking collapse
|
|
54
|
+
The consecutive-thinking collapse and compact self-rendered tool rows use pi's current internal TUI components. If pi changes those internal paths in a future release, the extension falls back to the normal hidden-thinking/tool rendering behavior.
|
|
@@ -119,7 +119,29 @@ function resultPreview(result: any): string {
|
|
|
119
119
|
return `${lines.length} lines`;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
function toolCallName(block: any): string {
|
|
123
|
+
return block?.name ?? block?.toolName ?? block?.tool_name ?? block?.tool?.name ?? "tool";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function toolCallArgs(block: any): any {
|
|
127
|
+
return block?.args ?? block?.input ?? block?.arguments ?? block?.tool?.args ?? {};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function nextStepSummary(content: any[], fromIndex: number): string {
|
|
131
|
+
const tools = content.slice(fromIndex + 1).filter((c: any) => c?.type === "toolCall");
|
|
132
|
+
if (tools.length === 0) return " Next, I’ll continue from this reasoning and respond with the result. I’ll keep the visible output brief.";
|
|
133
|
+
|
|
134
|
+
const first = tools[0];
|
|
135
|
+
const preview = limitPlain(previewFor(toolCallName(first), toolCallArgs(first)), 90);
|
|
136
|
+
if (tools.length === 1) {
|
|
137
|
+
return ` Next, I’ll use ${preview}. I’ll inspect the result and decide the next visible step from there.`;
|
|
138
|
+
}
|
|
139
|
+
const last = tools[tools.length - 1];
|
|
140
|
+
const lastPreview = limitPlain(previewFor(toolCallName(last), toolCallArgs(last)), 70);
|
|
141
|
+
return ` Next, I’ll run ${tools.length} tool calls, starting with ${preview}. I’ll use the latest result to continue, ending this batch around ${lastPreview}.`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function patchInternalRenderers() {
|
|
123
145
|
try {
|
|
124
146
|
const require = createRequire(import.meta.url);
|
|
125
147
|
const piMain = require.resolve("@earendil-works/pi-coding-agent");
|
|
@@ -127,7 +149,33 @@ async function patchAssistantThinkingRenderer() {
|
|
|
127
149
|
const assistantModule = await import(
|
|
128
150
|
pathToFileURL(join(distDir, "modes/interactive/components/assistant-message.js")).href
|
|
129
151
|
);
|
|
152
|
+
const toolExecutionModule = await import(
|
|
153
|
+
pathToFileURL(join(distDir, "modes/interactive/components/tool-execution.js")).href
|
|
154
|
+
);
|
|
130
155
|
const themeModule = await import(pathToFileURL(join(distDir, "modes/interactive/theme/theme.js")).href);
|
|
156
|
+
|
|
157
|
+
const ToolExecutionComponent = toolExecutionModule.ToolExecutionComponent;
|
|
158
|
+
if (ToolExecutionComponent?.prototype && !ToolExecutionComponent.prototype.__compactTranscriptPatched) {
|
|
159
|
+
const originalRender = ToolExecutionComponent.prototype.render;
|
|
160
|
+
ToolExecutionComponent.prototype.render = function (width: number) {
|
|
161
|
+
if (this.hideComponent) return [];
|
|
162
|
+
if (this.hasRendererDefinition?.() && this.getRenderShell?.() === "self") {
|
|
163
|
+
const contentLines = this.selfRenderContainer.render(width);
|
|
164
|
+
if (contentLines.length === 0 && this.imageComponents.length === 0) return [];
|
|
165
|
+
const lines = [...contentLines];
|
|
166
|
+
for (let i = 0; i < this.imageComponents.length; i++) {
|
|
167
|
+
const spacer = this.imageSpacers[i];
|
|
168
|
+
if (spacer) lines.push(...spacer.render(width));
|
|
169
|
+
const imageComponent = this.imageComponents[i];
|
|
170
|
+
if (imageComponent) lines.push(...imageComponent.render(width));
|
|
171
|
+
}
|
|
172
|
+
return lines;
|
|
173
|
+
}
|
|
174
|
+
return originalRender.call(this, width);
|
|
175
|
+
};
|
|
176
|
+
ToolExecutionComponent.prototype.__compactTranscriptPatched = true;
|
|
177
|
+
}
|
|
178
|
+
|
|
131
179
|
const Component = assistantModule.AssistantMessageComponent;
|
|
132
180
|
if (!Component?.prototype || Component.prototype.__compactTranscriptPatched) return;
|
|
133
181
|
const original = Component.prototype.updateContent;
|
|
@@ -161,8 +209,9 @@ async function patchAssistantThinkingRenderer() {
|
|
|
161
209
|
i += count - 1;
|
|
162
210
|
|
|
163
211
|
const label = count > 1 ? `${LABEL} (${count}x)` : LABEL;
|
|
212
|
+
const summary = nextStepSummary(message.content, i);
|
|
164
213
|
this.contentContainer.addChild(
|
|
165
|
-
new Text(themeModule.theme.italic(themeModule.theme.fg("thinkingText", label)), this.outputPad, 0),
|
|
214
|
+
new Text(themeModule.theme.italic(themeModule.theme.fg("thinkingText", limitPlain(`${label}${summary}`))), this.outputPad, 0),
|
|
166
215
|
);
|
|
167
216
|
|
|
168
217
|
const hasVisibleAfter = message.content
|
|
@@ -180,7 +229,7 @@ async function patchAssistantThinkingRenderer() {
|
|
|
180
229
|
}
|
|
181
230
|
|
|
182
231
|
export default async function (pi: ExtensionAPI) {
|
|
183
|
-
await
|
|
232
|
+
await patchInternalRenderers();
|
|
184
233
|
let current: ToolInfo[] = [];
|
|
185
234
|
let byId = new Map<string, ToolInfo>();
|
|
186
235
|
let consecutiveThinking = 0;
|
|
@@ -203,8 +252,11 @@ export default async function (pi: ExtensionAPI) {
|
|
|
203
252
|
ctx.ui.setWorkingMessage(LABEL);
|
|
204
253
|
});
|
|
205
254
|
|
|
206
|
-
pi.on("
|
|
255
|
+
pi.on("agent_start", () => {
|
|
207
256
|
resetTools();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
pi.on("turn_start", (_event, ctx) => {
|
|
208
260
|
consecutiveThinking = 0;
|
|
209
261
|
applyThinkingLabel(ctx);
|
|
210
262
|
});
|
|
@@ -219,6 +271,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
219
271
|
if (type && !type.startsWith("thinking_")) {
|
|
220
272
|
consecutiveThinking = 0;
|
|
221
273
|
applyThinkingLabel(ctx);
|
|
274
|
+
if (type === "text_delta" || type === "text_start") resetTools();
|
|
222
275
|
}
|
|
223
276
|
});
|
|
224
277
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-compact-transcript",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A compact transcript extension for pi: collapsed thinking and one-line tool previews.",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A compact transcript extension for pi: collapsed thinking summaries and one-line tool previews.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Alan Hagedorn <avhagedorn@gmail.com>",
|