pi-extensions-tool-display 1.0.0 → 1.1.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/SKILL.md +28 -0
- package/package.json +5 -1
- package/src/config-modal.ts +9 -6
- package/src/index.ts +12 -11
- package/src/result-render-middleware.ts +6 -2
- package/src/tool-overrides.ts +5 -2
- package/tool-display-api-consumer.js +10 -4
package/SKILL.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configure-pi-extensions-tool-display
|
|
3
|
+
description: "配置与排查 Pi 工具展示宿主、内建/自定义工具 override、输出模式和 diff 视图。Use when changing pi-extensions-tool-display rendering."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 配置 pi-extensions-tool-display
|
|
7
|
+
|
|
8
|
+
## 诊断
|
|
9
|
+
|
|
10
|
+
读取实际 Pi agent 目录下的 `extensions/pi-tool-display/config.json`。注意目录名是 `pi-tool-display`,不是 npm 包名。以包内 `config.example.json` 和当前源码支持的字段为准。
|
|
11
|
+
|
|
12
|
+
确认没有同时加载另一份工具展示宿主;`pi-distill` 与 `pi-tool-supervisor` 已会加载这个共享宿主,通常无需重复安装。
|
|
13
|
+
|
|
14
|
+
## 修改
|
|
15
|
+
|
|
16
|
+
优先运行 `/config:tool-display`;`/tool-display`、`/pi-tool-display` 是兼容别名。按目标最小修改:
|
|
17
|
+
|
|
18
|
+
- `registerToolOverrides` 控制 `read/grep/find/ls/bash/edit/write` 的展示所有权;
|
|
19
|
+
- `customToolOverrides.<tool>` 使用 `enabled`、`kind`、`outputMode`;
|
|
20
|
+
- `readOutputMode`、`searchOutputMode`、`mcpOutputMode`、`bashOutputMode` 控制输出展示;
|
|
21
|
+
- `diffViewMode`、`diffIndicatorMode`、折叠行数和换行字段只影响 diff UI;
|
|
22
|
+
- `enabled: false` 关闭宿主展示。
|
|
23
|
+
|
|
24
|
+
不要把展示开关解释为禁用工具,也不要让多个宿主同时注册同一内建 override。
|
|
25
|
+
|
|
26
|
+
## 验证
|
|
27
|
+
|
|
28
|
+
分别调用一个受影响的内建或自定义工具,观察折叠、预览、diff 或输出模式。若消费者审计卡片未出现,先确认宿主只加载一次,再确认消费者 middleware 已注册;不能用配置文件可解析代替真实 UI 证据。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extensions-tool-display",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Pi tool display host and shared result-rendering protocol for extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"config.example.json",
|
|
16
16
|
"README.md",
|
|
17
17
|
"README.zh-CN.md",
|
|
18
|
+
"SKILL.md",
|
|
18
19
|
"tsconfig.json"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
@@ -53,6 +54,9 @@
|
|
|
53
54
|
"pi": {
|
|
54
55
|
"extensions": [
|
|
55
56
|
"./index.ts"
|
|
57
|
+
],
|
|
58
|
+
"skills": [
|
|
59
|
+
"./SKILL.md"
|
|
56
60
|
]
|
|
57
61
|
},
|
|
58
62
|
"devDependencies": {
|
package/src/config-modal.ts
CHANGED
|
@@ -104,7 +104,7 @@ export function buildInspectorSettings(
|
|
|
104
104
|
inspectorTitle: "Global Tool Display Switch",
|
|
105
105
|
inspectorSummary: [
|
|
106
106
|
"Enables or disables all pi-tool-display rendering and tool ownership behavior.",
|
|
107
|
-
"The /tool-display command remains available while disabled so the extension can be enabled again without editing Pi package settings.",
|
|
107
|
+
"The /config:tool-display command remains available while disabled so the extension can be enabled again without editing Pi package settings.",
|
|
108
108
|
],
|
|
109
109
|
inspectorOptions: [
|
|
110
110
|
"on — enable tool overrides and enhanced rendering",
|
|
@@ -500,7 +500,7 @@ export function handleToolDisplayArgs(args: string, ctx: ExtensionCommandContext
|
|
|
500
500
|
const candidate = normalized.slice("preset ".length).trim();
|
|
501
501
|
const preset = parseToolDisplayPreset(candidate);
|
|
502
502
|
if (!preset) {
|
|
503
|
-
ctx.ui.notify(`Unknown preset. Use: /tool-display preset ${PRESET_COMMAND_HINT}`, "warning");
|
|
503
|
+
ctx.ui.notify(`Unknown preset. Use: /config:tool-display preset ${PRESET_COMMAND_HINT}`, "warning");
|
|
504
504
|
return true;
|
|
505
505
|
}
|
|
506
506
|
|
|
@@ -509,7 +509,7 @@ export function handleToolDisplayArgs(args: string, ctx: ExtensionCommandContext
|
|
|
509
509
|
return true;
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
-
ctx.ui.notify(`Usage: /tool-display [show|reset|preset ${PRESET_COMMAND_HINT}]`, "warning");
|
|
512
|
+
ctx.ui.notify(`Usage: /config:tool-display [show|reset|preset ${PRESET_COMMAND_HINT}]`, "warning");
|
|
513
513
|
return true;
|
|
514
514
|
}
|
|
515
515
|
|
|
@@ -523,7 +523,7 @@ export async function runToolDisplayCommandHandler(
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
if (!ctx.hasUI) {
|
|
526
|
-
ctx.ui.notify("/tool-display requires interactive TUI mode.", "warning");
|
|
526
|
+
ctx.ui.notify("/config:tool-display requires interactive TUI mode.", "warning");
|
|
527
527
|
return;
|
|
528
528
|
}
|
|
529
529
|
|
|
@@ -531,10 +531,13 @@ export async function runToolDisplayCommandHandler(
|
|
|
531
531
|
}
|
|
532
532
|
|
|
533
533
|
export function registerToolDisplayCommand(pi: ExtensionAPI, controller: ToolDisplayConfigController): void {
|
|
534
|
-
|
|
534
|
+
const command = {
|
|
535
535
|
description: "Configure tool output rendering (OpenCode-style)",
|
|
536
536
|
handler: async (args, ctx) => {
|
|
537
537
|
await runToolDisplayCommandHandler(args, ctx, controller);
|
|
538
538
|
},
|
|
539
|
-
}
|
|
539
|
+
};
|
|
540
|
+
for (const name of ["config:tool-display", "tool-display", "pi-tool-display"] as const) {
|
|
541
|
+
pi.registerCommand(name, command);
|
|
542
|
+
}
|
|
540
543
|
}
|
package/src/index.ts
CHANGED
|
@@ -44,9 +44,9 @@ export function toolDisplayReloadRequired(
|
|
|
44
44
|
|
|
45
45
|
const initializedHosts = new WeakSet<ExtensionAPI>();
|
|
46
46
|
|
|
47
|
-
function hasRegisteredToolDisplayCommand(pi: ExtensionAPI): boolean {
|
|
47
|
+
function hasRegisteredToolDisplayCommand(pi: ExtensionAPI, name: string): boolean {
|
|
48
48
|
try {
|
|
49
|
-
return pi.getCommands().some((command) => command.name ===
|
|
49
|
+
return pi.getCommands().some((command) => command.name === name);
|
|
50
50
|
} catch {
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
@@ -119,15 +119,16 @@ export function ensureToolDisplayHost(
|
|
|
119
119
|
|
|
120
120
|
// Each Pi extension has its own registration map, while getCommands() sees
|
|
121
121
|
// the shared runtime. Check the latter so feature extensions do not expose
|
|
122
|
-
// duplicate
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
// duplicate management commands when they initialize this host separately.
|
|
123
|
+
const command = {
|
|
124
|
+
description: "Configure tool output rendering (OpenCode-style)",
|
|
125
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
126
|
+
const { runToolDisplayCommandHandler } = await import("./config-modal.js");
|
|
127
|
+
await runToolDisplayCommandHandler(args, ctx, { getConfig, setConfig, getCapabilities });
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
for (const name of ["config:tool-display", "tool-display", "pi-tool-display"] as const) {
|
|
131
|
+
if (!hasRegisteredToolDisplayCommand(pi, name)) pi.registerCommand(name, command);
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -66,10 +66,14 @@ export function registerResultRenderMiddleware(
|
|
|
66
66
|
const api = getApi();
|
|
67
67
|
if (typeof api?.registerResultRenderMiddleware === "function") {
|
|
68
68
|
api.registerResultRenderMiddleware(registration);
|
|
69
|
-
} else {
|
|
70
|
-
queueRegistration(registration);
|
|
71
69
|
}
|
|
72
70
|
|
|
71
|
+
// Keep the registration in the shared protocol queue even when a host is
|
|
72
|
+
// already available. The host can be replaced during /reload or when a new
|
|
73
|
+
// session creates a new ExtensionAPI instance; the new host must be able to
|
|
74
|
+
// rehydrate registrations that were attached to the previous API object.
|
|
75
|
+
queueRegistration(registration);
|
|
76
|
+
|
|
73
77
|
return () => {
|
|
74
78
|
getApi()?.unregisterResultRenderMiddleware?.(registration.id);
|
|
75
79
|
removeQueuedRegistration(registration.id);
|
package/src/tool-overrides.ts
CHANGED
|
@@ -1525,8 +1525,11 @@ function drainPendingResultRenderMiddlewares(api: ToolDisplayApi): void {
|
|
|
1525
1525
|
const pending = globalWithApi[TOOL_DISPLAY_PENDING_RESULT_MIDDLEWARES_KEY];
|
|
1526
1526
|
if (!Array.isArray(pending) || pending.length === 0) return;
|
|
1527
1527
|
|
|
1528
|
-
|
|
1529
|
-
|
|
1528
|
+
// This queue is the cross-host registry for external middleware, not a
|
|
1529
|
+
// one-shot bootstrap queue. Keep it populated so a replacement host during
|
|
1530
|
+
// /reload or a new session can rehydrate middleware registered on the old
|
|
1531
|
+
// API instance.
|
|
1532
|
+
for (const entry of pending) {
|
|
1530
1533
|
if (!entry?.id || !entry.toolName || typeof entry.middleware !== "function") continue;
|
|
1531
1534
|
api.registerResultRenderMiddleware(entry);
|
|
1532
1535
|
}
|
|
@@ -53,19 +53,25 @@ export function registerToolResultRenderMiddleware(toolName, middleware, options
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const id = options.id || `external-result-middleware-${++nextResultMiddlewareId}`;
|
|
56
|
+
const registration = { id, toolName, middleware };
|
|
56
57
|
const api = getToolDisplayApi();
|
|
57
58
|
if (typeof api?.registerResultRenderMiddleware === "function") {
|
|
58
|
-
|
|
59
|
+
const registeredId = api.registerResultRenderMiddleware(registration);
|
|
60
|
+
queueResultRenderMiddleware(registration);
|
|
61
|
+
return registeredId;
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
queueResultRenderMiddleware(registration);
|
|
65
|
+
return id;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function queueResultRenderMiddleware(registration) {
|
|
61
69
|
const existing = globalThis[TOOL_DISPLAY_PENDING_RESULT_MIDDLEWARES_KEY];
|
|
62
70
|
const queue = Array.isArray(existing) ? existing : [];
|
|
63
|
-
const
|
|
64
|
-
const index = queue.findIndex((entry) => entry?.id === id);
|
|
71
|
+
const index = queue.findIndex((entry) => entry?.id === registration.id);
|
|
65
72
|
if (index >= 0) queue[index] = registration;
|
|
66
73
|
else queue.push(registration);
|
|
67
74
|
globalThis[TOOL_DISPLAY_PENDING_RESULT_MIDDLEWARES_KEY] = queue;
|
|
68
|
-
return id;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
export function unregisterToolResultRenderMiddleware(id) {
|