pi-cc-extensions 1.0.2 → 1.0.4
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 +35 -35
- package/README.md +3 -3
- package/extensions/config/config.ts +5 -0
- package/extensions/config/panel.ts +22 -0
- package/extensions/feature/context.ts +339 -149
- package/extensions/feature/reference/index.ts +2 -0
- package/extensions/feature/reference/subagent.ts +2 -0
- package/extensions/feature/shell/footer.ts +1 -0
- package/extensions/feature/shell/token-rate.ts +15 -3
- package/extensions/feature/shell/working-message.ts +0 -19
- package/extensions/renderer/compact-mode.ts +152 -49
- package/extensions/renderer/index.ts +3 -0
- package/extensions/renderer/mouse/interaction.ts +53 -26
- package/extensions/renderer/tool/diff/write-execution.ts +2 -2
- package/package.json +1 -1
|
@@ -191,7 +191,7 @@ const FULLSCREEN_FOCUS_OUT = "\x1b[O";
|
|
|
191
191
|
|
|
192
192
|
let pendingCollapsePress: {
|
|
193
193
|
card: any;
|
|
194
|
-
/**
|
|
194
|
+
/** 命中的最内层组件:卡内工具行命中时用于触发官方 click 抑制窗口。 */
|
|
195
195
|
component: any;
|
|
196
196
|
col: number;
|
|
197
197
|
row: number;
|
|
@@ -240,22 +240,17 @@ function rememberCollapsePress(card: any, component: any, packet: SgrMousePacket
|
|
|
240
240
|
|
|
241
241
|
/**
|
|
242
242
|
* 松手结算:只有"按下与松开在同一格"的完整单击才收起,拖动选择文本时保持展开。
|
|
243
|
-
*
|
|
244
|
-
*
|
|
243
|
+
* 官方卡与自有卡统一在这里结算:fullscreen 下结算成功的 release 被 consume,
|
|
244
|
+
* 官方不会再合成 click(合成 click 要求按下/松开坐标完全一致,手抖一格就不发,
|
|
245
|
+
* 还会把刚收起的卡 toggle 回去、或误触卡内其他 MouseRegion)。
|
|
245
246
|
*/
|
|
246
|
-
function resolveCollapsePress(
|
|
247
|
-
tui: any,
|
|
248
|
-
packet: SgrMousePacket,
|
|
249
|
-
options: { skipOfficialCards: boolean },
|
|
250
|
-
): any {
|
|
247
|
+
function resolveCollapsePress(tui: any, packet: SgrMousePacket): any {
|
|
251
248
|
const press = pendingCollapsePress;
|
|
252
249
|
pendingCollapsePress = null;
|
|
253
250
|
if (!press || packet.final !== "m") return undefined;
|
|
254
251
|
if (Math.abs(packet.col - press.col) > COLLAPSE_CLICK_MOVE_TOLERANCE) return undefined;
|
|
255
252
|
if (Math.abs(packet.row - press.row) > COLLAPSE_CLICK_MOVE_TOLERANCE) return undefined;
|
|
256
253
|
if (Date.now() - press.at > COLLAPSE_CLICK_MAX_MS) return undefined;
|
|
257
|
-
if (options.skipOfficialCards && press.component instanceof ToolExecutionComponent)
|
|
258
|
-
return undefined;
|
|
259
254
|
const card = press.card;
|
|
260
255
|
if (
|
|
261
256
|
(card instanceof ToolGroupComponent || isCompactAssistantComponent(card)) &&
|
|
@@ -265,7 +260,7 @@ function resolveCollapsePress(
|
|
|
265
260
|
suppressOfficialCardClickUntil = Date.now() + SUPPRESS_OFFICIAL_CARD_CLICK_MS;
|
|
266
261
|
}
|
|
267
262
|
collapseExpandedCard(tui, card);
|
|
268
|
-
//
|
|
263
|
+
// 返回收起的卡:fullscreen 调用方据此吞掉这次 release 并清官方按下/选区状态。
|
|
269
264
|
return card;
|
|
270
265
|
}
|
|
271
266
|
|
|
@@ -398,7 +393,7 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
398
393
|
if (!target) return false;
|
|
399
394
|
const component = target.component;
|
|
400
395
|
// compact 展开面板内命中时 owner 是面板:收起对象与记账对象都归面板,
|
|
401
|
-
//
|
|
396
|
+
// 面板内工具行命中时 release 统一由扩展结算。
|
|
402
397
|
const card = target.group ?? target.owner ?? component;
|
|
403
398
|
const pressComponent = target.owner ?? component;
|
|
404
399
|
// 回到底部按钮:按组件引用命中,不依赖渲染行缓存。
|
|
@@ -474,8 +469,8 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
474
469
|
});
|
|
475
470
|
}
|
|
476
471
|
}
|
|
477
|
-
// 其余放行官方:选区、OSC8
|
|
478
|
-
//
|
|
472
|
+
// 其余放行官方:选区、OSC8 链接与官方按下登记都交给 renderer。
|
|
473
|
+
// 完整单击的收起统一在松手结算(release 被 consume,官方不会再合成 click)。
|
|
479
474
|
rememberCollapsePress(card, pressComponent, packet);
|
|
480
475
|
return false;
|
|
481
476
|
}
|
|
@@ -584,6 +579,27 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
|
|
|
584
579
|
applyFullscreenHover(tui, target);
|
|
585
580
|
}
|
|
586
581
|
|
|
582
|
+
/**
|
|
583
|
+
* 鼠标包(1-based 屏幕坐标)是否落在某个已渲染 overlay 的矩形内。
|
|
584
|
+
* renderedOverlayLayouts 与官方 dispatchMouseToOverlay 同源:只含上一帧画出的可见 overlay。
|
|
585
|
+
*/
|
|
586
|
+
function packetInsideOverlay(tui: any, packet: SgrMousePacket): boolean {
|
|
587
|
+
const layouts = tui?.renderedOverlayLayouts;
|
|
588
|
+
if (!Array.isArray(layouts)) return false;
|
|
589
|
+
const x = packet.col - 1;
|
|
590
|
+
const y = packet.row - 1;
|
|
591
|
+
for (const layout of layouts) {
|
|
592
|
+
if (
|
|
593
|
+
x >= layout.col &&
|
|
594
|
+
x < layout.col + layout.width &&
|
|
595
|
+
y >= layout.row &&
|
|
596
|
+
y < layout.row + layout.height
|
|
597
|
+
)
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
|
|
587
603
|
/**
|
|
588
604
|
* 实例级包装 TuiAltScreen.handleViewportInput(惰性 Proxy 安全):
|
|
589
605
|
* 原型方法取 original(绕开 proxy 函数包装),实例 own property 装 wrapper
|
|
@@ -602,24 +618,32 @@ function patchFullscreenViewportInput(tui: any): void {
|
|
|
602
618
|
// 官方 viewport 会消费键盘,扩展监听器无法补偿,必须在这里调度。
|
|
603
619
|
scheduleScrollButtonSync(tui, data);
|
|
604
620
|
const packets = parseSgrMousePackets(data);
|
|
605
|
-
//
|
|
606
|
-
//
|
|
607
|
-
|
|
608
|
-
|
|
621
|
+
// overlay(文本预览/context 弹框,都是真 overlay)可见时:落在
|
|
622
|
+
// overlay 矩形内的包经 packetInsideOverlay 放行官方
|
|
623
|
+
// dispatchMouseToOverlay → overlay.handleMouse;overlay 外的包仍
|
|
624
|
+
// 走扩展收起/展开/hover。两条路径各管各的。
|
|
625
|
+
if (packets) {
|
|
626
|
+
// overlay 可见时:落在 overlay 矩形内的包全部放行官方(文本预览的
|
|
627
|
+
// [esc] 点击/滚轮、官方搜索框等),扩展不展开/收起/hover。
|
|
628
|
+
const overlayPackets = tui.hasOverlay?.()
|
|
629
|
+
? packets.filter((packet) => packetInsideOverlay(tui, packet))
|
|
630
|
+
: undefined;
|
|
631
|
+
const insideOverlay = (packet: SgrMousePacket) => overlayPackets?.includes(packet) === true;
|
|
609
632
|
for (const packet of packets) {
|
|
633
|
+
if (insideOverlay(packet)) continue;
|
|
610
634
|
if (isSgrLeftRelease(packet)) {
|
|
611
|
-
//
|
|
612
|
-
//
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
) {
|
|
635
|
+
// 结算单击收起:成功时吞掉 release,官方不会再对同一次点击合成
|
|
636
|
+
// click(官方 click 要求按下/松开坐标严格一致,还会把刚收起的卡
|
|
637
|
+
// toggle 回去,或误触卡内其他 MouseRegion 区)。
|
|
638
|
+
if (resolveCollapsePress(tui, packet) !== undefined) {
|
|
639
|
+
// 收起会重排布局:官方还留着按下时登记的 press 目标与选区锚点,
|
|
640
|
+
// 发 FOCUS_OUT 一次清干净,避免旧坐标结算出误选/误发 click。
|
|
618
641
|
try {
|
|
619
642
|
Reflect.apply(original, this, [FULLSCREEN_FOCUS_OUT]);
|
|
620
643
|
} catch {
|
|
621
644
|
/* 老版本没有选区状态 */
|
|
622
645
|
}
|
|
646
|
+
return { consume: true };
|
|
623
647
|
}
|
|
624
648
|
} else if (!isSgrLeftPress(packet) && !isSgrIdleMotion(packet))
|
|
625
649
|
clearPendingCollapsePressOnMove(packet);
|
|
@@ -965,12 +989,15 @@ function handleToolMouseInput(data: string): { consume: true } | undefined {
|
|
|
965
989
|
scheduleScrollButtonSync(getToolMouseTui(), data);
|
|
966
990
|
return undefined;
|
|
967
991
|
}
|
|
992
|
+
// 文本预览活动时,点击交给预览自己的 handleInput(esc/copy/滚动条),
|
|
993
|
+
// 不被残留的工具 region 吞掉;预览关闭后恢复。
|
|
994
|
+
if (hasActiveTextPreview()) return undefined;
|
|
968
995
|
|
|
969
996
|
let consumed = false;
|
|
970
997
|
for (const packet of packets) {
|
|
971
998
|
updateToolSummaryHover(getToolMouseTui(), packet);
|
|
972
999
|
if (isSgrLeftRelease(packet)) {
|
|
973
|
-
resolveCollapsePress(getToolMouseTui(), packet
|
|
1000
|
+
resolveCollapsePress(getToolMouseTui(), packet);
|
|
974
1001
|
continue;
|
|
975
1002
|
}
|
|
976
1003
|
if (!isSgrLeftPress(packet)) {
|
|
@@ -94,13 +94,13 @@ export async function executeWriteWithMetadata(
|
|
|
94
94
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
95
95
|
throwIfAborted();
|
|
96
96
|
await writeFile(absolutePath, params.content, "utf8");
|
|
97
|
-
|
|
97
|
+
// The file is already changed. A later abort must not report failure.
|
|
98
98
|
store.set(toolCallId, metadata);
|
|
99
99
|
return {
|
|
100
100
|
content: [
|
|
101
101
|
{
|
|
102
102
|
type: "text",
|
|
103
|
-
text: `Successfully wrote ${params.content
|
|
103
|
+
text: `Successfully wrote ${Buffer.byteLength(params.content, "utf8")} bytes to ${params.path}`,
|
|
104
104
|
},
|
|
105
105
|
],
|
|
106
106
|
details: undefined,
|