pi-nested-skills 0.2.2 → 0.4.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/package.json +2 -2
- package/src/index.ts +37 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-nested-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Pi extension for recursive nested-skill discovery and aliases",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@earendil-works/pi-tui": ">=0.80.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"pi-extensions-i18n": "^0.
|
|
65
|
+
"pi-extensions-i18n": "^0.6.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
package/src/index.ts
CHANGED
|
@@ -5,13 +5,28 @@ import type {
|
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import { fuzzyFilter } from "@earendil-works/pi-tui";
|
|
7
7
|
import type { AutocompleteItem, AutocompleteProvider } from "@earendil-works/pi-tui";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createTranslator,
|
|
10
|
+
loadCatalog,
|
|
11
|
+
installNoticeRenderer,
|
|
12
|
+
notifyWithSource,
|
|
13
|
+
type NoticeColor,
|
|
14
|
+
type NoticeLevel,
|
|
15
|
+
type NoticeSource,
|
|
16
|
+
} from "pi-extensions-i18n";
|
|
9
17
|
import { loadConfig, parseConfig, saveConfig, type LoadedNestedSkillsConfig } from "./config.ts";
|
|
10
18
|
import { scanSkillRoots, type NestedSkill, type SkillScanResult } from "./skills.ts";
|
|
11
19
|
|
|
12
20
|
const messages = loadCatalog(new URL("../locales/index.json", import.meta.url));
|
|
13
21
|
const i18n = createTranslator(messages);
|
|
14
22
|
|
|
23
|
+
/** 本扩展的提示标签;短且唯一,便于在会话里定位来源。 */
|
|
24
|
+
const NOTICE_TAG = "skills";
|
|
25
|
+
/** 提示标签颜色;与其它扩展错开,避免看起来像同一条消息。 */
|
|
26
|
+
const NOTICE_COLOR: NoticeColor = "success";
|
|
27
|
+
/** 本扩展的提示来源。 */
|
|
28
|
+
const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
|
|
29
|
+
|
|
15
30
|
const COMMAND_NAME = "skills";
|
|
16
31
|
const COMMAND_ALIASES = [COMMAND_NAME] as const;
|
|
17
32
|
const CONFIG_COMMAND_ALIASES = ["config:nested-skills", "nested-skills-config", "pi-nested-skills-config"] as const;
|
|
@@ -19,14 +34,19 @@ const CONFIG_RESET_COMMAND = "reset";
|
|
|
19
34
|
const DEFAULT_CONFIG_ROOT = "skills";
|
|
20
35
|
const ROOT_INPUT_SEPARATOR = ",";
|
|
21
36
|
const ROOT_DISPLAY_SEPARATOR = ", ";
|
|
22
|
-
const NOTICE_WARNING = "warning"
|
|
23
|
-
const NOTICE_INFO = "info"
|
|
24
|
-
const NOTICE_ERROR = "error"
|
|
37
|
+
const NOTICE_WARNING: NoticeLevel = "warning";
|
|
38
|
+
const NOTICE_INFO: NoticeLevel = "info";
|
|
39
|
+
const NOTICE_ERROR: NoticeLevel = "error";
|
|
25
40
|
const SKILL_COMMAND_PREFIX = "skill:";
|
|
26
41
|
const INPUT_SOURCES = new Set(["interactive", "rpc"]);
|
|
27
42
|
|
|
28
43
|
type SkillCommandContext = ExtensionCommandContext;
|
|
29
44
|
|
|
45
|
+
/** 统一的带来源提示出口,保持所有 notify 调用点只传正文与级别。 */
|
|
46
|
+
function notify(ctx: ExtensionContext, message: string, level: NoticeLevel): void {
|
|
47
|
+
notifyWithSource({ ctx, source: NOTICE_SOURCE, level, message });
|
|
48
|
+
}
|
|
49
|
+
|
|
30
50
|
interface SkillCandidate {
|
|
31
51
|
alias: string;
|
|
32
52
|
skill: NestedSkill;
|
|
@@ -210,22 +230,22 @@ function registerConfigCommand(pi: ExtensionAPI): void {
|
|
|
210
230
|
handler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {
|
|
211
231
|
const argument = args.trim();
|
|
212
232
|
if (argument && argument !== CONFIG_RESET_COMMAND) {
|
|
213
|
-
|
|
233
|
+
notify(ctx, i18n.t("configCommandUsage"), NOTICE_WARNING);
|
|
214
234
|
return;
|
|
215
235
|
}
|
|
216
236
|
if (argument === CONFIG_RESET_COMMAND) {
|
|
217
237
|
try {
|
|
218
238
|
const path = saveConfig(parseConfig({ skillRoots: [DEFAULT_CONFIG_ROOT] }));
|
|
219
|
-
|
|
239
|
+
notify(ctx, i18n.t("configCommandSaved", { path }), NOTICE_INFO);
|
|
220
240
|
} catch (error) {
|
|
221
|
-
|
|
241
|
+
notify(ctx, i18n.t("configCommandInvalid", {
|
|
222
242
|
error: error instanceof Error ? error.message : String(error),
|
|
223
243
|
}), NOTICE_ERROR);
|
|
224
244
|
}
|
|
225
245
|
return;
|
|
226
246
|
}
|
|
227
247
|
if (!ctx.hasUI) {
|
|
228
|
-
|
|
248
|
+
notify(ctx, i18n.t("configCommandInteractiveOnly"), NOTICE_WARNING);
|
|
229
249
|
return;
|
|
230
250
|
}
|
|
231
251
|
|
|
@@ -238,9 +258,9 @@ function registerConfigCommand(pi: ExtensionAPI): void {
|
|
|
238
258
|
try {
|
|
239
259
|
const roots = input.split(ROOT_INPUT_SEPARATOR).map((root) => root.trim()).filter(Boolean);
|
|
240
260
|
const path = saveConfig(parseConfig({ skillRoots: roots }));
|
|
241
|
-
|
|
261
|
+
notify(ctx, i18n.t("configCommandSaved", { path }), NOTICE_INFO);
|
|
242
262
|
} catch (error) {
|
|
243
|
-
|
|
263
|
+
notify(ctx, i18n.t("configCommandInvalid", {
|
|
244
264
|
error: error instanceof Error ? error.message : String(error),
|
|
245
265
|
}), NOTICE_ERROR);
|
|
246
266
|
}
|
|
@@ -264,16 +284,18 @@ function registerSkillsCommand(pi: ExtensionAPI, index: SkillIndex): void {
|
|
|
264
284
|
function notifyDiagnostics(ctx: ExtensionContext, loaded: LoadedNestedSkillsConfig, index: SkillIndex): void {
|
|
265
285
|
if (!ctx.hasUI) return;
|
|
266
286
|
for (const warning of loaded.warnings) {
|
|
267
|
-
|
|
287
|
+
notify(ctx, i18n.t("configWarning", { reason: warning }), NOTICE_WARNING);
|
|
268
288
|
}
|
|
269
289
|
for (const warning of index.warnings) {
|
|
270
|
-
|
|
290
|
+
notify(
|
|
291
|
+
ctx,
|
|
271
292
|
i18n.t("scanWarning", { path: warning.path, reason: warning.reason }),
|
|
272
293
|
NOTICE_WARNING,
|
|
273
294
|
);
|
|
274
295
|
}
|
|
275
296
|
if (loaded.explicit && index.skills.length === 0) {
|
|
276
|
-
|
|
297
|
+
notify(
|
|
298
|
+
ctx,
|
|
277
299
|
i18n.t("noSkills", { roots: loaded.config.skillRoots.join(", ") || i18n.t("noRoots") }),
|
|
278
300
|
NOTICE_WARNING,
|
|
279
301
|
);
|
|
@@ -282,6 +304,8 @@ function notifyDiagnostics(ctx: ExtensionContext, loaded: LoadedNestedSkillsConf
|
|
|
282
304
|
|
|
283
305
|
/** 注册递归技能别名,同时把实际技能正文交给 Pi 原生技能加载和展开流程。 */
|
|
284
306
|
export default function nestedSkillsExtension(pi: ExtensionAPI): void {
|
|
307
|
+
// 提示画成会话区里的带底色消息块;渲染器在本包这个模块实例里注册一次。
|
|
308
|
+
installNoticeRenderer(pi);
|
|
285
309
|
const loaded = loadConfig();
|
|
286
310
|
const scan = scanSkillRoots(loaded.config.skillRoots);
|
|
287
311
|
const index = buildSkillIndex(scan);
|