pi-agent-flow 0.4.3 → 0.4.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-agent-flow",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Flow-state delegation extension for Pi coding agent.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/render-utils.ts CHANGED
@@ -87,6 +87,17 @@ export function getTruncationBudget(prefixLength: number): number {
87
87
  return Math.max(width - prefixLength, 1);
88
88
  }
89
89
 
90
+ /** Fixed content budget for collapsed-line text (dir/exe/log). */
91
+ export const CONTENT_MAX = 40;
92
+
93
+ /**
94
+ * Compute how many visible chars of content fit after a prefix,
95
+ * using the fixed CONTENT_MAX budget. Floor of 8 to keep things readable.
96
+ */
97
+ export function contentBudget(prefixVisibleLen: number): number {
98
+ return Math.max(CONTENT_MAX - prefixVisibleLen, 8);
99
+ }
100
+
90
101
  /**
91
102
  * Truncate an ANSI-colored string to at most `max` visible characters,
92
103
  * preserving ANSI codes in the kept portions. Does not inject reset codes
@@ -95,14 +106,14 @@ export function getTruncationBudget(prefixLength: number): number {
95
106
  function truncateAnsi(text: string, max: number): string {
96
107
  if (visibleLength(text) <= max) return text;
97
108
 
98
- if (max < 6) {
99
- // Not enough room for " ... " — just truncate without ellipsis
109
+ if (max < 3) {
110
+ // Not enough room for '…' — just truncate without ellipsis
100
111
  const { raw } = takeVisible(text, max);
101
112
  return raw;
102
113
  }
103
114
 
104
115
  const head = Math.ceil(max * 0.6);
105
- const tail = max - head - 5; // 5 = " ... ".length
116
+ const tail = max - head - 1; // 1 = '…'.length
106
117
 
107
118
  // Walk through the string, collecting raw chars until we've consumed
108
119
  // `count` visible characters. ANSI sequences are copied through without
@@ -160,7 +171,7 @@ function truncateAnsi(text: string, max: number): string {
160
171
 
161
172
  const tailRaw = takeVisibleFromEnd(text, tail);
162
173
 
163
- return headResult.raw + " ... " + tailRaw;
174
+ return headResult.raw + "\u2026" + tailRaw;
164
175
  }
165
176
 
166
177
  export function truncateChars(text: string, max: number): string {
package/render.ts CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  isFlowError,
23
23
  isFlowSuccess,
24
24
  } from "./types.js";
25
- import { formatFixedTokens, formatCompactStats, formatFlowTypeName } from "./render-utils.js";
25
+ import { formatFixedTokens, formatCompactStats, formatFlowTypeName, truncateChars, contentBudget } from "./render-utils.js";
26
26
 
27
27
  function shortenPath(p: string): string {
28
28
  const home = os.homedir();
@@ -235,23 +235,28 @@ function renderFlowCollapsed(
235
235
 
236
236
  // dir: line (intent/objective)
237
237
  if (r.intent) {
238
- container.addChild(new TruncatedText(`${theme.fg("dim", "├─ dir:")} ${theme.fg("dim", r.intent)}`, 0, 0));
238
+ const dirContent = truncateChars(r.intent, contentBudget(10));
239
+ container.addChild(new TruncatedText(`${theme.fg("dim", "├─ dir:")} ${theme.fg("dim", dirContent)}`, 0, 0));
239
240
  }
240
241
 
241
242
  // exe: line (last tool call)
242
243
  const lastTool = getLastToolCall(r.messages);
243
244
  if (lastTool) {
244
245
  const exeStr = formatFlowToolCall(lastTool.name, lastTool.args, theme.fg.bind(theme));
245
- container.addChild(new TruncatedText(`${theme.fg("dim", "├─ exe:")} ${exeStr}`, 0, 0));
246
+ const exeContent = truncateChars(exeStr, contentBudget(10));
247
+ container.addChild(new TruncatedText(`${theme.fg("dim", "├─ exe:")} ${exeContent}`, 0, 0));
246
248
  }
247
249
 
248
250
  // log: line (last assistant text or streaming)
249
251
  if (flowOutput) {
250
- container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("dim", flowOutput)}`, 0, 0));
252
+ const logContent = truncateChars(flowOutput, contentBudget(10));
253
+ container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("dim", logContent)}`, 0, 0));
251
254
  } else if (streamingText) {
252
- container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("dim", streamingText)}`, 0, 0));
255
+ const logContent = truncateChars(streamingText, contentBudget(10));
256
+ container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("dim", logContent)}`, 0, 0));
253
257
  } else if (error && r.errorMessage) {
254
- container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("error", r.errorMessage)}`, 0, 0));
258
+ const logContent = truncateChars(r.errorMessage, contentBudget(10));
259
+ container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("error", logContent)}`, 0, 0));
255
260
  } else {
256
261
  container.addChild(new TruncatedText(`${theme.fg("dim", "└─ log:")} ${theme.fg("dim", "[n/a]")}`, 0, 0));
257
262
  }
@@ -371,22 +376,26 @@ function renderActivityPanel(
371
376
 
372
377
  // dir: line (intent/objective)
373
378
  if (r.intent) {
374
- container.addChild(new TruncatedText(`${theme.fg("dim", indent + "├─ dir:")} ${theme.fg("dim", r.intent)}`, 0, 0));
379
+ const dirContent = truncateChars(r.intent, contentBudget(10));
380
+ container.addChild(new TruncatedText(`${theme.fg("dim", indent + "├─ dir:")} ${theme.fg("dim", dirContent)}`, 0, 0));
375
381
  }
376
382
 
377
383
  // exe: line (last tool call)
378
384
  const lastTool = getLastToolCall(r.messages);
379
385
  if (lastTool) {
380
386
  const exeStr = formatFlowToolCall(lastTool.name, lastTool.args, theme.fg.bind(theme));
381
- container.addChild(new TruncatedText(`${theme.fg("dim", indent + "├─ exe:")} ${exeStr}`, 0, 0));
387
+ const exeContent = truncateChars(exeStr, contentBudget(10));
388
+ container.addChild(new TruncatedText(`${theme.fg("dim", indent + "├─ exe:")} ${exeContent}`, 0, 0));
382
389
  }
383
390
 
384
391
  // log: line (last assistant text)
385
392
  const lastText = getLastAssistantText(r.messages);
386
393
  if (lastText) {
387
- container.addChild(new TruncatedText(`${theme.fg("dim", indent + "└─ log:")} ${theme.fg("dim", lastText)}`, 0, 0));
394
+ const logContent = truncateChars(lastText, contentBudget(10));
395
+ container.addChild(new TruncatedText(`${theme.fg("dim", indent + "└─ log:")} ${theme.fg("dim", logContent)}`, 0, 0));
388
396
  } else if (error && r.errorMessage) {
389
- container.addChild(new TruncatedText(`${theme.fg("dim", indent + "└─ log:")} ${theme.fg("error", r.errorMessage)}`, 0, 0));
397
+ const logContent = truncateChars(r.errorMessage, contentBudget(10));
398
+ container.addChild(new TruncatedText(`${theme.fg("dim", indent + "└─ log:")} ${theme.fg("error", logContent)}`, 0, 0));
390
399
  } else {
391
400
  container.addChild(new TruncatedText(`${theme.fg("dim", indent + "└─ log:")} ${theme.fg("dim", "[n/a]")}`, 0, 0));
392
401
  }