pi-cc-extensions 1.0.0 → 1.0.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/README.en.md +2 -0
- package/README.md +3 -1
- package/extensions/config/config.ts +16 -0
- package/extensions/config/panel.ts +47 -0
- package/extensions/feature/compact-thinking.ts +1 -1
- package/extensions/feature/reference/subagent.ts +2 -1
- package/extensions/feature/shell/footer.ts +57 -10
- package/extensions/feature/shell/token-rate.ts +192 -0
- package/extensions/feature/shell/working-message.ts +52 -65
- package/extensions/renderer/compact-mode.ts +38 -28
- package/extensions/renderer/default-mode.ts +23 -463
- package/extensions/renderer/index.ts +3 -3
- package/extensions/renderer/markdown-enhance.ts +63 -22
- package/extensions/renderer/mouse/hover.ts +1 -1
- package/extensions/renderer/mouse/interaction.ts +2 -2
- package/extensions/renderer/mouse/packets.ts +1 -1
- package/extensions/renderer/mouse/sticky-prompt.ts +61 -9
- package/extensions/renderer/tool/ask-user-question.ts +1 -1
- package/extensions/renderer/tool/ccstyle-tool.ts +467 -0
- package/extensions/renderer/tool/codemode.ts +1 -1
- package/extensions/renderer/tool/diff/diff-edit-render.ts +1 -1
- package/extensions/renderer/tool/diff/diff-limits.ts +1 -1
- package/extensions/renderer/tool/diff/diff-write-render.ts +1 -1
- package/extensions/renderer/tool/diff/line-width-safety.ts +1 -1
- package/extensions/renderer/tool/grouping.ts +56 -50
- package/extensions/renderer/tool/message-display.ts +1 -1
- package/extensions/renderer/tool/names.ts +41 -1
- package/extensions/renderer/tool/result.ts +2 -862
- package/extensions/renderer/tool/tool-io.ts +735 -0
- package/extensions/renderer/tool/tool-state.ts +138 -0
- package/extensions/utils/format.ts +9 -0
- package/package.json +1 -1
- package/themes/cc-light.json +1 -1
- package/extensions/renderer/tool/show-more-hint.ts +0 -48
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "./codemode.ts";
|
|
23
23
|
import { getToolMouseTui } from "../mouse/scroll.ts";
|
|
24
24
|
import { mcpToolTitle } from "./mcp-title.ts";
|
|
25
|
-
import { collapseHintText, isToolTuiFullscreen, showMoreHintText } from "./
|
|
25
|
+
import { collapseHintText, isToolTuiFullscreen, showMoreHintText } from "./names.ts";
|
|
26
26
|
import { stripAnsi, stripBackgroundAnsi, stripLeadingStatusIcon } from "../../utils/ansi-text.ts";
|
|
27
27
|
import { walkComponentTree } from "../../utils/component-tree.ts";
|
|
28
28
|
import {
|
|
@@ -33,14 +33,8 @@ import {
|
|
|
33
33
|
toolCallSummary,
|
|
34
34
|
type ToolCallSummary,
|
|
35
35
|
} from "./names.ts";
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
formatToolDuration,
|
|
39
|
-
headTruncateToWidth,
|
|
40
|
-
isLiveToolCall,
|
|
41
|
-
textFromResult,
|
|
42
|
-
toolViewportWidth,
|
|
43
|
-
} from "./result.ts";
|
|
36
|
+
import { formatToolDuration, headTruncateToWidth, toolViewportWidth } from "./result.ts";
|
|
37
|
+
import { isLiveToolCall } from "./tool-state.ts";
|
|
44
38
|
import {
|
|
45
39
|
patchRegistry,
|
|
46
40
|
TOOL_GROUPING_GENERATION_KEY as GENERATION_KEY,
|
|
@@ -263,8 +257,8 @@ function codemodeResultSummary(tool: any): ToolCallSummary | undefined {
|
|
|
263
257
|
}
|
|
264
258
|
|
|
265
259
|
/**
|
|
266
|
-
* 组内 shell 行的尾巴:只报耗时(`· 12.4s
|
|
267
|
-
*
|
|
260
|
+
* 组内 shell 行的尾巴:只报耗时(`· 12.4s`)。输出和错误正文都在展开后看;
|
|
261
|
+
* 失败靠行首的 ✗,组头另有 failed 计数。
|
|
268
262
|
* 耗时取 pi 记在结果上的 durationMs(单卡渲染上下文里的同一个值),运行中还拿不到就不报。
|
|
269
263
|
*/
|
|
270
264
|
function shellResultTail(
|
|
@@ -273,23 +267,59 @@ function shellResultTail(
|
|
|
273
267
|
toolStatus: ToolStatus,
|
|
274
268
|
): string {
|
|
275
269
|
if (!SHELL_TOOL_NAMES.has(toolName(tool)) || toolStatus === "pending" || !tool?.result) return "";
|
|
276
|
-
const isError = tool.result?.isError === true;
|
|
277
|
-
// 失败报错误首行(不该只在展开后可见);成功只报耗时,行数是冗余信息。
|
|
278
|
-
const failure = isError
|
|
279
|
-
? collapsedResultSummary({
|
|
280
|
-
result: tool.result,
|
|
281
|
-
toolName: toolName(tool),
|
|
282
|
-
text: textFromResult(tool.result),
|
|
283
|
-
isError: true,
|
|
284
|
-
})
|
|
285
|
-
: "";
|
|
286
270
|
const durationMs = tool.result?.durationMs;
|
|
287
271
|
const duration =
|
|
288
272
|
typeof durationMs === "number" && Number.isFinite(durationMs) && durationMs >= 0
|
|
289
273
|
? formatToolDuration(durationMs)
|
|
290
274
|
: "";
|
|
291
|
-
|
|
292
|
-
|
|
275
|
+
return duration ? ` ${fg("dim", `· ${duration}`)}` : "";
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** 分组折叠态的一行子工具:`├/└` + 状态图标 + 与组内同一套摘要。 */
|
|
279
|
+
function collapsedGroupToolLine(
|
|
280
|
+
tool: any,
|
|
281
|
+
last: boolean,
|
|
282
|
+
fg: (color: string, text: string) => string,
|
|
283
|
+
width: number,
|
|
284
|
+
): string {
|
|
285
|
+
const toolStatus = status(tool);
|
|
286
|
+
const color = toolStatus === "pending" ? "accent" : toolStatus;
|
|
287
|
+
const summary = askUserResultSummary(tool) ?? codemodeResultSummary(tool) ?? toolSummary(tool);
|
|
288
|
+
const prefix = ` ${fg("dim", last ? "└" : "├")} ${fg(color, statusIcon(toolStatus))} `;
|
|
289
|
+
const detail = fg("dim", summary.detail);
|
|
290
|
+
const result = shellResultTail(tool, fg, toolStatus);
|
|
291
|
+
const rowWidth = toolViewportWidth(width);
|
|
292
|
+
const mainWidth = Math.max(
|
|
293
|
+
0,
|
|
294
|
+
rowWidth - visibleWidth(prefix) - visibleWidth(detail) - visibleWidth(result),
|
|
295
|
+
);
|
|
296
|
+
return truncateToWidth(
|
|
297
|
+
`${prefix}${renderToolSummary(summary, mainWidth, fg)}${detail}${result}`,
|
|
298
|
+
rowWidth,
|
|
299
|
+
"",
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
type GroupHeaderCounts = { pending: number; success: number; error: number };
|
|
304
|
+
|
|
305
|
+
/** 组头计数:`2 done · 1 failed`。没有计数时返回空串。 */
|
|
306
|
+
function groupCountText(
|
|
307
|
+
counts: GroupHeaderCounts,
|
|
308
|
+
fg: (color: string, text: string) => string,
|
|
309
|
+
): string {
|
|
310
|
+
return (["pending", "success", "error"] as const)
|
|
311
|
+
.filter((key) => counts[key])
|
|
312
|
+
.map((key) => {
|
|
313
|
+
const label = key === "pending" ? "running" : key === "success" ? "done" : "failed";
|
|
314
|
+
const color = key === "pending" ? "accent" : key;
|
|
315
|
+
return `${fg(color, String(counts[key]))} ${label}`;
|
|
316
|
+
})
|
|
317
|
+
.join(` ${fg("dim", "·")} `);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** 组头圆点色:有失败取 error,否则有运行中取 accent,否则 success。 */
|
|
321
|
+
function groupOverallStatus(counts: GroupHeaderCounts): ToolStatus {
|
|
322
|
+
return counts.error ? "error" : counts.pending ? "pending" : "success";
|
|
293
323
|
}
|
|
294
324
|
|
|
295
325
|
/**
|
|
@@ -464,17 +494,10 @@ export class ToolGroupComponent extends Container {
|
|
|
464
494
|
const fg = (color: string, text: string) => theme?.fg?.(color, text) ?? text;
|
|
465
495
|
const counts = { pending: 0, success: 0, error: 0 };
|
|
466
496
|
for (const tool of this.children) counts[status(tool)]++;
|
|
467
|
-
const countText = (
|
|
468
|
-
.filter((key) => counts[key])
|
|
469
|
-
.map((key) => {
|
|
470
|
-
const label = key === "pending" ? "running" : key === "success" ? "done" : "failed";
|
|
471
|
-
const color = key === "pending" ? "accent" : key;
|
|
472
|
-
return `${fg(color, String(counts[key]))} ${label}`;
|
|
473
|
-
})
|
|
474
|
-
.join(` ${fg("dim", "·")} `);
|
|
497
|
+
const countText = groupCountText(counts, fg);
|
|
475
498
|
const names = new Set(this.children.map(toolName));
|
|
476
499
|
const label = names.size === 1 ? toolTitle(this.children[0]) : "Multiple Tools";
|
|
477
|
-
const overall
|
|
500
|
+
const overall = groupOverallStatus(counts);
|
|
478
501
|
if ((this.children as any[]).some(isAnimatingTool)) scheduleGroupAnimation(this.patch);
|
|
479
502
|
const overallColor = overall === "pending" ? "accent" : overall;
|
|
480
503
|
// 圆点保持 dim;hover 只高亮可点击文字。
|
|
@@ -519,24 +542,7 @@ export class ToolGroupComponent extends Container {
|
|
|
519
542
|
const branch = index === total - 1 ? "└" : "├";
|
|
520
543
|
const continuation = index === total - 1 ? " " : "│ ";
|
|
521
544
|
if (!this._expanded) {
|
|
522
|
-
|
|
523
|
-
askUserResultSummary(tool) ?? codemodeResultSummary(tool) ?? toolSummary(tool);
|
|
524
|
-
const prefix = ` ${fg("dim", branch)} ${fg(color, statusIcon(toolStatus))} `;
|
|
525
|
-
const detail = fg("dim", summary.detail);
|
|
526
|
-
const result = shellResultTail(tool, fg, toolStatus);
|
|
527
|
-
// 与单工具卡标题同宽,宽屏右侧留白一致
|
|
528
|
-
const rowWidth = toolViewportWidth(width);
|
|
529
|
-
const mainWidth = Math.max(
|
|
530
|
-
0,
|
|
531
|
-
rowWidth - visibleWidth(prefix) - visibleWidth(detail) - visibleWidth(result),
|
|
532
|
-
);
|
|
533
|
-
lines.push(
|
|
534
|
-
truncateToWidth(
|
|
535
|
-
`${prefix}${renderToolSummary(summary, mainWidth, fg)}${detail}${result}`,
|
|
536
|
-
rowWidth,
|
|
537
|
-
"",
|
|
538
|
-
),
|
|
539
|
-
);
|
|
545
|
+
lines.push(collapsedGroupToolLine(tool, index === total - 1, fg, width));
|
|
540
546
|
continue;
|
|
541
547
|
}
|
|
542
548
|
const rendered = visibleLines(Array.isArray(childPaints?.[index]) ? childPaints[index] : []);
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { Markdown, Spacer, Text } from "@earendil-works/pi-tui";
|
|
7
7
|
import { MESSAGE_DISPLAY_PATCH, patchRegistry } from "../../utils/patch-keys.ts";
|
|
8
8
|
import { config } from "../../config/config.ts";
|
|
9
|
-
import { showMoreHintText } from "./
|
|
9
|
+
import { showMoreHintText } from "./names.ts";
|
|
10
10
|
import { walkComponentTree } from "../../utils/component-tree.ts";
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { posix, win32 } from "node:path";
|
|
2
2
|
import type { ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
import { getKeybindings, visibleWidth } from "@earendil-works/pi-tui";
|
|
4
4
|
import { config } from "../../config/config.ts";
|
|
5
5
|
import { oneLine } from "../../utils/format.ts";
|
|
6
6
|
import { headTruncateToWidth } from "./result.ts";
|
|
@@ -427,3 +427,43 @@ export function renderToolSummary(
|
|
|
427
427
|
? `${fg("toolTitle", title)}${fg("dim", headTruncateToWidth(` ${summary.payload}`, room))}`
|
|
428
428
|
: fg("toolTitle", title);
|
|
429
429
|
}
|
|
430
|
+
|
|
431
|
+
let toolTuiFullscreen: boolean | undefined;
|
|
432
|
+
|
|
433
|
+
export function setToolTuiFullscreen(value: boolean): void {
|
|
434
|
+
toolTuiFullscreen = value;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export function isToolTuiFullscreen(): boolean {
|
|
438
|
+
return toolTuiFullscreen !== false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function formatKeyPart(part: string): string {
|
|
442
|
+
// 与 pi 内置 keybinding-hints 一致:macOS 上 alt 显示为 option
|
|
443
|
+
return process.platform === "darwin" && part.toLowerCase() === "alt" ? "option" : part;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** 默认展开快捷键(app.tools.expand)显示文本;未配置时回退 ctrl+o。 */
|
|
447
|
+
export function expandShortcutText(): string {
|
|
448
|
+
const keys = getKeybindings().getKeys("app.tools.expand");
|
|
449
|
+
if (keys.length === 0) return "ctrl+o";
|
|
450
|
+
return keys
|
|
451
|
+
.join("/")
|
|
452
|
+
.split("/")
|
|
453
|
+
.map((part) => part.split("+").map(formatKeyPart).join("+"))
|
|
454
|
+
.join("/");
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function showMoreHintText(): string {
|
|
458
|
+
return isToolTuiFullscreen() ? "click to show more" : `${expandShortcutText()} to show more`;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** 展开卡的收起提示,与折叠态 showMoreHintText 同一位置对称。 */
|
|
462
|
+
export function collapseHintText(): string {
|
|
463
|
+
return isToolTuiFullscreen() ? "↑ Collapse" : `${expandShortcutText()} to collapse`;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** 该行是否带展开态收起提示(用于展开卡的 hint hover 命中)。 */
|
|
467
|
+
export function isCollapseHintLine(plainLine: string): boolean {
|
|
468
|
+
return plainLine.includes(collapseHintText());
|
|
469
|
+
}
|