pi-cc-extensions 0.5.5 → 0.6.0
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.md +20 -22
- package/assets/readme/fixed-editor-navigation.webp +0 -0
- package/extensions/claude-code-style.ts +164 -48
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
6
|
<a href="#安装"><img alt="Pi package" src="https://img.shields.io/badge/Pi-package-58B7FF?style=flat-square"></a>
|
|
7
|
-
<a href="./package.json"><img alt="Version 0.
|
|
7
|
+
<a href="./package.json"><img alt="Version 0.5.6" src="https://img.shields.io/badge/version-0.5.6-66E3C4?style=flat-square"></a>
|
|
8
8
|
<a href="#兼容性"><img alt="Node.js 22.19 or newer" src="https://img.shields.io/badge/Node.js-%E2%89%A522.19-66E3C4?style=flat-square"></a>
|
|
9
9
|
<a href="./extensions"><img alt="TypeScript extensions" src="https://img.shields.io/badge/TypeScript-extensions-3178C6?style=flat-square"></a>
|
|
10
10
|
</p>
|
|
@@ -15,10 +15,15 @@
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## 界面预览
|
|
19
19
|
|
|
20
20
|
<table>
|
|
21
21
|
<tr>
|
|
22
|
+
<td width="50%" align="center">
|
|
23
|
+
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Pi fixed-editor 中的工具结果、回到底部按钮与 Ctrl+End 快捷键">
|
|
24
|
+
<br>
|
|
25
|
+
<sub><b>固定编辑器工作流</b><br>工具结果摘要、折叠展开与键盘导航</sub>
|
|
26
|
+
</td>
|
|
22
27
|
<td width="50%" align="center">
|
|
23
28
|
<img src="./assets/readme/session-reference.webp" width="100%" alt="在 Pi 中通过 @ 补全选择历史 Session">
|
|
24
29
|
<br>
|
|
@@ -55,9 +60,9 @@
|
|
|
55
60
|
|
|
56
61
|
```text
|
|
57
62
|
/ccstyle # 切换开关
|
|
63
|
+
/ccstyle on # 开启
|
|
64
|
+
/ccstyle off # 关闭
|
|
58
65
|
/ccstyle status # 查看状态
|
|
59
|
-
/ccstyle compact # 紧凑摘要
|
|
60
|
-
/ccstyle minimal # 最小化输出
|
|
61
66
|
```
|
|
62
67
|
|
|
63
68
|
### 上下文窗口查看
|
|
@@ -82,6 +87,16 @@
|
|
|
82
87
|
|
|
83
88
|
Session 模糊查询默认显示 5 个候选;若已加载 `pi-subagents`,也可直接引用现有 SubAgent。一次提示词可以引用多个 Session;扩展会自动去重,并限制注入规模以避免上下文无限膨胀。更多细节见 [`extensions/session-reference/README.md`](./extensions/session-reference/README.md)。
|
|
84
89
|
|
|
90
|
+
### SubAgent `@` 补全
|
|
91
|
+
|
|
92
|
+
`extensions/agent-autocomplete.ts` 将 `~/.pi/agent/agents/*.md` 中定义的 SubAgent 接入 `@` 补全:
|
|
93
|
+
|
|
94
|
+
1. 在提示词中输入 `@agent-name`。
|
|
95
|
+
2. 从补全列表中选择 SubAgent。
|
|
96
|
+
3. 提交后自动注入委托指令;提示词中提到的每个 SubAgent 都会分别交由 Agent 工具处理。
|
|
97
|
+
|
|
98
|
+
该补全不会占用 `@session:` 的历史 Session 引用语法;修改 SubAgent 定义后执行 `/reload` 即可重新加载。
|
|
99
|
+
|
|
85
100
|
## 安装
|
|
86
101
|
|
|
87
102
|
从 npm 安装(推荐):
|
|
@@ -100,7 +115,7 @@ pi install git:github.com/minuque/pi-cc-extensions
|
|
|
100
115
|
|
|
101
116
|
```text
|
|
102
117
|
/context
|
|
103
|
-
/ccstyle
|
|
118
|
+
/ccstyle on
|
|
104
119
|
```
|
|
105
120
|
|
|
106
121
|
## 本地开发
|
|
@@ -126,20 +141,3 @@ pi install /absolute/path/to/pi-cc-extensions
|
|
|
126
141
|
|
|
127
142
|
- Node.js `>=22.19.0`
|
|
128
143
|
- 作为 Pi package 加载,入口由根目录 `package.json` 的 `pi.extensions` 显式声明
|
|
129
|
-
|
|
130
|
-
## 发布
|
|
131
|
-
|
|
132
|
-
发布前检查:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
npm test
|
|
136
|
-
npm pack --dry-run
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
使用 npm 发布。未指定 tag 时使用 `latest`:
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
npm run release
|
|
143
|
-
npm run release -- --tag next
|
|
144
|
-
npm run release -- --tag beta
|
|
145
|
-
```
|
|
Binary file
|
|
@@ -30,18 +30,13 @@ import { join, resolve } from "node:path";
|
|
|
30
30
|
* /ccstyle on enable
|
|
31
31
|
* /ccstyle off disable
|
|
32
32
|
* /ccstyle status show current state
|
|
33
|
-
* /ccstyle minimal hide most tool output in collapsed view
|
|
34
|
-
* /ccstyle compact show short summaries in collapsed view
|
|
35
33
|
*
|
|
36
34
|
* Shortcut:
|
|
37
35
|
* ctrl+shift+o toggle on/off
|
|
38
36
|
*/
|
|
39
37
|
|
|
40
|
-
type StyleMode = "compact" | "minimal";
|
|
41
|
-
|
|
42
38
|
type Config = {
|
|
43
39
|
enabled: boolean;
|
|
44
|
-
mode: StyleMode;
|
|
45
40
|
};
|
|
46
41
|
|
|
47
42
|
const CONFIG_PATH = join(homedir(), ".pi", "agent", "claude-code-style.json");
|
|
@@ -54,13 +49,12 @@ function loadConfig(): Config {
|
|
|
54
49
|
const parsed = JSON.parse(readFileSync(CONFIG_PATH, "utf8")) as Partial<Config>;
|
|
55
50
|
return {
|
|
56
51
|
enabled: parsed.enabled ?? true,
|
|
57
|
-
mode: parsed.mode === "minimal" ? "minimal" : "compact",
|
|
58
52
|
};
|
|
59
53
|
}
|
|
60
54
|
} catch {
|
|
61
55
|
// Ignore bad config and fall back to defaults.
|
|
62
56
|
}
|
|
63
|
-
return { enabled: true
|
|
57
|
+
return { enabled: true };
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
function saveConfig() {
|
|
@@ -318,6 +312,8 @@ const TOOL_MOUSE_WIDGET_KEY = "ccstyle-tool-mouse";
|
|
|
318
312
|
const TOOL_MOUSE_ENABLE = "\x1b[?1000h\x1b[?1006h";
|
|
319
313
|
const TOOL_MOUSE_DISABLE = "\x1b[?1006l\x1b[?1000l";
|
|
320
314
|
const ZENTUI_PAGE_UP_INPUT = /^\x1b\[5;9(?::[12])?~$|^\x1b\[57421;9(?::[12])?u$|^\x1b\[1;6A$/;
|
|
315
|
+
const ZENTUI_PAGE_DOWN_INPUT = /^\x1b\[6;9(?::[12])?~$|^\x1b\[57422;9(?::[12])?u$|^\x1b\[1;6B$/;
|
|
316
|
+
const SCROLL_BOTTOM_SHORTCUT = "ctrl+end";
|
|
321
317
|
let toolMouseTui: any = null;
|
|
322
318
|
let toolMouseUi: any = null;
|
|
323
319
|
let toolMouseInputUnsubscribe: (() => void) | null = null;
|
|
@@ -326,6 +322,9 @@ let toolMouseInputPatchOriginalHandle: ((...args: any[]) => any) | null = null;
|
|
|
326
322
|
let toolMouseInputPatchWrapper: ((...args: any[]) => any) | null = null;
|
|
327
323
|
let scrollButtonVisible = false;
|
|
328
324
|
let scrollButtonWidget: any = null;
|
|
325
|
+
let pendingScrollMessages = 0;
|
|
326
|
+
let assistantMessageActive = false;
|
|
327
|
+
let scrollButtonSyncScheduled = false;
|
|
329
328
|
|
|
330
329
|
function parseSgrMousePackets(data: string): SgrMousePacket[] | null {
|
|
331
330
|
const pattern = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
@@ -520,6 +519,96 @@ function isFixedEditorTui(tui: any): boolean {
|
|
|
520
519
|
return typeof ownRows?.get === "function" && ownRows.get !== inheritedRows?.get;
|
|
521
520
|
}
|
|
522
521
|
|
|
522
|
+
function formatShortcut(shortcut: string): string {
|
|
523
|
+
return shortcut
|
|
524
|
+
.split("+")
|
|
525
|
+
.map((part) => part.length <= 1 ? part.toUpperCase() : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`)
|
|
526
|
+
.join("+");
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function isScrollBottomInput(data: string): boolean {
|
|
530
|
+
return matchesKey(data, SCROLL_BOTTOM_SHORTCUT);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function isScrollNavigationInput(data: string): boolean {
|
|
534
|
+
if (
|
|
535
|
+
matchesKey(data, "pageUp")
|
|
536
|
+
|| matchesKey(data, "pageDown")
|
|
537
|
+
|| ZENTUI_PAGE_UP_INPUT.test(data)
|
|
538
|
+
|| ZENTUI_PAGE_DOWN_INPUT.test(data)
|
|
539
|
+
) {
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
const packets = parseSgrMousePackets(data);
|
|
543
|
+
return Boolean(packets?.some((packet) => {
|
|
544
|
+
const baseButton = packet.code & ~(4 | 8 | 16 | 32);
|
|
545
|
+
return packet.final === "M" && (baseButton === 64 || baseButton === 65);
|
|
546
|
+
}));
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function directRenderLines(component: any, width: number): string[] {
|
|
550
|
+
try {
|
|
551
|
+
const lines = component?.render?.(width);
|
|
552
|
+
return Array.isArray(lines) ? lines : [];
|
|
553
|
+
} catch {
|
|
554
|
+
return [];
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/** Render only the transcript portion that fixed-editor leaves scrollable. */
|
|
559
|
+
function renderFixedScrollableRoot(tui: any, width: number): string[] {
|
|
560
|
+
const children = Array.isArray(tui?.children) ? tui.children : [];
|
|
561
|
+
const editorIndex = children.findIndex((child: any) =>
|
|
562
|
+
containsEditorLike(child, tui.focusedComponent),
|
|
563
|
+
);
|
|
564
|
+
const end = editorIndex >= 2 ? editorIndex - 2 : children.length;
|
|
565
|
+
return children.slice(0, end).flatMap((child: any) => directRenderLines(child, width));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function isFixedEditorAtBottom(tui: any): boolean {
|
|
569
|
+
if (!isFixedEditorTui(tui)) return true;
|
|
570
|
+
const visibleLines = Array.isArray(tui?.previousLines) ? tui.previousLines : [];
|
|
571
|
+
if (visibleLines.length === 0) return true;
|
|
572
|
+
const width = Math.max(1, Number(tui?.terminal?.columns) || 80);
|
|
573
|
+
const rootLines = renderFixedScrollableRoot(tui, width);
|
|
574
|
+
if (rootLines.length <= visibleLines.length) return true;
|
|
575
|
+
const tail = rootLines.slice(-visibleLines.length);
|
|
576
|
+
return tail.every((line, index) =>
|
|
577
|
+
stripTerminalSequences(String(line)) === stripTerminalSequences(String(visibleLines[index] ?? "")),
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function hideScrollButton(tui: any): void {
|
|
582
|
+
const changed = scrollButtonVisible || pendingScrollMessages > 0;
|
|
583
|
+
scrollButtonVisible = false;
|
|
584
|
+
pendingScrollMessages = 0;
|
|
585
|
+
if (changed) tui.requestRender?.();
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function scheduleScrollButtonSync(tui: any, data: string): void {
|
|
589
|
+
if (!scrollButtonVisible || !isScrollNavigationInput(data) || scrollButtonSyncScheduled) return;
|
|
590
|
+
scrollButtonSyncScheduled = true;
|
|
591
|
+
const previousLines = tui.previousLines;
|
|
592
|
+
const check = (attempt: number) => {
|
|
593
|
+
scrollButtonSyncScheduled = false;
|
|
594
|
+
if (toolMouseTui !== tui || !scrollButtonVisible) return;
|
|
595
|
+
// Pi renders on its own frame timer. Do not inspect the old visible window
|
|
596
|
+
// before Zentui has applied the new scroll offset, or PageUp at bottom would
|
|
597
|
+
// immediately hide the button it just requested.
|
|
598
|
+
const rendered = tui.previousLines !== previousLines;
|
|
599
|
+
if (!rendered && attempt < 4) {
|
|
600
|
+
scrollButtonSyncScheduled = true;
|
|
601
|
+
const timer = setTimeout(() => check(attempt + 1), 16);
|
|
602
|
+
if (typeof timer === "object" && timer !== null && "unref" in timer) {
|
|
603
|
+
(timer as { unref: () => void }).unref();
|
|
604
|
+
}
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (isFixedEditorAtBottom(tui)) hideScrollButton(tui);
|
|
608
|
+
};
|
|
609
|
+
process.nextTick(() => check(0));
|
|
610
|
+
}
|
|
611
|
+
|
|
523
612
|
function updateScrollButtonFromInput(tui: any, data: string): void {
|
|
524
613
|
if (!isFixedEditorTui(tui)) return;
|
|
525
614
|
|
|
@@ -532,8 +621,15 @@ function updateScrollButtonFromInput(tui: any, data: string): void {
|
|
|
532
621
|
});
|
|
533
622
|
}
|
|
534
623
|
|
|
535
|
-
const jumpedBottom =
|
|
536
|
-
|
|
624
|
+
const jumpedBottom =
|
|
625
|
+
matchesKey(data, "enter")
|
|
626
|
+
|| matchesKey(data, "return")
|
|
627
|
+
|| isScrollBottomInput(data);
|
|
628
|
+
if (jumpedBottom) {
|
|
629
|
+
hideScrollButton(tui);
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
const nextVisible = movedUp ? true : scrollButtonVisible;
|
|
537
633
|
if (nextVisible !== scrollButtonVisible) {
|
|
538
634
|
scrollButtonVisible = nextVisible;
|
|
539
635
|
tui.requestRender?.();
|
|
@@ -692,8 +788,7 @@ function jumpToBottomWithoutSubmit(tui: any): boolean {
|
|
|
692
788
|
} finally {
|
|
693
789
|
tui.focusedComponent = focused;
|
|
694
790
|
}
|
|
695
|
-
|
|
696
|
-
tui.requestRender?.();
|
|
791
|
+
hideScrollButton(tui);
|
|
697
792
|
return true;
|
|
698
793
|
}
|
|
699
794
|
|
|
@@ -715,7 +810,11 @@ function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
715
810
|
|
|
716
811
|
function renderScrollButton(width: number, theme: any): string[] {
|
|
717
812
|
if (!scrollButtonVisible || !isFixedEditorTui(toolMouseTui)) return [];
|
|
718
|
-
const
|
|
813
|
+
const shortcut = formatShortcut(SCROLL_BOTTOM_SHORTCUT);
|
|
814
|
+
const messageText = pendingScrollMessages > 0
|
|
815
|
+
? `${pendingScrollMessages} new message${pendingScrollMessages === 1 ? "" : "s"}`
|
|
816
|
+
: "Back to bottom";
|
|
817
|
+
const label = theme.fg("accent", `[ ↓ ${messageText} · ${shortcut} · click ]`);
|
|
719
818
|
const leftPad = Math.max(0, Math.floor((width - visibleWidth(label)) / 2));
|
|
720
819
|
return [`${" ".repeat(leftPad)}${truncateToWidth(label, width, "…")}`];
|
|
721
820
|
}
|
|
@@ -737,6 +836,7 @@ function patchToolMouseInputCapture(tui: any): void {
|
|
|
737
836
|
const data = args[0];
|
|
738
837
|
if (typeof data === "string") {
|
|
739
838
|
updateScrollButtonFromInput(this, data);
|
|
839
|
+
if (isFixedEditorTui(this) && isScrollBottomInput(data) && jumpToBottomWithoutSubmit(this)) return;
|
|
740
840
|
const packets = parseSgrMousePackets(data);
|
|
741
841
|
if (packets) {
|
|
742
842
|
for (const packet of packets) {
|
|
@@ -745,7 +845,9 @@ function patchToolMouseInputCapture(tui: any): void {
|
|
|
745
845
|
}
|
|
746
846
|
}
|
|
747
847
|
}
|
|
748
|
-
|
|
848
|
+
const result = Reflect.apply(originalHandle, this, args);
|
|
849
|
+
if (typeof data === "string") scheduleScrollButtonSync(this, data);
|
|
850
|
+
return result;
|
|
749
851
|
};
|
|
750
852
|
|
|
751
853
|
try {
|
|
@@ -774,8 +876,14 @@ function restoreToolMouseInputCapture(): void {
|
|
|
774
876
|
function handleToolMouseInput(data: string): { consume: true } | undefined {
|
|
775
877
|
if (!toolMouseTui) return undefined;
|
|
776
878
|
updateScrollButtonFromInput(toolMouseTui, data);
|
|
879
|
+
if (isFixedEditorTui(toolMouseTui) && isScrollBottomInput(data) && jumpToBottomWithoutSubmit(toolMouseTui)) {
|
|
880
|
+
return { consume: true };
|
|
881
|
+
}
|
|
777
882
|
const packets = parseSgrMousePackets(data);
|
|
778
|
-
if (!packets)
|
|
883
|
+
if (!packets) {
|
|
884
|
+
scheduleScrollButtonSync(toolMouseTui, data);
|
|
885
|
+
return undefined;
|
|
886
|
+
}
|
|
779
887
|
|
|
780
888
|
let consumed = false;
|
|
781
889
|
for (const packet of packets) {
|
|
@@ -787,6 +895,7 @@ function handleToolMouseInput(data: string): { consume: true } | undefined {
|
|
|
787
895
|
|
|
788
896
|
// Let scrolling, motion, release, and clicks outside tool results reach the
|
|
789
897
|
// normal TUI input chain (including other extensions such as pi-zentui).
|
|
898
|
+
scheduleScrollButtonSync(toolMouseTui, data);
|
|
790
899
|
return consumed ? { consume: true } : undefined;
|
|
791
900
|
}
|
|
792
901
|
|
|
@@ -806,6 +915,9 @@ function teardownToolMouseInteraction(): void {
|
|
|
806
915
|
restoreToolMouseInputCapture();
|
|
807
916
|
scrollButtonVisible = false;
|
|
808
917
|
scrollButtonWidget = null;
|
|
918
|
+
pendingScrollMessages = 0;
|
|
919
|
+
assistantMessageActive = false;
|
|
920
|
+
scrollButtonSyncScheduled = false;
|
|
809
921
|
toolMouseTui = null;
|
|
810
922
|
toolMouseUi = null;
|
|
811
923
|
}
|
|
@@ -979,7 +1091,7 @@ function renderFileDiffPreview(_toolName: string, _args: any, theme: any, contex
|
|
|
979
1091
|
}
|
|
980
1092
|
|
|
981
1093
|
function statusText() {
|
|
982
|
-
return config.enabled ?
|
|
1094
|
+
return config.enabled ? "CC on" : "CC off";
|
|
983
1095
|
}
|
|
984
1096
|
|
|
985
1097
|
function updateStatus(ctx: any) {
|
|
@@ -1089,14 +1201,7 @@ function createCcstyleTool(originalTool: any): any {
|
|
|
1089
1201
|
const expanded = isToolExpanded(options, context);
|
|
1090
1202
|
|
|
1091
1203
|
const text = textFromResult(result);
|
|
1092
|
-
|
|
1093
|
-
if (config.mode === "minimal" && !expanded) {
|
|
1094
|
-
rendered = "";
|
|
1095
|
-
} else if (!expanded) {
|
|
1096
|
-
rendered = text ? oneLine(text, 96) : "Done";
|
|
1097
|
-
} else {
|
|
1098
|
-
rendered = text;
|
|
1099
|
-
}
|
|
1204
|
+
const rendered = !expanded ? (text ? oneLine(text, 96) : "Done") : text;
|
|
1100
1205
|
|
|
1101
1206
|
const hint = !expanded && hasExpandableResult(text) ? expandHint(theme) : "";
|
|
1102
1207
|
if (expanded) return renderExpandedToolResult(rendered, theme, isError);
|
|
@@ -1369,6 +1474,18 @@ function registerWrappedTool(pi: ExtensionAPI, name: keyof ReturnType<typeof cre
|
|
|
1369
1474
|
});
|
|
1370
1475
|
}
|
|
1371
1476
|
|
|
1477
|
+
function notePendingScrollMessage(role: unknown): void {
|
|
1478
|
+
if (!toolMouseTui || !isFixedEditorTui(toolMouseTui) || !scrollButtonVisible) return;
|
|
1479
|
+
if (role === "assistant") {
|
|
1480
|
+
if (assistantMessageActive) return;
|
|
1481
|
+
assistantMessageActive = true;
|
|
1482
|
+
} else if (role !== "toolResult") {
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
pendingScrollMessages += 1;
|
|
1486
|
+
toolMouseTui.requestRender?.();
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1372
1489
|
export default function (pi: ExtensionAPI) {
|
|
1373
1490
|
installGlobalToolRendering();
|
|
1374
1491
|
deactivateLegacyCompactionRendering();
|
|
@@ -1379,35 +1496,27 @@ export default function (pi: ExtensionAPI) {
|
|
|
1379
1496
|
const topLevel = [
|
|
1380
1497
|
{ value: "on", label: "on", description: "Enable Claude Code style" },
|
|
1381
1498
|
{ value: "off", label: "off", description: "Disable Claude Code style" },
|
|
1382
|
-
{ value: "status", label: "status", description: "Show current
|
|
1383
|
-
{ value: "minimal", label: "minimal", description: "Hide most tool output in collapsed view" },
|
|
1384
|
-
{ value: "compact", label: "compact", description: "Show short summaries in collapsed view" },
|
|
1499
|
+
{ value: "status", label: "status", description: "Show current state" },
|
|
1385
1500
|
];
|
|
1386
1501
|
return topLevel.filter((item) => item.value.startsWith(prefix));
|
|
1387
1502
|
},
|
|
1388
1503
|
handler: async (args, ctx) => {
|
|
1389
1504
|
const arg = args.trim().toLowerCase();
|
|
1390
|
-
if (arg === "on"
|
|
1391
|
-
else if (arg === "off"
|
|
1392
|
-
else if (arg === "
|
|
1393
|
-
config.enabled = true;
|
|
1394
|
-
config.mode = "minimal";
|
|
1395
|
-
} else if (arg === "compact") {
|
|
1396
|
-
config.enabled = true;
|
|
1397
|
-
config.mode = "compact";
|
|
1398
|
-
} else if (arg === "status") {
|
|
1505
|
+
if (arg === "on") config.enabled = true;
|
|
1506
|
+
else if (arg === "off") config.enabled = false;
|
|
1507
|
+
else if (arg === "status") {
|
|
1399
1508
|
updateStatus(ctx);
|
|
1400
|
-
ctx.ui.notify(
|
|
1401
|
-
`Claude Code style: ${config.enabled ? "on" : "off"}, mode=${config.mode}`,
|
|
1402
|
-
"info",
|
|
1403
|
-
);
|
|
1509
|
+
ctx.ui.notify(`Claude Code style: ${config.enabled ? "on" : "off"}`, "info");
|
|
1404
1510
|
return;
|
|
1405
|
-
} else {
|
|
1511
|
+
} else if (!arg) {
|
|
1406
1512
|
config.enabled = !config.enabled;
|
|
1513
|
+
} else {
|
|
1514
|
+
ctx.ui.notify("Usage: /ccstyle [on|off|status]", "warning");
|
|
1515
|
+
return;
|
|
1407
1516
|
}
|
|
1408
1517
|
saveConfig();
|
|
1409
1518
|
updateStatus(ctx);
|
|
1410
|
-
ctx.ui.notify(`Claude Code style: ${config.enabled ? "on" : "off"}
|
|
1519
|
+
ctx.ui.notify(`Claude Code style: ${config.enabled ? "on" : "off"}`, "info");
|
|
1411
1520
|
},
|
|
1412
1521
|
});
|
|
1413
1522
|
|
|
@@ -1423,10 +1532,24 @@ export default function (pi: ExtensionAPI) {
|
|
|
1423
1532
|
|
|
1424
1533
|
pi.on("session_start", async (_event, ctx) => {
|
|
1425
1534
|
diffPreviewByCall.clear();
|
|
1535
|
+
pendingScrollMessages = 0;
|
|
1536
|
+
assistantMessageActive = false;
|
|
1426
1537
|
updateStatus(ctx);
|
|
1427
1538
|
installToolMouseInteraction(ctx);
|
|
1428
1539
|
});
|
|
1429
1540
|
|
|
1541
|
+
pi.on("message_start", async (event) => {
|
|
1542
|
+
notePendingScrollMessage(event?.message?.role);
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
pi.on("message_update", async (event) => {
|
|
1546
|
+
if (event?.message?.role === "assistant") notePendingScrollMessage("assistant");
|
|
1547
|
+
});
|
|
1548
|
+
|
|
1549
|
+
pi.on("message_end", async (event) => {
|
|
1550
|
+
if (event?.message?.role === "assistant") assistantMessageActive = false;
|
|
1551
|
+
});
|
|
1552
|
+
|
|
1430
1553
|
pi.on("session_shutdown", async () => {
|
|
1431
1554
|
teardownToolMouseInteraction();
|
|
1432
1555
|
deactivateGlobalToolRendering();
|
|
@@ -1440,7 +1563,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1440
1563
|
call: (args) => fileAction(args, "Read"),
|
|
1441
1564
|
result: (result, { expanded }) => {
|
|
1442
1565
|
const text = textFromResult(result);
|
|
1443
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1444
1566
|
if (!expanded) return `${countLines(text)} lines read`;
|
|
1445
1567
|
return text;
|
|
1446
1568
|
},
|
|
@@ -1450,7 +1572,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1450
1572
|
call: (args) => `Bash(${oneLine(args?.command, 86) || "..."})`,
|
|
1451
1573
|
result: (result, { expanded }) => {
|
|
1452
1574
|
const text = textFromResult(result).trim();
|
|
1453
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1454
1575
|
if (!expanded) return summarizeBash(text);
|
|
1455
1576
|
return text;
|
|
1456
1577
|
},
|
|
@@ -1462,7 +1583,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1462
1583
|
diffAfterResult: true,
|
|
1463
1584
|
result: (result, { expanded }, _theme, context) => {
|
|
1464
1585
|
const text = textFromResult(result).trim();
|
|
1465
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1466
1586
|
return summarizeDiffStats(context?.state?.ccstyleDiffPreview) ?? summarizeEdit(text);
|
|
1467
1587
|
},
|
|
1468
1588
|
});
|
|
@@ -1477,7 +1597,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1477
1597
|
diffAfterResult: true,
|
|
1478
1598
|
result: (result, { expanded }, _theme, context) => {
|
|
1479
1599
|
const text = textFromResult(result).trim();
|
|
1480
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1481
1600
|
return summarizeDiffStats(context?.state?.ccstyleDiffPreview) ?? (text ? oneLine(text, 96) : "Written");
|
|
1482
1601
|
},
|
|
1483
1602
|
});
|
|
@@ -1486,7 +1605,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1486
1605
|
call: (args) => `Find(${args?.pattern || "..."}${args?.path ? ` in ${shortenPath(args.path)}` : ""})`,
|
|
1487
1606
|
result: (result, { expanded }) => {
|
|
1488
1607
|
const text = textFromResult(result).trim();
|
|
1489
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1490
1608
|
if (!expanded) return `${countLines(text)} files`;
|
|
1491
1609
|
return text;
|
|
1492
1610
|
},
|
|
@@ -1496,7 +1614,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1496
1614
|
call: (args) => `Grep(${args?.pattern ? `/${oneLine(args.pattern, 48)}/` : "..."})`,
|
|
1497
1615
|
result: (result, { expanded }) => {
|
|
1498
1616
|
const text = textFromResult(result).trim();
|
|
1499
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1500
1617
|
if (!expanded) {
|
|
1501
1618
|
const matches = countLines(text);
|
|
1502
1619
|
const files = parsePathCount(text);
|
|
@@ -1510,7 +1627,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1510
1627
|
call: (args) => `List(${shortenPath(args?.path || ".")})`,
|
|
1511
1628
|
result: (result, { expanded }) => {
|
|
1512
1629
|
const text = textFromResult(result).trim();
|
|
1513
|
-
if (config.mode === "minimal" && !expanded) return "";
|
|
1514
1630
|
if (!expanded) return `${countLines(text)} entries`;
|
|
1515
1631
|
return text;
|
|
1516
1632
|
},
|