pi-nested-skills 0.2.1 → 0.3.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/README.md CHANGED
@@ -66,7 +66,7 @@ The package does not access credentials, make network requests, start processes,
66
66
  ## Requirements
67
67
 
68
68
  - Node.js 22 or newer.
69
- - Pi `>=0.80.0 <0.81.0`.
69
+ - Pi `>=0.80.0`.
70
70
 
71
71
  ## License
72
72
 
package/README.zh-CN.md CHANGED
@@ -66,7 +66,7 @@ pi install npm:pi-nested-skills
66
66
  ## 要求
67
67
 
68
68
  - Node.js 22 或更高版本。
69
- - Pi `>=0.80.0 <0.81.0`。
69
+ - Pi `>=0.80.0`。
70
70
 
71
71
  ## 许可证
72
72
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-nested-skills",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Pi extension for recursive nested-skill discovery and aliases",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -58,15 +58,15 @@
58
58
  "autocomplete"
59
59
  ],
60
60
  "peerDependencies": {
61
- "@earendil-works/pi-coding-agent": ">=0.80.0 <0.81.0",
62
- "@earendil-works/pi-tui": ">=0.80.0 <0.81.0"
61
+ "@earendil-works/pi-coding-agent": ">=0.80.0",
62
+ "@earendil-works/pi-tui": ">=0.80.0"
63
63
  },
64
64
  "dependencies": {
65
- "pi-extensions-i18n": "^0.4.0"
65
+ "pi-extensions-i18n": "^0.5.0"
66
66
  },
67
67
  "devDependencies": {
68
- "@earendil-works/pi-coding-agent": "0.80.10",
69
- "@earendil-works/pi-tui": "0.80.10",
68
+ "@earendil-works/pi-coding-agent": "0.85.1",
69
+ "@earendil-works/pi-tui": "0.85.1",
70
70
  "@types/node": "24.12.4",
71
71
  "tsx": "4.23.1",
72
72
  "typescript": "5.9.3"
package/src/index.ts CHANGED
@@ -5,13 +5,27 @@ 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 { createTranslator, loadCatalog } from "pi-extensions-i18n";
8
+ import {
9
+ createTranslator,
10
+ loadCatalog,
11
+ notifyWithSource,
12
+ type NoticeColor,
13
+ type NoticeLevel,
14
+ type NoticeSource,
15
+ } from "pi-extensions-i18n";
9
16
  import { loadConfig, parseConfig, saveConfig, type LoadedNestedSkillsConfig } from "./config.ts";
10
17
  import { scanSkillRoots, type NestedSkill, type SkillScanResult } from "./skills.ts";
11
18
 
12
19
  const messages = loadCatalog(new URL("../locales/index.json", import.meta.url));
13
20
  const i18n = createTranslator(messages);
14
21
 
22
+ /** 本扩展的提示标签;短且唯一,便于在会话里定位来源。 */
23
+ const NOTICE_TAG = "skills";
24
+ /** 提示标签颜色;与其它扩展错开,避免看起来像同一条消息。 */
25
+ const NOTICE_COLOR: NoticeColor = "success";
26
+ /** 本扩展的提示来源。 */
27
+ const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
28
+
15
29
  const COMMAND_NAME = "skills";
16
30
  const COMMAND_ALIASES = [COMMAND_NAME] as const;
17
31
  const CONFIG_COMMAND_ALIASES = ["config:nested-skills", "nested-skills-config", "pi-nested-skills-config"] as const;
@@ -19,14 +33,19 @@ const CONFIG_RESET_COMMAND = "reset";
19
33
  const DEFAULT_CONFIG_ROOT = "skills";
20
34
  const ROOT_INPUT_SEPARATOR = ",";
21
35
  const ROOT_DISPLAY_SEPARATOR = ", ";
22
- const NOTICE_WARNING = "warning" as const;
23
- const NOTICE_INFO = "info" as const;
24
- const NOTICE_ERROR = "error" as const;
36
+ const NOTICE_WARNING: NoticeLevel = "warning";
37
+ const NOTICE_INFO: NoticeLevel = "info";
38
+ const NOTICE_ERROR: NoticeLevel = "error";
25
39
  const SKILL_COMMAND_PREFIX = "skill:";
26
40
  const INPUT_SOURCES = new Set(["interactive", "rpc"]);
27
41
 
28
42
  type SkillCommandContext = ExtensionCommandContext;
29
43
 
44
+ /** 统一的带来源提示出口,保持所有 notify 调用点只传正文与级别。 */
45
+ function notify(ctx: ExtensionContext, message: string, level: NoticeLevel): void {
46
+ notifyWithSource({ ctx, source: NOTICE_SOURCE, level, message });
47
+ }
48
+
30
49
  interface SkillCandidate {
31
50
  alias: string;
32
51
  skill: NestedSkill;
@@ -210,22 +229,22 @@ function registerConfigCommand(pi: ExtensionAPI): void {
210
229
  handler: async (args: string, ctx: ExtensionCommandContext): Promise<void> => {
211
230
  const argument = args.trim();
212
231
  if (argument && argument !== CONFIG_RESET_COMMAND) {
213
- ctx.ui.notify(i18n.t("configCommandUsage"), NOTICE_WARNING);
232
+ notify(ctx, i18n.t("configCommandUsage"), NOTICE_WARNING);
214
233
  return;
215
234
  }
216
235
  if (argument === CONFIG_RESET_COMMAND) {
217
236
  try {
218
237
  const path = saveConfig(parseConfig({ skillRoots: [DEFAULT_CONFIG_ROOT] }));
219
- ctx.ui.notify(i18n.t("configCommandSaved", { path }), NOTICE_INFO);
238
+ notify(ctx, i18n.t("configCommandSaved", { path }), NOTICE_INFO);
220
239
  } catch (error) {
221
- ctx.ui.notify(i18n.t("configCommandInvalid", {
240
+ notify(ctx, i18n.t("configCommandInvalid", {
222
241
  error: error instanceof Error ? error.message : String(error),
223
242
  }), NOTICE_ERROR);
224
243
  }
225
244
  return;
226
245
  }
227
246
  if (!ctx.hasUI) {
228
- ctx.ui.notify(i18n.t("configCommandInteractiveOnly"), NOTICE_WARNING);
247
+ notify(ctx, i18n.t("configCommandInteractiveOnly"), NOTICE_WARNING);
229
248
  return;
230
249
  }
231
250
 
@@ -238,9 +257,9 @@ function registerConfigCommand(pi: ExtensionAPI): void {
238
257
  try {
239
258
  const roots = input.split(ROOT_INPUT_SEPARATOR).map((root) => root.trim()).filter(Boolean);
240
259
  const path = saveConfig(parseConfig({ skillRoots: roots }));
241
- ctx.ui.notify(i18n.t("configCommandSaved", { path }), NOTICE_INFO);
260
+ notify(ctx, i18n.t("configCommandSaved", { path }), NOTICE_INFO);
242
261
  } catch (error) {
243
- ctx.ui.notify(i18n.t("configCommandInvalid", {
262
+ notify(ctx, i18n.t("configCommandInvalid", {
244
263
  error: error instanceof Error ? error.message : String(error),
245
264
  }), NOTICE_ERROR);
246
265
  }
@@ -264,16 +283,18 @@ function registerSkillsCommand(pi: ExtensionAPI, index: SkillIndex): void {
264
283
  function notifyDiagnostics(ctx: ExtensionContext, loaded: LoadedNestedSkillsConfig, index: SkillIndex): void {
265
284
  if (!ctx.hasUI) return;
266
285
  for (const warning of loaded.warnings) {
267
- ctx.ui.notify(i18n.t("configWarning", { reason: warning }), NOTICE_WARNING);
286
+ notify(ctx, i18n.t("configWarning", { reason: warning }), NOTICE_WARNING);
268
287
  }
269
288
  for (const warning of index.warnings) {
270
- ctx.ui.notify(
289
+ notify(
290
+ ctx,
271
291
  i18n.t("scanWarning", { path: warning.path, reason: warning.reason }),
272
292
  NOTICE_WARNING,
273
293
  );
274
294
  }
275
295
  if (loaded.explicit && index.skills.length === 0) {
276
- ctx.ui.notify(
296
+ notify(
297
+ ctx,
277
298
  i18n.t("noSkills", { roots: loaded.config.skillRoots.join(", ") || i18n.t("noRoots") }),
278
299
  NOTICE_WARNING,
279
300
  );