pi-cc-extensions 0.8.48 → 0.8.49
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 +17 -36
- package/README.md +13 -12
- package/assets/readme/welcome.webp +0 -0
- package/extensions/config/config.ts +245 -0
- package/extensions/config/panel.ts +469 -0
- package/extensions/{compact-thinking.ts → feature/compact-thinking.ts} +43 -6
- package/extensions/{markdown-enhance.ts → feature/markdown-enhance.ts} +88 -62
- package/extensions/{pi-startup-header.ts → feature/pi-startup-header.ts} +129 -56
- package/extensions/index.ts +9 -9
- package/extensions/renderer/index.ts +890 -0
- package/extensions/renderer/mouse-interaction.ts +1344 -0
- package/extensions/renderer/show-more-hint.ts +40 -0
- package/extensions/{tool-diff → renderer/tool-diff}/diff-renderer.ts +3 -2
- package/extensions/{tool-diff → renderer/tool-diff}/line-width-safety.ts +2 -1
- package/extensions/{tool-grouping.ts → renderer/tool-grouping.ts} +71 -10
- package/extensions/renderer/tool-result.ts +717 -0
- package/package.json +1 -1
- package/themes/cc-dark.json +2 -2
- package/themes/cc-light.json +2 -2
- package/extensions/claude-code-style.ts +0 -3348
- /package/extensions/{agent-autocomplete.ts → feature/agent-autocomplete.ts} +0 -0
- /package/extensions/{context.ts → feature/context.ts} +0 -0
- /package/extensions/{pi-aliases.ts → feature/pi-aliases.ts} +0 -0
- /package/extensions/{session-reference-core.ts → feature/session-reference-core.ts} +0 -0
- /package/extensions/{session-reference.ts → feature/session-reference.ts} +0 -0
- /package/extensions/{working-message.ts → feature/working-message.ts} +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/ATTRIBUTION.md +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/ansi-utils.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/diff-presentation.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/index.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/render-utils.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/shiki-highlight.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/types.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/write-display-utils.ts +0 -0
- /package/extensions/{tool-diff → renderer/tool-diff}/write-execution.ts +0 -0
- /package/extensions/{fullscreen-detect.ts → utils/fullscreen-detect.ts} +0 -0
- /package/extensions/{tool-loading-icon.ts → utils/tool-loading-icon.ts} +0 -0
- /package/extensions/{tool-result-sanitize.ts → utils/tool-result-sanitize.ts} +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* show-more 提示文本:fullscreen 下鼠标 hover/click 可用,提示 "click to show more";
|
|
3
|
+
* 其他模式(regular 保留终端原生 scrollback、不启用鼠标上报)提示默认展开快捷键。
|
|
4
|
+
*
|
|
5
|
+
* tui 模式由 mouse-interaction 在 renderer 回调中维护;未安装时按 fullscreen 处理,
|
|
6
|
+
* 保证纯渲染测试与既有行为不变。
|
|
7
|
+
*/
|
|
8
|
+
import { getKeybindings } from "@earendil-works/pi-tui";
|
|
9
|
+
|
|
10
|
+
let toolTuiFullscreen: boolean | undefined;
|
|
11
|
+
|
|
12
|
+
export function setToolTuiFullscreen(value: boolean): void {
|
|
13
|
+
toolTuiFullscreen = value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isToolTuiFullscreen(): boolean {
|
|
17
|
+
return toolTuiFullscreen !== false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function formatKeyPart(part: string): string {
|
|
21
|
+
// 与 pi 内置 keybinding-hints 一致:macOS 上 alt 显示为 option
|
|
22
|
+
return process.platform === "darwin" && part.toLowerCase() === "alt" ? "option" : part;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** 默认展开快捷键(app.tools.expand)显示文本;未配置时回退 ctrl+o。 */
|
|
26
|
+
export function expandShortcutText(): string {
|
|
27
|
+
const keys = getKeybindings().getKeys("app.tools.expand");
|
|
28
|
+
if (keys.length === 0) return "ctrl+o";
|
|
29
|
+
return keys
|
|
30
|
+
.join("/")
|
|
31
|
+
.split("/")
|
|
32
|
+
.map((part) => part.split("+").map(formatKeyPart).join("+"))
|
|
33
|
+
.join("/");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function showMoreHintText(): string {
|
|
37
|
+
return isToolTuiFullscreen()
|
|
38
|
+
? "click to show more"
|
|
39
|
+
: `${expandShortcutText()} to show more`;
|
|
40
|
+
}
|
|
@@ -30,10 +30,11 @@ import {
|
|
|
30
30
|
resolveDiffPresentationMode,
|
|
31
31
|
type DiffPresentationMode,
|
|
32
32
|
} from "./diff-presentation.ts";
|
|
33
|
-
import { sanitizeToolResultText } from "
|
|
33
|
+
import { sanitizeToolResultText } from "../../utils/tool-result-sanitize.ts";
|
|
34
34
|
import { pluralize, sanitizeAnsiForThemedOutput } from "./render-utils.ts";
|
|
35
35
|
import { splitWriteContentLines } from "./write-display-utils.ts";
|
|
36
36
|
import { MAX_HL_CHARS, shikiHighlightCache } from "./shiki-highlight.ts";
|
|
37
|
+
import { showMoreHintText } from "../show-more-hint.ts";
|
|
37
38
|
import {
|
|
38
39
|
DEFAULT_TOOL_DISPLAY_CONFIG,
|
|
39
40
|
type DiffIndicatorMode,
|
|
@@ -2319,7 +2320,7 @@ function applyLineLimit(
|
|
|
2319
2320
|
DIFF_WIDTH_OPS,
|
|
2320
2321
|
);
|
|
2321
2322
|
|
|
2322
|
-
const clickLabel =
|
|
2323
|
+
const clickLabel = showMoreHintText();
|
|
2323
2324
|
const clickIndex = hintText.lastIndexOf(clickLabel);
|
|
2324
2325
|
const styledHint =
|
|
2325
2326
|
hovered && !expanded && clickIndex >= 0
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { normalizeDiffRenderWidth } from "./diff-presentation.ts";
|
|
2
2
|
import { pluralize } from "./render-utils.ts";
|
|
3
|
+
import { showMoreHintText } from "../show-more-hint.ts";
|
|
3
4
|
|
|
4
5
|
export interface WidthMeasurementOps {
|
|
5
6
|
measure(text: string): number;
|
|
@@ -71,7 +72,7 @@ export function buildCollapsedDiffHintText(
|
|
|
71
72
|
: undefined;
|
|
72
73
|
|
|
73
74
|
const candidates = [
|
|
74
|
-
`… (${[remainingText, hiddenHunksText,
|
|
75
|
+
`… (${[remainingText, hiddenHunksText, showMoreHintText()].filter(Boolean).join(" • ")})`,
|
|
75
76
|
`… (${[remainingText, hiddenHunksText].filter(Boolean).join(" • ")})`,
|
|
76
77
|
`… (${[shortRemainingText, shortHiddenHunksText].filter(Boolean).join(" • ")})`,
|
|
77
78
|
options.hiddenHunks > 0
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AssistantMessageComponent, ToolExecutionComponent } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Container, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
|
-
import { TOOL_LOADING_INTERVAL_MS, toolLoadingIcon } from "
|
|
4
|
-
import { sanitizeToolResultText } from "
|
|
3
|
+
import { TOOL_LOADING_INTERVAL_MS, toolLoadingIcon } from "../utils/tool-loading-icon.ts";
|
|
4
|
+
import { sanitizeToolResultText } from "../utils/tool-result-sanitize.ts";
|
|
5
|
+
import { showMoreHintText } from "./show-more-hint.ts";
|
|
5
6
|
|
|
6
7
|
const PATCH_KEY = Symbol.for("pi.ccstyle.tool-grouping-patch");
|
|
7
8
|
const PARENT_KEY = Symbol.for("pi.ccstyle.tool-grouping-parent");
|
|
@@ -250,7 +251,11 @@ let nextGroupId = 1;
|
|
|
250
251
|
export class ToolGroupComponent extends Container {
|
|
251
252
|
readonly toolCallId = `ccstyle-tool-group-${nextGroupId++}`;
|
|
252
253
|
readonly toolName = "Tool group";
|
|
253
|
-
private
|
|
254
|
+
private _expanded = false;
|
|
255
|
+
/** 分组是否展开(只读;测试与外部读状态用)。 */
|
|
256
|
+
get expanded(): boolean {
|
|
257
|
+
return this._expanded;
|
|
258
|
+
}
|
|
254
259
|
private hintHovered = false;
|
|
255
260
|
private readonly patch: Patch;
|
|
256
261
|
|
|
@@ -279,7 +284,7 @@ export class ToolGroupComponent extends Container {
|
|
|
279
284
|
}
|
|
280
285
|
|
|
281
286
|
setExpanded(expanded: boolean): void {
|
|
282
|
-
this.
|
|
287
|
+
this._expanded = expanded;
|
|
283
288
|
for (const tool of this.children) tool.setExpanded?.(expanded);
|
|
284
289
|
}
|
|
285
290
|
|
|
@@ -287,6 +292,30 @@ export class ToolGroupComponent extends Container {
|
|
|
287
292
|
this.hintHovered = hovered;
|
|
288
293
|
}
|
|
289
294
|
|
|
295
|
+
/**
|
|
296
|
+
* 展开时按局部行定位内部组件(null = 行属于 group 自身:空行/头行/尾行)。
|
|
297
|
+
* 行数计算与 render 保持一致:宽度 width-2 + 空行过滤。
|
|
298
|
+
*/
|
|
299
|
+
childAtRow(localRow: number, width: number): { component: any; row: number } | null {
|
|
300
|
+
if (!this._expanded || localRow < 2) return null;
|
|
301
|
+
let offset = 2;
|
|
302
|
+
for (const tool of this.children) {
|
|
303
|
+
let lines: string[] = [];
|
|
304
|
+
try {
|
|
305
|
+
const rendered = tool.render?.(Math.max(1, width - 2));
|
|
306
|
+
if (Array.isArray(rendered)) lines = visibleLines(rendered.map((line) => String(line)));
|
|
307
|
+
} catch {
|
|
308
|
+
lines = [];
|
|
309
|
+
}
|
|
310
|
+
const lineCount = Math.max(1, lines.length);
|
|
311
|
+
if (localRow < offset + lineCount) {
|
|
312
|
+
return { component: tool, row: localRow - offset };
|
|
313
|
+
}
|
|
314
|
+
offset += lineCount;
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
|
|
290
319
|
invalidate(): void {
|
|
291
320
|
for (const tool of this.children) tool.invalidate?.();
|
|
292
321
|
}
|
|
@@ -312,7 +341,7 @@ export class ToolGroupComponent extends Container {
|
|
|
312
341
|
const overallColor = overall === "pending" ? "accent" : overall;
|
|
313
342
|
const nameList = names.size > 1 ? ` ${fg("dim", `• ${toolNameList(this.children)}`)}` : "";
|
|
314
343
|
// 圆点保持 dim;hover 只高亮可点击文字。
|
|
315
|
-
const hint = `${fg("dim", "•")} ${fg(this.hintHovered ? "text" : "dim",
|
|
344
|
+
const hint = `${fg("dim", "•")} ${fg(this.hintHovered ? "text" : "dim", showMoreHintText())}`;
|
|
316
345
|
const lines = [
|
|
317
346
|
"",
|
|
318
347
|
truncateToWidth(
|
|
@@ -329,7 +358,7 @@ export class ToolGroupComponent extends Container {
|
|
|
329
358
|
const color = toolStatus === "pending" ? "accent" : toolStatus;
|
|
330
359
|
const branch = index === total - 1 ? "└" : "├";
|
|
331
360
|
const continuation = index === total - 1 ? " " : "│ ";
|
|
332
|
-
if (!this.
|
|
361
|
+
if (!this._expanded) {
|
|
333
362
|
const summary = toolSummary(tool);
|
|
334
363
|
lines.push(
|
|
335
364
|
truncateToWidth(
|
|
@@ -357,7 +386,7 @@ export class ToolGroupComponent extends Container {
|
|
|
357
386
|
expandedLines.push(prefix + content);
|
|
358
387
|
}
|
|
359
388
|
}
|
|
360
|
-
if (this.
|
|
389
|
+
if (this._expanded) {
|
|
361
390
|
const backgroundSlot =
|
|
362
391
|
overall === "error"
|
|
363
392
|
? "toolErrorBg"
|
|
@@ -438,9 +467,40 @@ function maybeGroup(patch: Patch, parent: any, component: any): void {
|
|
|
438
467
|
children.splice(index, 1);
|
|
439
468
|
}
|
|
440
469
|
|
|
470
|
+
/** /reload 不会重新 addChild;扫描当前 mounted roots,把已有工具重新送入同一分组规则。 */
|
|
471
|
+
function regroup(patch: Patch, root: any): void {
|
|
472
|
+
if (!patch.active || !patch.enabled() || !root) return;
|
|
473
|
+
const seen = new Set<any>();
|
|
474
|
+
const visit = (value: any): void => {
|
|
475
|
+
if (!value || typeof value !== "object" || seen.has(value)) return;
|
|
476
|
+
seen.add(value);
|
|
477
|
+
if (Array.isArray(value)) {
|
|
478
|
+
for (const child of value) visit(child);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const children = value.children;
|
|
482
|
+
if (Array.isArray(children)) {
|
|
483
|
+
for (const child of [...children]) {
|
|
484
|
+
if (child && typeof child === "object") child[PARENT_KEY] = value;
|
|
485
|
+
maybeGroup(patch, value, child);
|
|
486
|
+
}
|
|
487
|
+
for (const child of [...children]) {
|
|
488
|
+
if (!(child instanceof ToolGroupComponent) && !isGroupable(child)) visit(child);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
try {
|
|
492
|
+
const mounted = value.getMountedRoots?.();
|
|
493
|
+
if (Array.isArray(mounted)) visit(mounted);
|
|
494
|
+
} catch {
|
|
495
|
+
// renderer 切换中的惰性 Proxy 可能暂时没有 mounted roots。
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
visit(root);
|
|
499
|
+
}
|
|
500
|
+
|
|
441
501
|
export type ToolGroupingHooks = {
|
|
442
502
|
setTheme(theme: any): void;
|
|
443
|
-
refresh(): void;
|
|
503
|
+
refresh(root?: any): void;
|
|
444
504
|
shutdown(): void;
|
|
445
505
|
};
|
|
446
506
|
|
|
@@ -522,13 +582,14 @@ export function installToolGrouping(getEnabled: () => boolean): ToolGroupingHook
|
|
|
522
582
|
setTheme(theme: any) {
|
|
523
583
|
patch.theme = theme;
|
|
524
584
|
},
|
|
525
|
-
refresh() {
|
|
585
|
+
refresh(root?: any) {
|
|
526
586
|
const enabled = patch.enabled();
|
|
527
587
|
if (enabled !== patch.lastEnabled) {
|
|
528
588
|
patch.lastEnabled = enabled;
|
|
529
589
|
if (enabled) patch.generation++;
|
|
530
590
|
}
|
|
531
|
-
if (
|
|
591
|
+
if (enabled) regroup(patch, root);
|
|
592
|
+
else ungroup(patch);
|
|
532
593
|
},
|
|
533
594
|
shutdown() {
|
|
534
595
|
if (!patch.active) return;
|