pi-extensions-tool-display 1.3.1 → 1.3.3
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 +2 -2
- package/src/config-modal.ts +3 -2
- package/src/diff-presentation.ts +3 -3
- package/src/diff-renderer.ts +9 -9
- package/src/index.ts +3 -2
- package/src/thinking-label.ts +3 -2
- package/src/tool-overrides.ts +18 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extensions-tool-display",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
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.
|
|
51
|
+
"pi-extensions-i18n": "^0.9.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@earendil-works/pi-coding-agent": ">=0.80.0",
|
package/src/config-modal.ts
CHANGED
|
@@ -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 =
|
|
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
|
|
package/src/diff-presentation.ts
CHANGED
|
@@ -54,9 +54,9 @@ export function buildDiffSummaryText(stats: DiffSummaryStats, width: number): st
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const summaryCandidates = [
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
"…",
|
package/src/diff-renderer.ts
CHANGED
|
@@ -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",
|
|
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", "
|
|
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",
|
|
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", "
|
|
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",
|
|
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
|
-
|
|
2372
|
-
|
|
2373
|
-
"
|
|
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", "
|
|
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 =
|
|
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
|
|
package/src/thinking-label.ts
CHANGED
|
@@ -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 =
|
|
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
|
|
package/src/tool-overrides.ts
CHANGED
|
@@ -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", "
|
|
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", "
|
|
485
|
+
return theme.fg("muted", "command completed (no output)");
|
|
477
486
|
}
|
|
478
|
-
return theme.fg("muted", "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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", "
|
|
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
|
-
|
|
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", "
|
|
2073
|
+
let hidden = theme.fg("muted", "output hidden");
|
|
2065
2074
|
if (config.showTruncationHints) {
|
|
2066
2075
|
hidden += formatBashTruncationHints(details, theme);
|
|
2067
2076
|
}
|