@heyhuynhgiabuu/pi-pretty 0.6.29 → 0.6.31

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/src/tools/read.ts CHANGED
@@ -3,19 +3,9 @@
3
3
  import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
4
  import type { AgentToolResult, ExtensionAPI, ExtensionContext, ToolDefinition } from "@earendil-works/pi-coding-agent";
5
5
  import { getReadmePath } from "@earendil-works/pi-coding-agent";
6
- import {
7
- BG_BASE,
8
- BG_ERROR,
9
- FG_DIM,
10
- FG_LNUM,
11
- FG_RULE,
12
- RST,
13
- resolveBaseBackground,
14
- TOOL_RESULT_INDENT,
15
- termWidth,
16
- } from "../config.js";
6
+ import { BG_BASE, BG_ERROR, FG_DIM, FG_LNUM, FG_RULE, RST, resolveBaseBackground, termWidth } from "../config.js";
17
7
  import { normalizeLineEndings, shortPath } from "../helpers.js";
18
- import { fillToolBackground, fillToolBody, renderFileContent, renderToolError } from "../render.js";
8
+ import { fillToolBackground, fillToolBody, renderFileContent, renderToolError, toolIndent } from "../render.js";
19
9
  import { resolveTextCtor } from "../tui-text.js";
20
10
  import type { ReadDetails, RenderCtxLike, SdkToolDef, TextContent, ThemeLike } from "../types.js";
21
11
  import { wrapExecuteWithMetrics } from "./metrics.js";
@@ -79,6 +69,7 @@ export function registerReadTool(
79
69
  promptSnippet: sdkTool.promptSnippet,
80
70
  promptGuidelines: sdkTool.promptGuidelines,
81
71
  constrainedSampling: sdkTool.constrainedSampling,
72
+ outputSchema: sdkTool.outputSchema as ToolDefinition["outputSchema"],
82
73
  renderShell: "self",
83
74
 
84
75
  execute: wrapExecuteWithMetrics(async (tid, params, sig, _upd, ctx: ExtensionContext) => {
@@ -114,9 +105,10 @@ export function registerReadTool(
114
105
  return text;
115
106
  }
116
107
 
108
+ const ind = toolIndent(ctx);
117
109
  const path = String(args.path ?? "");
118
110
  const label = theme.fg("error", theme.bold("→ read"));
119
- text.setText(fillToolBackground(`\n${TOOL_RESULT_INDENT}${label} ${theme.fg("toolTitle", path)}\n`, BG_ERROR));
111
+ text.setText(fillToolBackground(`\n${ind}${label} ${theme.fg("toolTitle", path)}\n`, BG_ERROR, undefined, ind));
120
112
  return text;
121
113
  },
122
114
 
@@ -125,9 +117,10 @@ export function registerReadTool(
125
117
 
126
118
  const renderToken = nextReadRenderToken(ctx);
127
119
  const text = ctx.lastComponent ?? new TC("", 0, 0);
120
+ const ind = toolIndent(ctx);
128
121
 
129
122
  if (ctx.isError) {
130
- text.setText(renderToolError(getText(result) || "Error", theme));
123
+ text.setText(renderToolError(getText(result) || "Error", theme, ind));
131
124
  return text;
132
125
  }
133
126
 
@@ -155,7 +148,7 @@ export function registerReadTool(
155
148
  if (!ctx.expanded) {
156
149
  if (skillName) {
157
150
  const header = renderSkillHeader(skillName, false, theme);
158
- text.setText(fillToolBody(`\n${TOOL_RESULT_INDENT}${header}\n`, BG_BASE));
151
+ text.setText(fillToolBody(`\n${ind}${header}\n`, BG_BASE, undefined, ind));
159
152
  return text;
160
153
  }
161
154
  const docsLabel = getPiDocsLabel(filePath, cwd);
@@ -164,8 +157,10 @@ export function registerReadTool(
164
157
  : `${theme.fg("toolTitle", theme.bold("→ read"))} ${theme.fg("toolTitle", p2)}`;
165
158
  text.setText(
166
159
  fillToolBody(
167
- `\n${TOOL_RESULT_INDENT}${title}${theme.fg("dim", off2)} ${FG_DIM}${total} lines — ctrl+o to expand${RST}`,
160
+ `\n${ind}${title}${theme.fg("dim", off2)} ${FG_DIM}${total} lines — ctrl+o to expand${RST}`,
168
161
  BG_BASE,
162
+ undefined,
163
+ ind,
169
164
  ),
170
165
  );
171
166
  return text;
@@ -175,7 +170,8 @@ export function registerReadTool(
175
170
  const offset = d.offset || 0;
176
171
  const nw = Math.max(3, String(offset + total).length);
177
172
  const gw = nw + 3;
178
- const cw = Math.max(1, tw - gw);
173
+ // Default pad 1 keeps its historical budget; extra padding is subtracted so rows do not grow.
174
+ const cw = Math.max(1, tw - gw - Math.max(0, ind.length - 1));
179
175
 
180
176
  const header = skillName
181
177
  ? renderSkillHeader(skillName, true, theme)
@@ -189,27 +185,27 @@ export function registerReadTool(
189
185
  };
190
186
  const cachedHighlight = getCachedReadHighlight(ctx, highlightRequest);
191
187
  if (cachedHighlight !== undefined) {
192
- const highlighted = buildHighlightedRead(cachedHighlight, header, skillName, offset, nw, tw);
193
- text.setText(fillToolBody(highlighted, BG_BASE));
188
+ const highlighted = buildHighlightedRead(cachedHighlight, header, skillName, offset, nw, tw, ind);
189
+ text.setText(fillToolBody(highlighted, BG_BASE, undefined, ind));
194
190
  return text;
195
191
  }
196
192
 
197
- const out: string[] = ["", `${TOOL_RESULT_INDENT}${header}`, ""];
198
- out.push(`${TOOL_RESULT_INDENT}${FG_RULE}${"─".repeat(tw - 1)}${RST}`);
193
+ const out: string[] = ["", `${ind}${header}`, ""];
194
+ out.push(`${ind}${FG_RULE}${"─".repeat(Math.max(1, tw - ind.length))}${RST}`);
199
195
  for (let i = 0; i < show.length; i++) {
200
196
  const ln = offset + i + 1;
201
197
  const code = show[i] ?? "";
202
198
  const display = code.length > cw ? `${code.slice(0, Math.max(0, cw - 1))}${FG_DIM}›${RST}` : code;
203
199
  const lineNo = String(ln);
204
200
  out.push(
205
- `${TOOL_RESULT_INDENT}${FG_LNUM}${" ".repeat(Math.max(0, nw - lineNo.length))}${lineNo}${RST} ${FG_RULE}│${RST} ${display}${RST}`,
201
+ `${ind}${FG_LNUM}${" ".repeat(Math.max(0, nw - lineNo.length))}${lineNo}${RST} ${FG_RULE}│${RST} ${display}${RST}`,
206
202
  );
207
203
  }
208
204
  if (total > maxShow) {
209
- out.push(`${TOOL_RESULT_INDENT}${FG_DIM}… ${total - maxShow} more lines (${total} total)${RST}`);
205
+ out.push(`${ind}${FG_DIM}… ${total - maxShow} more lines (${total} total)${RST}`);
210
206
  }
211
207
  const rendered = out.join("\n");
212
- text.setText(fillToolBody(rendered, BG_BASE));
208
+ text.setText(fillToolBody(rendered, BG_BASE, undefined, ind));
213
209
 
214
210
  // Async syntax highlighting via Shiki. The component is reused across
215
211
  // expansion changes, so stale work must not restore an older view.
@@ -217,8 +213,8 @@ export function registerReadTool(
217
213
  .then((hl) => {
218
214
  if (!isCurrentReadRender(ctx, renderToken)) return;
219
215
  setCachedReadHighlight(ctx, highlightRequest, hl);
220
- const highlighted = buildHighlightedRead(hl, header, skillName, offset, nw, tw);
221
- text.setText(fillToolBody(highlighted, BG_BASE));
216
+ const highlighted = buildHighlightedRead(hl, header, skillName, offset, nw, tw, ind);
217
+ text.setText(fillToolBody(highlighted, BG_BASE, undefined, ind));
222
218
  ctx.invalidate?.();
223
219
  })
224
220
  .catch(() => {});
@@ -229,8 +225,10 @@ export function registerReadTool(
229
225
  const fc = result.content?.[0];
230
226
  text.setText(
231
227
  fillToolBody(
232
- `${TOOL_RESULT_INDENT}${theme.fg("dim", fc && "text" in fc ? String(fc.text).slice(0, 120) : "done")}`,
228
+ `${ind}${theme.fg("dim", fc && "text" in fc ? String(fc.text).slice(0, 120) : "done")}`,
233
229
  BG_BASE,
230
+ undefined,
231
+ ind,
234
232
  ),
235
233
  );
236
234
  return text;
@@ -293,16 +291,17 @@ function buildHighlightedRead(
293
291
  offset: number,
294
292
  nw: number,
295
293
  tw: number,
294
+ ind: string,
296
295
  ): string {
297
296
  const padded = highlighted
298
297
  .split("\n")
299
298
  .map((line, index) => {
300
299
  const lineNo = String(offset + index + 1);
301
- return `${TOOL_RESULT_INDENT}${FG_LNUM}${" ".repeat(Math.max(0, nw - lineNo.length))}${lineNo}${RST} ${FG_RULE}│${RST} ${line}${RST}`;
300
+ return `${ind}${FG_LNUM}${" ".repeat(Math.max(0, nw - lineNo.length))}${lineNo}${RST} ${FG_RULE}│${RST} ${line}${RST}`;
302
301
  })
303
302
  .join("\n");
304
- const divider = skillName ? `${TOOL_RESULT_INDENT}${FG_RULE}${"─".repeat(Math.max(1, tw - 1))}${RST}\n` : "";
305
- return `\n${TOOL_RESULT_INDENT}${header}\n\n${divider}${padded}`;
303
+ const divider = skillName ? `${ind}${FG_RULE}${"─".repeat(Math.max(1, tw - ind.length))}${RST}\n` : "";
304
+ return `\n${ind}${header}\n\n${divider}${padded}`;
306
305
  }
307
306
 
308
307
  function getText(result: Result): string {
package/src/types.ts CHANGED
@@ -35,6 +35,10 @@ export interface RenderCtxLike {
35
35
  state: Record<string, unknown>;
36
36
  expanded?: boolean;
37
37
  invalidate?: () => void;
38
+ /** Host horizontal padding (pi >= 1.1). Absent on older hosts; renderers fall back to 1. */
39
+ outputPad?: number;
40
+ /** Final host-measured execution time in ms; undefined while running or on older hosts. */
41
+ durationMs?: number;
38
42
  }
39
43
 
40
44
  export interface TextLike {
@@ -139,6 +143,7 @@ export interface SdkToolDef {
139
143
  promptSnippet?: string;
140
144
  promptGuidelines?: string[];
141
145
  constrainedSampling?: false | ConstrainedSamplingConfig;
146
+ outputSchema?: unknown;
142
147
  execute: (...args: any[]) => Promise<AgentToolResult<any>>;
143
148
  }
144
149