pi-cc-extensions 0.8.0 → 0.8.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.md +7 -0
- package/assets/readme/welcome.webp +0 -0
- package/extensions/claude-code-style.ts +28 -27
- package/extensions/compact-style.ts +19 -12
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
## 界面预览
|
|
19
19
|
|
|
20
20
|
<table>
|
|
21
|
+
<tr>
|
|
22
|
+
<td colspan="2" align="center">
|
|
23
|
+
<img src="./assets/readme/welcome.webp" width="100%" alt="Pi 启动后的欢迎界面">
|
|
24
|
+
<br>
|
|
25
|
+
<sub><b>欢迎界面</b><br> @ <code>npm:pi-startup-header</code> 与 <code>npm:pi-zentui</code></sub>
|
|
26
|
+
</td>
|
|
27
|
+
</tr>
|
|
21
28
|
<tr>
|
|
22
29
|
<td width="50%" align="center">
|
|
23
30
|
<img src="./assets/readme/fixed-editor-navigation.webp" width="100%" alt="Pi fixed-editor 中的工具结果、回到底部按钮与 Ctrl+End 快捷键">
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import {
|
|
3
|
+
DynamicBorder,
|
|
3
4
|
keyHint,
|
|
4
|
-
getSettingsListTheme,
|
|
5
5
|
ToolExecutionComponent,
|
|
6
6
|
} from "@earendil-works/pi-coding-agent";
|
|
7
7
|
import {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
type CompactStyleMode,
|
|
11
11
|
} from "./compact-style.ts";
|
|
12
12
|
import { sanitizeToolResultText } from "./tool-result-sanitize.ts";
|
|
13
|
-
import { Container,
|
|
13
|
+
import { Container, SelectList, Text, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
14
14
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { join } from "node:path";
|
|
@@ -254,7 +254,7 @@ export class ExpandedToolResultText {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
function renderCollapsedToolResult(body: string, collapsedHint = ""): string {
|
|
257
|
-
return
|
|
257
|
+
return `\n ⎿ ${body}${collapsedHint}`;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
function renderExpandedToolResult(
|
|
@@ -958,37 +958,38 @@ async function showCcstylePanel(ctx: any, compactStyle: CompactStyleHooks): Prom
|
|
|
958
958
|
return;
|
|
959
959
|
}
|
|
960
960
|
|
|
961
|
-
|
|
961
|
+
const modes: Array<{ value: CompactStyleMode; label: string; description: string }> = [
|
|
962
|
+
{ value: "on", label: "on", description: "Claude Code style" },
|
|
963
|
+
{ value: "off", label: "off", description: "Pi native output" },
|
|
964
|
+
{ value: "compact", label: "compact", description: "Compact transcript" },
|
|
965
|
+
];
|
|
966
|
+
const selectedMode = await (ctx.ui.custom((tui: any, theme: any, _keybindings: any, done: (value?: CompactStyleMode) => void) => {
|
|
962
967
|
const container = new Container();
|
|
963
|
-
container.addChild(new
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
tui.requestRender();
|
|
979
|
-
},
|
|
980
|
-
() => done(),
|
|
981
|
-
);
|
|
982
|
-
container.addChild(settingsList);
|
|
968
|
+
container.addChild(new DynamicBorder((text: string) => theme.fg("accent", text)));
|
|
969
|
+
container.addChild(new Text(theme.fg("accent", theme.bold("Claude Code Style")), 1, 0));
|
|
970
|
+
const selectList = new SelectList(modes, modes.length, {
|
|
971
|
+
selectedPrefix: (text: string) => theme.fg("accent", text),
|
|
972
|
+
selectedText: (text: string) => theme.fg("accent", text),
|
|
973
|
+
description: (text: string) => theme.fg("muted", text),
|
|
974
|
+
scrollInfo: (text: string) => theme.fg("dim", text),
|
|
975
|
+
noMatch: (text: string) => theme.fg("warning", text),
|
|
976
|
+
});
|
|
977
|
+
selectList.setSelectedIndex(modes.findIndex((item) => item.value === config.mode));
|
|
978
|
+
selectList.onSelect = (item: { value: string }) => done(item.value as CompactStyleMode);
|
|
979
|
+
selectList.onCancel = () => done();
|
|
980
|
+
container.addChild(selectList);
|
|
981
|
+
container.addChild(new Text(theme.fg("dim", "↑↓ navigate · enter select · esc cancel"), 1, 0));
|
|
982
|
+
container.addChild(new DynamicBorder((text: string) => theme.fg("accent", text)));
|
|
983
983
|
return {
|
|
984
984
|
render: (width: number) => container.render(width),
|
|
985
985
|
invalidate: () => container.invalidate(),
|
|
986
986
|
handleInput(data: string) {
|
|
987
|
-
|
|
987
|
+
selectList.handleInput(data);
|
|
988
988
|
tui.requestRender();
|
|
989
989
|
},
|
|
990
990
|
};
|
|
991
|
-
});
|
|
991
|
+
}) as Promise<CompactStyleMode | undefined>);
|
|
992
|
+
if (selectedMode) applyStyleMode(selectedMode, ctx, compactStyle);
|
|
992
993
|
}
|
|
993
994
|
|
|
994
995
|
function renderDefault(tool: any, slot: "renderCall" | "renderResult", args: any[], fallback = "") {
|
|
@@ -1171,7 +1172,7 @@ function shouldUseSelfShell(component: any, patch: GlobalToolRenderPatch): boole
|
|
|
1171
1172
|
const definition = component.toolDefinition ?? component.builtInToolDefinition;
|
|
1172
1173
|
const toolName = String(component.toolName || definition?.name || "");
|
|
1173
1174
|
const useSelfShell =
|
|
1174
|
-
patch.
|
|
1175
|
+
patch.mode() !== "off" &&
|
|
1175
1176
|
SUBAGENT_TOOL_NAMES.has(toolName) &&
|
|
1176
1177
|
definition != null &&
|
|
1177
1178
|
definition.renderShell === undefined;
|
|
@@ -104,7 +104,6 @@ type RuntimeState = {
|
|
|
104
104
|
hiddenToolIds: Set<string>;
|
|
105
105
|
runningToolIds: Set<string>;
|
|
106
106
|
agentActive: boolean;
|
|
107
|
-
blinkOn: boolean;
|
|
108
107
|
blinkTimer?: ReturnType<typeof setInterval>;
|
|
109
108
|
runStats: RunStats;
|
|
110
109
|
toolComponents: Set<any>;
|
|
@@ -123,8 +122,11 @@ const MIN_PREVIEW_WIDTH = 20;
|
|
|
123
122
|
const MAX_PREVIEW_WIDTH = 104;
|
|
124
123
|
// Leave room for pi's row gutter/padding so compact lines never wrap.
|
|
125
124
|
const PREVIEW_MARGIN = 6;
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
// Keep the running marker in sync with Claude mode's braille loader.
|
|
126
|
+
const BLINK_INTERVAL_MS = 80;
|
|
127
|
+
const CLAUDE_LOADING_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
128
|
+
const CLAUDE_LOADING_TOOLS = new Set(["read", "bash", "edit", "write", "find", "grep", "ls"]);
|
|
129
|
+
// Status marker is two cells wide ("✓ ", "✗ ", or the Claude-style running frame).
|
|
128
130
|
const MARKER_WIDTH = 2;
|
|
129
131
|
const STATE_KEY = Symbol.for("pi.ccstyle.compact-style.state");
|
|
130
132
|
const TOOL_PATCH_KEY = Symbol.for("pi.ccstyle.compact-style.tool-patch");
|
|
@@ -153,7 +155,6 @@ function getState(): RuntimeState {
|
|
|
153
155
|
hiddenToolIds: new Set(),
|
|
154
156
|
runningToolIds: new Set(),
|
|
155
157
|
agentActive: false,
|
|
156
|
-
blinkOn: true,
|
|
157
158
|
runStats: newRunStats(),
|
|
158
159
|
toolComponents: new Set(),
|
|
159
160
|
assistantComponents: new Set(),
|
|
@@ -378,7 +379,6 @@ function ensureBlinkTimer() {
|
|
|
378
379
|
stopBlinkTimer();
|
|
379
380
|
return;
|
|
380
381
|
}
|
|
381
|
-
state.blinkOn = !state.blinkOn;
|
|
382
382
|
for (const id of state.runningToolIds) state.toolsById.get(id)?.invalidate?.();
|
|
383
383
|
}, BLINK_INTERVAL_MS);
|
|
384
384
|
state.blinkTimer.unref?.();
|
|
@@ -387,14 +387,21 @@ function ensureBlinkTimer() {
|
|
|
387
387
|
function stopBlinkTimer() {
|
|
388
388
|
if (state.blinkTimer) clearInterval(state.blinkTimer);
|
|
389
389
|
state.blinkTimer = undefined;
|
|
390
|
-
state.blinkOn = true;
|
|
391
390
|
}
|
|
392
391
|
|
|
393
|
-
function statusMarker(
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
392
|
+
function statusMarker(
|
|
393
|
+
theme: Theme,
|
|
394
|
+
name: string,
|
|
395
|
+
opts: { running?: boolean; isError?: boolean; hasResult?: boolean },
|
|
396
|
+
): string {
|
|
397
|
+
if (opts.isError) return theme.fg("error", "✗ ");
|
|
398
|
+
if (opts.running) {
|
|
399
|
+
if (!CLAUDE_LOADING_TOOLS.has(name)) return theme.fg("accent", "● ");
|
|
400
|
+
const frame = CLAUDE_LOADING_FRAMES[Math.floor(Date.now() / BLINK_INTERVAL_MS) % CLAUDE_LOADING_FRAMES.length] ?? "⠋";
|
|
401
|
+
return theme.fg("accent", `${frame} `);
|
|
402
|
+
}
|
|
403
|
+
if (opts.hasResult) return theme.fg("success", "✓ ");
|
|
404
|
+
return theme.fg("dim", "● ");
|
|
398
405
|
}
|
|
399
406
|
|
|
400
407
|
function textSignalHasVisibleContent(assistantMessageEvent: any): boolean {
|
|
@@ -611,7 +618,7 @@ function compactToolLine(
|
|
|
611
618
|
const inner = [info.result ? oneLine(info.result) : "", durationText].filter(Boolean).join(" · ");
|
|
612
619
|
const status = inner ? ` {${inner}}` : info.running ? " {running}" : "";
|
|
613
620
|
const details = `${info.preview}${status}`;
|
|
614
|
-
const marker = statusMarker(theme, {
|
|
621
|
+
const marker = statusMarker(theme, name, {
|
|
615
622
|
running: info.running,
|
|
616
623
|
isError: info.isError,
|
|
617
624
|
hasResult: result != null || !!info.result,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cc-extensions",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "A Pi productivity suite with Claude Code-style UI, context inspection, and agent/session references",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -27,9 +27,10 @@
|
|
|
27
27
|
"./extensions/claude-code-style.ts",
|
|
28
28
|
"./extensions/context.ts",
|
|
29
29
|
"./extensions/session-reference.ts",
|
|
30
|
-
"./extensions/agent-autocomplete.ts"
|
|
30
|
+
"./extensions/agent-autocomplete.ts",
|
|
31
|
+
"./extensions/compact-style.ts"
|
|
31
32
|
],
|
|
32
|
-
"image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/
|
|
33
|
+
"image": "https://raw.githubusercontent.com/minuque/pi-cc-extensions/main/assets/readme/welcome.webp"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
35
36
|
"test": "node --test tests/**/*.test.ts",
|