pi-dynamic-help 0.2.0 → 0.2.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/CHANGELOG.md +17 -0
- package/package.json +1 -1
- package/src/extension.ts +16 -5
- package/src/render/markdown.ts +0 -17
- package/src/resources/index.ts +8 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### 安全修复
|
|
6
|
+
- **MCP 信息泄漏**: 移除 `/help` 输出中暴露的完整 MCP 服务器 URL 和命令路径,改为显示 "HTTP 服务器" 或 "stdio 服务器"
|
|
7
|
+
- **内置命令重复**: 修复 `/model`、`/help` 等内置命令在列表中显示两次的问题,添加去重逻辑
|
|
8
|
+
- **保存失败提示**: `pin`/`unpin`/`refresh` 命令现在检查保存结果,失败时回滚状态并显示错误信息,不再谎报成功
|
|
9
|
+
|
|
10
|
+
### 测试增强
|
|
11
|
+
- 添加 MCP URL 消毒测试
|
|
12
|
+
- 添加内置命令去重测试
|
|
13
|
+
- 添加 pin/unpin 保存失败回滚测试
|
|
14
|
+
|
|
15
|
+
## 0.2.1
|
|
16
|
+
|
|
17
|
+
- 移除 `/help` 输出中硬编码的 MCP 用法示例(包含特定服务器名 chrome-devtools/screenshot)
|
|
18
|
+
- 移除 `/help` 输出中硬编码的"示例"工作流部分(需求分析/系统设计//goal//brainstorm)
|
|
19
|
+
- `/help` 现在只显示动态生成的内容,不再包含可能不一致的硬编码示例
|
|
3
20
|
## 0.2.0
|
|
4
21
|
|
|
5
22
|
- Refactor the extension into maintainable modules for state, identity, resource indexing, rendering, and extension wiring.
|
package/package.json
CHANGED
package/src/extension.ts
CHANGED
|
@@ -84,9 +84,10 @@ export function registerHelpExtension(pi: ExtensionAPI): void {
|
|
|
84
84
|
return index;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function persist(ctx: ExtensionContext):
|
|
87
|
+
function persist(ctx: ExtensionContext): { ok: boolean; warning?: string } {
|
|
88
88
|
const result = saveState(paths, state);
|
|
89
89
|
notifySaveWarning(ctx, result.warning);
|
|
90
|
+
return result;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
pi.registerCommand("help", {
|
|
@@ -101,8 +102,12 @@ export function registerHelpExtension(pi: ExtensionAPI): void {
|
|
|
101
102
|
|
|
102
103
|
if (subcommand === "refresh") {
|
|
103
104
|
rebuildIndex(ctx);
|
|
104
|
-
persist(ctx);
|
|
105
|
-
|
|
105
|
+
const result = persist(ctx);
|
|
106
|
+
if (result.ok) {
|
|
107
|
+
ctx.ui.notify("帮助索引已刷新", "info");
|
|
108
|
+
} else {
|
|
109
|
+
ctx.ui.notify(`帮助索引刷新失败:${result.warning ?? "保存状态失败"}`, "error");
|
|
110
|
+
}
|
|
106
111
|
return;
|
|
107
112
|
}
|
|
108
113
|
|
|
@@ -116,10 +121,16 @@ export function registerHelpExtension(pi: ExtensionAPI): void {
|
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
const target = matches[0];
|
|
124
|
+
const wasPinned = target.pinned;
|
|
119
125
|
target.pinned = subcommand === "pin";
|
|
120
126
|
target.lastSeenAt = Date.now();
|
|
121
|
-
persist(ctx);
|
|
122
|
-
|
|
127
|
+
const result = persist(ctx);
|
|
128
|
+
if (result.ok) {
|
|
129
|
+
ctx.ui.notify(`${subcommand === "pin" ? "已固定" : "已取消固定"}:${target.displayName ?? target.name} (${target.kind} · ${target.sourceLabel})`, "info");
|
|
130
|
+
} else {
|
|
131
|
+
target.pinned = wasPinned; // rollback
|
|
132
|
+
ctx.ui.notify(`${subcommand === "pin" ? "固定" : "取消固定"}失败:${result.warning ?? "保存状态失败"}`, "error");
|
|
133
|
+
}
|
|
123
134
|
return;
|
|
124
135
|
}
|
|
125
136
|
|
package/src/render/markdown.ts
CHANGED
|
@@ -57,13 +57,6 @@ export function buildMarkdown(index: ResourceIndex, updatedAt: number | undefine
|
|
|
57
57
|
|
|
58
58
|
const updated = updatedAt ? new Date(updatedAt).toLocaleString() : new Date().toLocaleString();
|
|
59
59
|
const title = normalizedQuery ? `动态帮助 · 搜索:${escapeMarkdownInline(query?.trim())}` : "动态帮助";
|
|
60
|
-
const mcpUsageLines = [
|
|
61
|
-
"### 用法",
|
|
62
|
-
"- `mcp({})` 查看状态",
|
|
63
|
-
"- `mcp({ server: \"chrome-devtools\" })` 列出服务器工具",
|
|
64
|
-
"- `mcp({ search: \"screenshot\" })` 搜索工具",
|
|
65
|
-
"- `mcp({ tool: \"...\", args: '{\"...\"}' })` 调用工具",
|
|
66
|
-
].join("\n");
|
|
67
60
|
|
|
68
61
|
return [
|
|
69
62
|
`# ${title}`,
|
|
@@ -89,8 +82,6 @@ export function buildMarkdown(index: ResourceIndex, updatedAt: number | undefine
|
|
|
89
82
|
"### 网关",
|
|
90
83
|
gatewayItems.length > 0 ? gatewayItems.map(formatItem).join("\n") : "- 暂无",
|
|
91
84
|
"",
|
|
92
|
-
mcpUsageLines,
|
|
93
|
-
"",
|
|
94
85
|
"### 服务器",
|
|
95
86
|
serverItems.length > 0 ? serverItems.map(formatItem).join("\n") : "- 暂无",
|
|
96
87
|
"",
|
|
@@ -102,13 +93,5 @@ export function buildMarkdown(index: ResourceIndex, updatedAt: number | undefine
|
|
|
102
93
|
"- `/help pin <词>` 固定匹配项",
|
|
103
94
|
"- `/help unpin <词>` 取消固定",
|
|
104
95
|
"- `/help refresh` 重新扫描并刷新使用统计",
|
|
105
|
-
"",
|
|
106
|
-
"## 示例",
|
|
107
|
-
"- `需求分析:...`",
|
|
108
|
-
"- `系统设计:...`",
|
|
109
|
-
"- `实现:...`",
|
|
110
|
-
"- `审查:...`",
|
|
111
|
-
"- `/goal ...`",
|
|
112
|
-
"- `/brainstorm ...`",
|
|
113
96
|
].join("\n");
|
|
114
97
|
}
|
package/src/resources/index.ts
CHANGED
|
@@ -103,22 +103,26 @@ export function buildResourceIndex(input: ResourceRuntimeInput): ResourceIndex {
|
|
|
103
103
|
for (const server of input.mcpServers) mergedMcp.set(server.name, server);
|
|
104
104
|
|
|
105
105
|
const commandItems: IndexedItem[] = [];
|
|
106
|
+
const seenCommandKeys = new Set<string>();
|
|
106
107
|
for (const command of commands) {
|
|
107
108
|
const sourceRef = compactSourceRef(command.sourceInfo.source ?? command.sourceInfo.origin ?? command.sourceInfo.scope);
|
|
108
109
|
const base = itemBase("command", command.name, sourceRef);
|
|
109
|
-
|
|
110
|
+
const item = upsertItem(state, {
|
|
110
111
|
...base,
|
|
111
112
|
description: command.description,
|
|
112
113
|
sourceLabel: sourceLabelForCommand(command.sourceInfo),
|
|
113
114
|
scope: command.sourceInfo.scope,
|
|
114
115
|
packageName: command.sourceInfo.source,
|
|
115
116
|
lastSeenAt: now,
|
|
116
|
-
})
|
|
117
|
+
});
|
|
118
|
+
commandItems.push(item);
|
|
119
|
+
seenCommandKeys.add(item.key);
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
for (const builtin of BUILTIN_COMMANDS) {
|
|
120
123
|
const sourceRef = "builtin";
|
|
121
124
|
const base = itemBase("command", builtin.name, sourceRef);
|
|
125
|
+
if (seenCommandKeys.has(base.key)) continue;
|
|
122
126
|
commandItems.push(upsertItem(state, {
|
|
123
127
|
...base,
|
|
124
128
|
description: builtin.description,
|
|
@@ -172,10 +176,10 @@ export function buildResourceIndex(input: ResourceRuntimeInput): ResourceIndex {
|
|
|
172
176
|
const base = itemBase("mcp", server.name, sourceRef);
|
|
173
177
|
mcpItems.push(upsertItem(state, {
|
|
174
178
|
...base,
|
|
175
|
-
description: server.
|
|
179
|
+
description: server.mode === "http" ? "HTTP 服务器" : "stdio 服务器",
|
|
176
180
|
sourceLabel: sourceLabelForMcp(server),
|
|
177
181
|
scope: "user",
|
|
178
|
-
packageName:
|
|
182
|
+
packageName: undefined,
|
|
179
183
|
lastSeenAt: now,
|
|
180
184
|
}));
|
|
181
185
|
}
|