pi-extensions-tool-display 1.3.1 → 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-extensions-tool-display",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Pi tool display host and shared result-rendering protocol for extensions",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -48,7 +48,7 @@
48
48
  "tool-display"
49
49
  ],
50
50
  "dependencies": {
51
- "pi-extensions-i18n": "^0.7.0"
51
+ "pi-extensions-i18n": "^0.8.0"
52
52
  },
53
53
  "peerDependencies": {
54
54
  "@earendil-works/pi-coding-agent": ">=0.80.0",
@@ -12,6 +12,7 @@ import { shortenPath } from "./render-utils.js";
12
12
  import type { InspectorSettingItem } from "./settings-inspector-modal.js";
13
13
  import { type ToolDisplayConfig } from "./types.js";
14
14
  import {
15
+ NOTICE_TAG_COLOR,
15
16
  notifyWithSource,
16
17
  type NoticeColor,
17
18
  type NoticeLevel,
@@ -20,8 +21,8 @@ import {
20
21
 
21
22
  /** 本扩展的提示标签;短且唯一,便于在会话里定位来源。 */
22
23
  const NOTICE_TAG = "display";
23
- /** 提示标签颜色;与其它扩展错开,避免看起来像同一条消息。 */
24
- const NOTICE_COLOR: NoticeColor = "muted";
24
+ /** 提示标签颜色:所有扩展统一用弱化色,来源靠 tag 文本区分,不靠颜色。 */
25
+ const NOTICE_COLOR: NoticeColor = NOTICE_TAG_COLOR;
25
26
  /** 本扩展的提示来源。 */
26
27
  const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
27
28
 
@@ -54,9 +54,9 @@ export function buildDiffSummaryText(stats: DiffSummaryStats, width: number): st
54
54
  }
55
55
 
56
56
  const summaryCandidates = [
57
- `↳ diff +${stats.added} -${stats.removed} • ${stats.hunks} ${pluralize(stats.hunks, "hunk")} • ${stats.files} ${pluralize(stats.files, "file")}`,
58
- `↳ diff +${stats.added} -${stats.removed} • ${stats.hunks}h • ${stats.files}f`,
59
- `↳ diff +${stats.added} -${stats.removed}`,
57
+ `diff +${stats.added} -${stats.removed} • ${stats.hunks} ${pluralize(stats.hunks, "hunk")} • ${stats.files} ${pluralize(stats.files, "file")}`,
58
+ `diff +${stats.added} -${stats.removed} • ${stats.hunks}h • ${stats.files}f`,
59
+ `diff +${stats.added} -${stats.removed}`,
60
60
  `+${stats.added} -${stats.removed}`,
61
61
  "diff",
62
62
  "…",
@@ -1871,7 +1871,7 @@ function renderDiffStatBar(stats: DiffStats, width: number, theme: DiffTheme): s
1871
1871
 
1872
1872
  function buildDiffSummaryBasePieces(stats: DiffStats, theme: DiffTheme): string[] {
1873
1873
  return [
1874
- theme.fg("toolOutput", `↳ ${emphasis(theme, "diff")}`),
1874
+ theme.fg("toolOutput", emphasis(theme, "diff")),
1875
1875
  theme.fg("toolDiffAdded", `+${stats.added}`),
1876
1876
  theme.fg("toolDiffRemoved", `-${stats.removed}`),
1877
1877
  ];
@@ -2074,7 +2074,7 @@ export function renderEditDiffResult(
2074
2074
  const diffText = safeGetDiff(details);
2075
2075
  if (!diffText.trim()) {
2076
2076
  if (!fallbackText.trim()) {
2077
- return new Text(theme.fg("muted", "↳ edit completed (no diff payload)"), 0, 0);
2077
+ return new Text(theme.fg("muted", "edit completed (no diff payload)"), 0, 0);
2078
2078
  }
2079
2079
  return new Text(theme.fg("toolOutput", fallbackText), 0, 0);
2080
2080
  }
@@ -2084,11 +2084,11 @@ export function renderEditDiffResult(
2084
2084
  parsed = parseDiff(diffText);
2085
2085
  } catch (error) {
2086
2086
  const message = error instanceof Error ? error.message : String(error);
2087
- return new Text(theme.fg("warning", `↳ unable to render diff: ${message}`), 0, 0);
2087
+ return new Text(theme.fg("warning", `unable to render diff: ${message}`), 0, 0);
2088
2088
  }
2089
2089
 
2090
2090
  if (parsed.entries.length === 0) {
2091
- return new Text(theme.fg("muted", "↳ no diff data"), 0, 0);
2091
+ return new Text(theme.fg("muted", "no diff data"), 0, 0);
2092
2092
  }
2093
2093
 
2094
2094
  const splitRows = buildSplitRows(parsed.entries);
@@ -2164,7 +2164,7 @@ function renderWriteHeader(
2164
2164
  ): string {
2165
2165
  const actionLabel = headerLabel?.trim() || (wasOverwrite ? "overwritten" : "created");
2166
2166
  return stabilizeBackgroundResets(
2167
- truncateToWidth(theme.fg("toolOutput", `↳ ${emphasis(theme, actionLabel)}`), width),
2167
+ truncateToWidth(theme.fg("toolOutput", emphasis(theme, actionLabel)), width),
2168
2168
  );
2169
2169
  }
2170
2170
 
@@ -2368,9 +2368,9 @@ function buildWriteOverwriteGuardText(guard: WriteOverwriteGuard, width: number)
2368
2368
  }
2369
2369
 
2370
2370
  const candidates = [
2371
- `↳ overwrite diff omitted (${guard.previousLineCount} → ${guard.nextLineCount} lines)`,
2372
- `↳ overwrite diff omitted (${guard.previousLineCount}→${guard.nextLineCount})`,
2373
- "↳ overwrite diff omitted",
2371
+ `overwrite diff omitted (${guard.previousLineCount} → ${guard.nextLineCount} lines)`,
2372
+ `overwrite diff omitted (${guard.previousLineCount}→${guard.nextLineCount})`,
2373
+ "overwrite diff omitted",
2374
2374
  "diff omitted",
2375
2375
  "…",
2376
2376
  ];
@@ -2399,7 +2399,7 @@ export function renderWriteDiffResult(
2399
2399
  ): Component {
2400
2400
  if (typeof content !== "string") {
2401
2401
  if (!fallbackText.trim()) {
2402
- return new Text(theme.fg("muted", "↳ write completed"), 0, 0);
2402
+ return new Text(theme.fg("muted", "write completed"), 0, 0);
2403
2403
  }
2404
2404
  return new Text(theme.fg("toolOutput", fallbackText), 0, 0);
2405
2405
  }
package/src/index.ts CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  type ToolDisplayConfig,
24
24
  } from "./types.js";
25
25
  import {
26
+ NOTICE_TAG_COLOR,
26
27
  installNoticeRenderer,
27
28
  notifyWithSource,
28
29
  type NoticeColor,
@@ -31,8 +32,8 @@ import {
31
32
 
32
33
  /** 本扩展的提示标签;短且唯一,便于在会话里定位来源。 */
33
34
  const NOTICE_TAG = "display";
34
- /** 提示标签颜色;与其它扩展错开,避免看起来像同一条消息。 */
35
- const NOTICE_COLOR: NoticeColor = "muted";
35
+ /** 提示标签颜色:所有扩展统一用弱化色,来源靠 tag 文本区分,不靠颜色。 */
36
+ const NOTICE_COLOR: NoticeColor = NOTICE_TAG_COLOR;
36
37
  /** 本扩展的提示来源。 */
37
38
  const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
38
39
 
@@ -2,6 +2,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
2
2
  import { isRecord } from "./tool-metadata.js";
3
3
  import { onReloadShutdown } from "./extension-lifecycle.js";
4
4
  import {
5
+ NOTICE_TAG_COLOR,
5
6
  notifyWithSource,
6
7
  type NoticeColor,
7
8
  type NoticeSource,
@@ -9,8 +10,8 @@ import {
9
10
 
10
11
  /** 本扩展的提示标签;短且唯一,便于在会话里定位来源。 */
11
12
  const NOTICE_TAG = "display";
12
- /** 提示标签颜色;与其它扩展错开,避免看起来像同一条消息。 */
13
- const NOTICE_COLOR: NoticeColor = "muted";
13
+ /** 提示标签颜色:所有扩展统一用弱化色,来源靠 tag 文本区分,不靠颜色。 */
14
+ const NOTICE_COLOR: NoticeColor = NOTICE_TAG_COLOR;
14
15
  /** 本扩展的提示来源。 */
15
16
  const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
16
17
 
@@ -68,6 +68,15 @@ import {
68
68
  shouldRenderWriteCallSummary,
69
69
  } from "./write-display-utils.js";
70
70
 
71
+ /**
72
+ * 结果摘要行(`loaded 42 lines`、`3 matches returned`、`(no output)`)不加前缀符号。
73
+ *
74
+ * `↳` 在会话里归活动区独占,表示「这条命令正在流出的输出尾巴」
75
+ * (见 pi-clean-mode 的 `activity.ts`)。两边都写 `↳` 时,同一个符号会在同一屏里
76
+ * 指两件事:一边是还没跑完的实时尾巴,一边是已经落定的结果计数。
77
+ * 摘要本身靠弱化色与「紧接在调用行下面」就能认出身份,不需要额外符号。
78
+ */
79
+
71
80
  interface BuiltInTools {
72
81
  read: ReturnType<typeof createReadTool>;
73
82
  grep: ReturnType<typeof createGrepTool>;
@@ -447,7 +456,7 @@ function buildPreviewText(
447
456
  expanded: boolean,
448
457
  ): string {
449
458
  if (lines.length === 0) {
450
- return theme.fg("muted", "↳ (no output)");
459
+ return theme.fg("muted", "(no output)");
451
460
  }
452
461
 
453
462
  const { shown, remaining } = previewLines(lines, maxLines);
@@ -473,9 +482,9 @@ function formatBashNoOutputLine(
473
482
  theme: RenderTheme,
474
483
  ): string {
475
484
  if (isLikelyQuietCommand(command)) {
476
- return theme.fg("muted", "↳ command completed (no output)");
485
+ return theme.fg("muted", "command completed (no output)");
477
486
  }
478
- return theme.fg("muted", "↳ (no output)");
487
+ return theme.fg("muted", "(no output)");
479
488
  }
480
489
 
481
490
  function truncationHint(
@@ -958,7 +967,7 @@ function formatReadSummary(
958
967
  const lineCount = lines.length;
959
968
  let summary = theme.fg(
960
969
  "muted",
961
- `↳ loaded ${lineCount} ${pluralize(lineCount, "line")}`,
970
+ `loaded ${lineCount} ${pluralize(lineCount, "line")}`,
962
971
  );
963
972
  summary += theme.fg(
964
973
  "warning",
@@ -978,7 +987,7 @@ function formatSearchSummary(
978
987
  const count = countNonEmptyLines(lines);
979
988
  let summary = theme.fg(
980
989
  "muted",
981
- `↳ ${count} ${pluralize(count, unitLabel, pluralLabel)} returned`,
990
+ `${count} ${pluralize(count, unitLabel, pluralLabel)} returned`,
982
991
  );
983
992
  summary += theme.fg(
984
993
  "warning",
@@ -996,7 +1005,7 @@ function formatBashSummary(
996
1005
  const lineCount = lines.length;
997
1006
  const summary = theme.fg(
998
1007
  "muted",
999
- `↳ ${lineCount} ${pluralize(lineCount, "line")} returned`,
1008
+ `${lineCount} ${pluralize(lineCount, "line")} returned`,
1000
1009
  );
1001
1010
  return summary;
1002
1011
  }
@@ -1105,7 +1114,7 @@ function renderBashErrorResult(
1105
1114
  details: BashToolDetails | undefined,
1106
1115
  ): Text {
1107
1116
  const lines = prepareOutputLines(rawOutput, options);
1108
- let text = theme.fg("error", "↳ command failed");
1117
+ let text = theme.fg("error", "command failed");
1109
1118
 
1110
1119
  if (lines.length > 0) {
1111
1120
  const maxLines = getBashPreviewLineLimit(lines, options, config);
@@ -1270,7 +1279,7 @@ function renderMcpResult(
1270
1279
  const lineCount = countNonEmptyLines(lines);
1271
1280
  let summary = theme.fg(
1272
1281
  "muted",
1273
- `↳ ${lineCount} ${pluralize(lineCount, "line")} returned`,
1282
+ `${lineCount} ${pluralize(lineCount, "line")} returned`,
1274
1283
  );
1275
1284
  summary += formatExpandHint(theme);
1276
1285
  if (config.showTruncationHints && truncation.truncated) {
@@ -2061,7 +2070,7 @@ export function registerToolDisplayOverrides(
2061
2070
  }
2062
2071
 
2063
2072
  if (!options.expanded && config.bashCollapsedLines === 0) {
2064
- let hidden = theme.fg("muted", "↳ output hidden");
2073
+ let hidden = theme.fg("muted", "output hidden");
2065
2074
  if (config.showTruncationHints) {
2066
2075
  hidden += formatBashTruncationHints(details, theme);
2067
2076
  }