@spences10/pi-skills 0.0.19 → 0.0.21

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.
Files changed (67) hide show
  1. package/README.md +18 -32
  2. package/dist/commands/completions.d.ts +8 -0
  3. package/dist/commands/completions.js +68 -0
  4. package/dist/commands/completions.js.map +1 -0
  5. package/dist/commands/github-handlers.d.ts +4 -0
  6. package/dist/commands/github-handlers.js +127 -0
  7. package/dist/commands/github-handlers.js.map +1 -0
  8. package/dist/commands/handler.d.ts +2 -0
  9. package/dist/commands/handler.js +56 -0
  10. package/dist/commands/handler.js.map +1 -0
  11. package/dist/commands/home-handler.d.ts +2 -0
  12. package/dist/commands/home-handler.js +38 -0
  13. package/dist/commands/home-handler.js.map +1 -0
  14. package/dist/commands/profile-handlers.d.ts +2 -0
  15. package/dist/commands/profile-handlers.js +117 -0
  16. package/dist/commands/profile-handlers.js.map +1 -0
  17. package/dist/commands/skill-handlers.d.ts +8 -0
  18. package/dist/commands/skill-handlers.js +184 -0
  19. package/dist/commands/skill-handlers.js.map +1 -0
  20. package/dist/commands/types.d.ts +13 -0
  21. package/dist/commands/types.js +2 -0
  22. package/dist/commands/types.js.map +1 -0
  23. package/dist/commands.js +91 -227
  24. package/dist/commands.js.map +1 -1
  25. package/dist/gh-skill.d.ts +16 -0
  26. package/dist/gh-skill.js +52 -0
  27. package/dist/gh-skill.js.map +1 -1
  28. package/dist/importer.d.ts +4 -0
  29. package/dist/importer.js +21 -0
  30. package/dist/importer.js.map +1 -1
  31. package/dist/manager/discovery.d.ts +19 -0
  32. package/dist/manager/discovery.js +101 -0
  33. package/dist/manager/discovery.js.map +1 -0
  34. package/dist/manager/import-management.d.ts +11 -0
  35. package/dist/manager/import-management.js +28 -0
  36. package/dist/manager/import-management.js.map +1 -0
  37. package/dist/manager/profile.d.ts +29 -0
  38. package/dist/manager/profile.js +214 -0
  39. package/dist/manager/profile.js.map +1 -0
  40. package/dist/manager.d.ts +4 -7
  41. package/dist/manager.js +35 -36
  42. package/dist/manager.js.map +1 -1
  43. package/dist/resource-discovery.d.ts +1 -0
  44. package/dist/resource-discovery.js +7 -0
  45. package/dist/resource-discovery.js.map +1 -0
  46. package/dist/scanner.d.ts +2 -33
  47. package/dist/scanner.js +7 -108
  48. package/dist/scanner.js.map +1 -1
  49. package/dist/skill-utils.d.ts +0 -7
  50. package/dist/skill-utils.js +10 -89
  51. package/dist/skill-utils.js.map +1 -1
  52. package/dist/skills-ui/github.d.ts +1 -0
  53. package/dist/skills-ui/github.js +128 -2
  54. package/dist/skills-ui/github.js.map +1 -1
  55. package/dist/skills-ui/home.d.ts +5 -1
  56. package/dist/skills-ui/home.js +7 -7
  57. package/dist/skills-ui/home.js.map +1 -1
  58. package/dist/skills-ui/manage.js +33 -5
  59. package/dist/skills-ui/manage.js.map +1 -1
  60. package/dist/skills-ui/profiles.js +1 -1
  61. package/dist/skills-ui/profiles.js.map +1 -1
  62. package/dist/skills-ui/skill-list.js +2 -5
  63. package/dist/skills-ui/skill-list.js.map +1 -1
  64. package/dist/skills-ui.d.ts +1 -2
  65. package/dist/skills-ui.js +1 -2
  66. package/dist/skills-ui.js.map +1 -1
  67. package/package.json +6 -4
@@ -0,0 +1,184 @@
1
+ import { show_text_modal } from '@spences10/pi-tui-modal';
2
+ import { find_skill, format_skill_detail, format_skill_list, sort_skills, } from '../skill-utils.js';
3
+ import { pick_skill, show_defaults_modal, show_refresh_summary, show_skill_detail_modal, show_skill_list_modal, } from '../skills-ui.js';
4
+ import { handle_github_import } from './github-handlers.js';
5
+ function notify_error(ctx, error) {
6
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), 'warning');
7
+ }
8
+ export async function handle_list_command({ mgr, ctx, }) {
9
+ const skills = [...mgr.discover(), ...mgr.discover_importable()];
10
+ if (ctx.hasUI)
11
+ await show_skill_list_modal(ctx, mgr);
12
+ else
13
+ ctx.ui.notify(format_skill_list(skills));
14
+ return false;
15
+ }
16
+ export async function handle_show_command({ arg, mgr, ctx, }) {
17
+ const skills = [...mgr.discover(), ...mgr.discover_importable()];
18
+ let target = arg;
19
+ if (!target && ctx.hasUI) {
20
+ target =
21
+ (await pick_skill(ctx, {
22
+ title: 'Show skill details',
23
+ subtitle: 'Open a read-only skill detail view',
24
+ skills: sort_skills(skills),
25
+ empty_message: 'No skills found',
26
+ })) ?? '';
27
+ if (!target)
28
+ return true;
29
+ }
30
+ if (!target) {
31
+ ctx.ui.notify('Usage: /skills show <key|name>', 'warning');
32
+ return true;
33
+ }
34
+ try {
35
+ const skill = find_skill(skills, target);
36
+ if (ctx.hasUI)
37
+ await show_skill_detail_modal(ctx, skill);
38
+ else
39
+ ctx.ui.notify(format_skill_detail(skill));
40
+ }
41
+ catch (error) {
42
+ notify_error(ctx, error);
43
+ }
44
+ return false;
45
+ }
46
+ export async function handle_toggle_command(request) {
47
+ const { sub, arg, mgr, ctx } = request;
48
+ let target = arg;
49
+ if (!target && ctx.hasUI) {
50
+ target =
51
+ (await pick_skill(ctx, {
52
+ title: sub === 'enable'
53
+ ? 'Enable skill in active profile'
54
+ : 'Disable skill in active profile',
55
+ subtitle: `Profile: ${mgr.get_active_profile()}`,
56
+ skills: sort_skills(mgr.discover()),
57
+ empty_message: 'No managed skills found',
58
+ })) ?? '';
59
+ if (!target)
60
+ return true;
61
+ }
62
+ if (!target) {
63
+ ctx.ui.notify(`Usage: /skills ${sub} <key|name|pattern>`, 'warning');
64
+ return true;
65
+ }
66
+ let pattern = target;
67
+ try {
68
+ pattern = find_skill(mgr.discover(), target).key;
69
+ }
70
+ catch {
71
+ // Treat misses as patterns, e.g. design-* or *@plugin:vendor.
72
+ }
73
+ if (sub === 'enable')
74
+ mgr.enable(pattern);
75
+ else
76
+ mgr.disable(pattern);
77
+ ctx.ui.notify(`Updated ${mgr.get_active_profile()} profile. Reloading...`, 'info');
78
+ await ctx.reload();
79
+ return true;
80
+ }
81
+ export async function handle_import_command(request) {
82
+ const { arg, mgr, ctx } = request;
83
+ let target = arg;
84
+ if (!target && ctx.hasUI) {
85
+ target =
86
+ (await pick_skill(ctx, {
87
+ title: 'Import skill',
88
+ subtitle: 'Copy an external skill into Pi-native storage, or run: /skills import <owner/repo> <skill>',
89
+ skills: sort_skills(mgr.discover_importable()),
90
+ empty_message: 'No importable skills found',
91
+ })) ?? '';
92
+ if (!target)
93
+ return true;
94
+ }
95
+ if (!target) {
96
+ ctx.ui.notify('Usage: /skills import <key|name> OR /skills import <owner/repo> <skill[@ref]> [--pin ref|--scope project|--dir path|--force]', 'warning');
97
+ return true;
98
+ }
99
+ if (await handle_github_import(request))
100
+ return true;
101
+ try {
102
+ const result = mgr.import_skill(target);
103
+ ctx.ui.notify(`Imported ${target} to ${result.skillDir}. Reloading...`, 'info');
104
+ await ctx.reload();
105
+ return true;
106
+ }
107
+ catch (error) {
108
+ notify_error(ctx, error);
109
+ return true;
110
+ }
111
+ }
112
+ export async function handle_sync_command({ arg, mgr, ctx, }) {
113
+ let target = arg;
114
+ if (!target && ctx.hasUI) {
115
+ target =
116
+ (await pick_skill(ctx, {
117
+ title: 'Sync imported skill',
118
+ subtitle: 'Update an imported skill from its upstream source',
119
+ skills: sort_skills(mgr
120
+ .discover()
121
+ .filter((skill) => Boolean(skill.import_meta))),
122
+ empty_message: 'No imported skills found',
123
+ })) ?? '';
124
+ if (!target)
125
+ return true;
126
+ }
127
+ if (!target) {
128
+ ctx.ui.notify('Usage: /skills sync <key|name>', 'warning');
129
+ return true;
130
+ }
131
+ try {
132
+ const result = mgr.sync_skill(target);
133
+ if (result.changed) {
134
+ ctx.ui.notify(`Synced ${target}. Reloading...`, 'info');
135
+ await ctx.reload();
136
+ return true;
137
+ }
138
+ if (ctx.hasUI) {
139
+ await show_text_modal(ctx, {
140
+ title: 'Skill already up to date',
141
+ text: `${target} is already up to date.`,
142
+ });
143
+ }
144
+ else {
145
+ ctx.ui.notify(`${target} is already up to date.`, 'info');
146
+ }
147
+ return true;
148
+ }
149
+ catch (error) {
150
+ notify_error(ctx, error);
151
+ return true;
152
+ }
153
+ }
154
+ export async function handle_refresh_command({ mgr, ctx, }) {
155
+ if (ctx.hasUI) {
156
+ await show_refresh_summary(ctx, mgr);
157
+ return false;
158
+ }
159
+ mgr.refresh();
160
+ ctx.ui.notify(`Rescanned: ${mgr.discover().length} managed skills, ${mgr.discover_importable().length} importable skills found`);
161
+ return false;
162
+ }
163
+ export async function handle_defaults_command({ arg, mgr, ctx, }) {
164
+ if (!arg && ctx.hasUI) {
165
+ await show_defaults_modal(ctx, mgr);
166
+ return false;
167
+ }
168
+ if (arg !== 'all-enabled' && arg !== 'all-disabled') {
169
+ ctx.ui.notify('Usage: /skills defaults <all-enabled|all-disabled>', 'warning');
170
+ return true;
171
+ }
172
+ mgr.set_defaults(arg);
173
+ if (ctx.hasUI) {
174
+ await show_text_modal(ctx, {
175
+ title: 'Default skill policy updated',
176
+ text: `Active profile now starts from: ${arg}`,
177
+ });
178
+ }
179
+ else {
180
+ ctx.ui.notify(`Default skill policy: ${arg}`);
181
+ }
182
+ return false;
183
+ }
184
+ //# sourceMappingURL=skill-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-handlers.js","sourceRoot":"","sources":["../../src/commands/skill-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ExtensionCommandContext } from '@earendil-works/pi-coding-agent';
2
+ import type { create_skills_manager } from '../manager.js';
3
+ export type SkillsManager = ReturnType<typeof create_skills_manager>;
4
+ export type SkillsCommandUiContext = ExtensionCommandContext;
5
+ export type SkillsCommandRequest = {
6
+ args: string;
7
+ trimmed: string;
8
+ sub: string;
9
+ rest: string[];
10
+ arg: string;
11
+ mgr: SkillsManager;
12
+ ctx: SkillsCommandUiContext;
13
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/commands/types.ts"],"names":[],"mappings":""}
package/dist/commands.js CHANGED
@@ -1,14 +1,10 @@
1
- import { run_with_progress_modal, show_input_modal, show_text_modal, } from '@spences10/pi-tui-modal';
2
- import { has_gh_skill, parse_gh_skill_install_args, run_gh_skill_install, run_gh_skill_install_async, run_gh_skill_update, run_gh_skill_update_async, } from './gh-skill.js';
1
+ import { run_with_progress_modal, show_confirm_modal, show_input_modal, show_text_modal, } from '@spences10/pi-tui-modal';
2
+ import { get_skill_argument_completions, SKILL_SUBCOMMANDS, } from './commands/completions.js';
3
+ import { has_gh_skill, parse_gh_skill_install_args, run_gh_skill_install, run_gh_skill_install_async, run_gh_skill_search, run_gh_skill_update, run_gh_skill_update_async, } from './gh-skill.js';
3
4
  import { create_skills_manager } from './manager.js';
5
+ import { is_resource_enabled } from './resource-discovery.js';
4
6
  import { find_skill, format_profile_detail, format_skill_detail, format_skill_list, profile_description, sort_skills, } from './skill-utils.js';
5
- import { pick_profile, pick_skill, show_add_github_skill_modal, show_defaults_modal, show_importable_skills_modal, show_profiles_modal, show_refresh_summary, show_skill_detail_modal, show_skill_list_modal, show_skills_home_modal, show_skills_manager_modal, show_update_github_skills_modal, } from './skills-ui.js';
6
- function is_resource_enabled(value) {
7
- const normalized = value?.trim().toLowerCase();
8
- if (!normalized)
9
- return true;
10
- return !['0', 'false', 'no', 'skip', 'disable'].includes(normalized);
11
- }
7
+ import { pick_profile, pick_skill, show_add_github_skill_modal, show_defaults_modal, show_profiles_modal, show_refresh_summary, show_search_github_skills_modal, show_skill_detail_modal, show_skill_list_modal, show_skills_home_modal, show_skills_manager_modal, show_update_github_skills_modal, } from './skills-ui.js';
12
8
  export default async function skills(pi) {
13
9
  const mgr = create_skills_manager();
14
10
  pi.on('resources_discover', async (event) => {
@@ -18,119 +14,28 @@ export default async function skills(pi) {
18
14
  });
19
15
  return { skillPaths: resource_mgr.get_enabled_skill_paths() };
20
16
  });
21
- const subs = [
22
- 'list',
23
- 'show',
24
- 'enable',
25
- 'disable',
26
- 'add',
27
- 'import',
28
- 'sync',
29
- 'update',
30
- 'profile',
31
- 'refresh',
32
- 'defaults',
33
- ];
34
17
  pi.registerCommand('skills', {
35
- description: 'Manage pi-native skills and import external skills',
36
- getArgumentCompletions: (prefix) => {
37
- const parts = prefix.trimStart().split(/\s+/);
38
- const has_trailing_space = /\s$/.test(prefix);
39
- if (parts.length <= 1 && !has_trailing_space) {
40
- return subs
41
- .filter((s) => s.startsWith(parts[0] || ''))
42
- .map((s) => ({ value: s, label: s }));
43
- }
44
- if (['show', 'enable', 'disable'].includes(parts[0] ?? '')) {
45
- const q = parts.slice(1).join(' ').toLowerCase();
46
- const skills = parts[0] === 'show'
47
- ? [...mgr.discover(), ...mgr.discover_importable()]
48
- : mgr.discover();
49
- return sort_skills(skills)
50
- .filter((s) => s.key.toLowerCase().includes(q) ||
51
- s.name.toLowerCase().includes(q))
52
- .slice(0, 20)
53
- .map((s) => ({
54
- value: `${parts[0]} ${s.key}`,
55
- label: s.key,
56
- }));
57
- }
58
- if (parts[0] === 'import') {
59
- const q = parts.slice(1).join(' ').toLowerCase();
60
- return sort_skills(mgr.discover_importable())
61
- .filter((s) => s.key.toLowerCase().includes(q) ||
62
- s.name.toLowerCase().includes(q))
63
- .slice(0, 20)
64
- .map((s) => ({
65
- value: `${parts[0]} ${s.key}`,
66
- label: s.key,
67
- }));
68
- }
69
- if (parts[0] === 'update') {
70
- return ['--dry-run', '--all', '--force', '--unpin']
71
- .filter((flag) => flag.startsWith(parts.at(-1) ?? ''))
72
- .map((flag) => ({
73
- value: `${parts.slice(0, -1).join(' ')} ${flag}`.trim(),
74
- label: flag,
75
- }));
76
- }
77
- if (parts[0] === 'sync') {
78
- const q = parts.slice(1).join(' ').toLowerCase();
79
- return sort_skills(mgr
80
- .discover()
81
- .filter((skill) => Boolean(skill.import_meta)))
82
- .filter((s) => s.key.toLowerCase().includes(q) ||
83
- s.name.toLowerCase().includes(q))
84
- .slice(0, 20)
85
- .map((s) => ({
86
- value: `${parts[0]} ${s.key}`,
87
- label: s.key,
88
- }));
89
- }
90
- if (parts[0] === 'profile') {
91
- const profile_subs = [
92
- 'list',
93
- 'show',
94
- 'use',
95
- 'create',
96
- 'include',
97
- 'exclude',
98
- ];
99
- if (parts.length <= 2 && !has_trailing_space) {
100
- return profile_subs
101
- .filter((s) => s.startsWith(parts[1] || ''))
102
- .map((s) => ({ value: `profile ${s}`, label: s }));
103
- }
104
- if (['show', 'use', 'include', 'exclude'].includes(parts[1] ?? '')) {
105
- const q = parts.slice(2).join(' ').toLowerCase();
106
- return mgr
107
- .list_profiles()
108
- .filter((profile) => profile.name.toLowerCase().includes(q))
109
- .slice(0, 20)
110
- .map((profile) => ({
111
- value: `profile ${parts[1]} ${profile.name}`,
112
- label: profile.name,
113
- }));
114
- }
115
- }
116
- return null;
117
- },
18
+ description: 'Manage and discover Pi skills',
19
+ getArgumentCompletions: (prefix) => get_skill_argument_completions(prefix, mgr),
118
20
  handler: async (args, ctx) => {
119
21
  const trimmed = args.trim();
120
22
  if (!trimmed && ctx.hasUI) {
121
23
  let selected;
122
24
  while (true) {
123
- const managed_count = mgr.discover().length;
124
- const importable_count = mgr.discover_importable().length;
125
- selected = await show_skills_home_modal(ctx, managed_count, importable_count, mgr.get_active_profile());
25
+ const managed = mgr.discover();
26
+ const counts = {
27
+ managed: managed.length,
28
+ pi_native: managed.filter((skill) => skill.source === 'pi-native').length,
29
+ };
30
+ selected = await show_skills_home_modal(ctx, counts, mgr.get_active_profile());
126
31
  if (!selected)
127
32
  break;
128
33
  if (selected === 'manage') {
129
34
  if (await show_skills_manager_modal(ctx, mgr))
130
35
  return;
131
36
  }
132
- else if (selected === 'importable') {
133
- if (await show_importable_skills_modal(ctx, mgr))
37
+ else if (selected === 'search') {
38
+ if (await show_search_github_skills_modal(ctx))
134
39
  return;
135
40
  }
136
41
  else if (selected === 'add') {
@@ -155,10 +60,7 @@ export default async function skills(pi) {
155
60
  const arg = rest.join(' ');
156
61
  switch (sub) {
157
62
  case 'list': {
158
- const skills = [
159
- ...mgr.discover(),
160
- ...mgr.discover_importable(),
161
- ];
63
+ const skills = mgr.discover();
162
64
  if (ctx.hasUI) {
163
65
  await show_skill_list_modal(ctx, mgr);
164
66
  }
@@ -168,10 +70,7 @@ export default async function skills(pi) {
168
70
  break;
169
71
  }
170
72
  case 'show': {
171
- const skills = [
172
- ...mgr.discover(),
173
- ...mgr.discover_importable(),
174
- ];
73
+ const skills = mgr.discover();
175
74
  let target = arg;
176
75
  if (!target && ctx.hasUI) {
177
76
  target =
@@ -237,6 +136,78 @@ export default async function skills(pi) {
237
136
  await ctx.reload();
238
137
  return;
239
138
  }
139
+ case 'delete': {
140
+ let targets = rest;
141
+ if (!targets.length && ctx.hasUI) {
142
+ const target = await pick_skill(ctx, {
143
+ title: 'Delete skill',
144
+ subtitle: 'Remove a managed skill directory from disk',
145
+ skills: sort_skills(mgr.discover()),
146
+ empty_message: 'No managed skills found',
147
+ });
148
+ if (!target)
149
+ return;
150
+ targets = [target];
151
+ }
152
+ if (!targets.length) {
153
+ ctx.ui.notify('Usage: /skills delete <key|name> [key|name...]', 'warning');
154
+ return;
155
+ }
156
+ if (ctx.hasUI) {
157
+ const ok = await show_confirm_modal(ctx, {
158
+ title: 'Delete skills?',
159
+ message: `Delete ${targets.length} skill${targets.length === 1 ? '' : 's'} from disk? This cannot be undone.`,
160
+ confirm_label: 'Delete',
161
+ cancel_label: 'Keep skills',
162
+ });
163
+ if (!ok)
164
+ return;
165
+ }
166
+ let deleted = 0;
167
+ for (const target of targets) {
168
+ try {
169
+ mgr.delete_skill(target);
170
+ deleted += 1;
171
+ }
172
+ catch (error) {
173
+ ctx.ui.notify(error instanceof Error
174
+ ? error.message
175
+ : String(error), 'warning');
176
+ }
177
+ }
178
+ if (deleted) {
179
+ ctx.ui.notify(`Deleted ${deleted} skill${deleted === 1 ? '' : 's'}. Reloading...`, 'info');
180
+ await ctx.reload();
181
+ return;
182
+ }
183
+ break;
184
+ }
185
+ case 'search': {
186
+ if (!arg && ctx.hasUI) {
187
+ if (await show_search_github_skills_modal(ctx))
188
+ return;
189
+ break;
190
+ }
191
+ if (!arg) {
192
+ ctx.ui.notify('Usage: /skills search <query>', 'warning');
193
+ return;
194
+ }
195
+ if (!has_gh_skill()) {
196
+ ctx.ui.notify('GitHub skill search requires gh v2.90.0+ with `gh skill` support.', 'warning');
197
+ return;
198
+ }
199
+ try {
200
+ const results = run_gh_skill_search(arg, 15);
201
+ const lines = results.map((result) => `${result.skillName} — ${result.repo} (${result.stars}★)\n ${result.path}\n ${result.description}`);
202
+ ctx.ui.notify(lines.length
203
+ ? `GitHub skill search results for ${arg}:\n\n${lines.join('\n\n')}\n\nReview before installing. Preview: gh skill preview <repo> <path>\nInstall: /skills add <repo> <path>`
204
+ : `Nothing found matching “${arg}”. Try a shorter query or run: gh skill search ${arg}`, lines.length ? 'info' : 'warning');
205
+ }
206
+ catch (error) {
207
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), 'warning');
208
+ }
209
+ return;
210
+ }
240
211
  case 'add': {
241
212
  if (!arg && ctx.hasUI) {
242
213
  if (await show_add_github_skill_modal(ctx))
@@ -273,113 +244,6 @@ export default async function skills(pi) {
273
244
  return;
274
245
  }
275
246
  }
276
- case 'import': {
277
- let target = arg;
278
- if (!target && ctx.hasUI) {
279
- target =
280
- (await pick_skill(ctx, {
281
- title: 'Import skill',
282
- subtitle: 'Copy an external skill into Pi-native storage, or run: /skills import <owner/repo> <skill>',
283
- skills: sort_skills(mgr.discover_importable()),
284
- empty_message: 'No importable skills found',
285
- })) ?? '';
286
- if (!target)
287
- return;
288
- }
289
- if (!target) {
290
- ctx.ui.notify('Usage: /skills import <key|name> OR /skills import <owner/repo> <skill[@ref]> [--pin ref|--scope project|--dir path|--force]', 'warning');
291
- return;
292
- }
293
- const gh_request = parse_gh_skill_install_args(rest);
294
- if (gh_request) {
295
- if (!has_gh_skill()) {
296
- ctx.ui.notify('GitHub skill imports require gh v2.90.0+ with `gh skill` support.', 'warning');
297
- return;
298
- }
299
- try {
300
- const output = ctx.hasUI
301
- ? await run_with_progress_modal(ctx, {
302
- title: 'Importing GitHub skill',
303
- message: `Installing ${gh_request.skill} from ${gh_request.repository}`,
304
- }, async ({ signal, update }) => {
305
- update({ current: gh_request.skill });
306
- return await run_gh_skill_install_async(gh_request, undefined, { signal });
307
- })
308
- : run_gh_skill_install(gh_request);
309
- if (output === undefined)
310
- return;
311
- if (ctx.hasUI) {
312
- await show_text_modal(ctx, {
313
- title: 'GitHub skill imported',
314
- text: `${output || `Imported ${gh_request.skill} from ${gh_request.repository}`}\n\nReloading...`,
315
- });
316
- }
317
- else {
318
- ctx.ui.notify(`${output || `Imported ${gh_request.skill} from ${gh_request.repository}`}\nReloading...`, 'info');
319
- }
320
- await ctx.reload();
321
- return;
322
- }
323
- catch (error) {
324
- ctx.ui.notify(error instanceof Error
325
- ? error.message
326
- : String(error), 'warning');
327
- return;
328
- }
329
- }
330
- try {
331
- const result = mgr.import_skill(target);
332
- ctx.ui.notify(`Imported ${target} to ${result.skillDir}. Reloading...`, 'info');
333
- await ctx.reload();
334
- return;
335
- }
336
- catch (error) {
337
- ctx.ui.notify(error instanceof Error ? error.message : String(error), 'warning');
338
- return;
339
- }
340
- }
341
- case 'sync': {
342
- let target = arg;
343
- if (!target && ctx.hasUI) {
344
- target =
345
- (await pick_skill(ctx, {
346
- title: 'Sync imported skill',
347
- subtitle: 'Update an imported skill from its upstream source',
348
- skills: sort_skills(mgr
349
- .discover()
350
- .filter((skill) => Boolean(skill.import_meta))),
351
- empty_message: 'No imported skills found',
352
- })) ?? '';
353
- if (!target)
354
- return;
355
- }
356
- if (!target) {
357
- ctx.ui.notify('Usage: /skills sync <key|name>', 'warning');
358
- return;
359
- }
360
- try {
361
- const result = mgr.sync_skill(target);
362
- if (result.changed) {
363
- ctx.ui.notify(`Synced ${target}. Reloading...`, 'info');
364
- await ctx.reload();
365
- return;
366
- }
367
- if (ctx.hasUI) {
368
- await show_text_modal(ctx, {
369
- title: 'Skill already up to date',
370
- text: `${target} is already up to date.`,
371
- });
372
- }
373
- else {
374
- ctx.ui.notify(`${target} is already up to date.`, 'info');
375
- }
376
- return;
377
- }
378
- catch (error) {
379
- ctx.ui.notify(error instanceof Error ? error.message : String(error), 'warning');
380
- return;
381
- }
382
- }
383
247
  case 'update': {
384
248
  if (!has_gh_skill()) {
385
249
  ctx.ui.notify('GitHub skill updates require gh v2.90.0+ with `gh skill` support.', 'warning');
@@ -545,7 +409,7 @@ export default async function skills(pi) {
545
409
  break;
546
410
  }
547
411
  mgr.refresh();
548
- ctx.ui.notify(`Rescanned: ${mgr.discover().length} managed skills, ${mgr.discover_importable().length} importable skills found`);
412
+ ctx.ui.notify(`Rescanned: ${mgr.discover().length} managed skills found`);
549
413
  break;
550
414
  }
551
415
  case 'defaults': {
@@ -570,7 +434,7 @@ export default async function skills(pi) {
570
434
  break;
571
435
  }
572
436
  default:
573
- ctx.ui.notify(`Unknown: ${sub}. Use: ${subs.join(', ')}`, 'warning');
437
+ ctx.ui.notify(`Unknown: ${sub}. Use: ${SKILL_SUBCOMMANDS.join(', ')}`, 'warning');
574
438
  }
575
439
  },
576
440
  });