@spences10/pi-skill-importer 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Scott Spence
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @spences10/pi-skill-importer
2
+
3
+ Pi extension and helper API for importing external Agent
4
+ Skills-compatible sources into Pi-native skill storage.
5
+
6
+ The extension registers `/skill-importer` with list/import/sync/delete
7
+ flows. It discovers Claude plugin skills, then copies selected skills
8
+ into:
9
+
10
+ ```text
11
+ $PI_CODING_AGENT_DIR/skills/<skill-name>
12
+ ```
13
+
14
+ Imported copies include provenance metadata so sync can detect
15
+ upstream changes and refuse to overwrite local edits.
16
+
17
+ ## Safety model
18
+
19
+ External source locations such as `~/.claude/skills` and Claude plugin
20
+ caches are treated as upstream sources. The importer only owns copied
21
+ Pi-native skills that contain its metadata; it should not delete
22
+ upstream Claude/plugin directories.
23
+
24
+ ## Commands
25
+
26
+ ```text
27
+ /skill-importer
28
+ /skill-importer list
29
+ /skill-importer import <key|name>
30
+ /skill-importer sync <key|name>
31
+ /skill-importer delete <key|name>
32
+ ```
33
+
34
+ Review external skills before importing: they can instruct agent
35
+ behavior and tool use. Sync refuses to overwrite local edits, and
36
+ delete only removes imported Pi-native copies with metadata.
37
+
38
+ ## API
39
+
40
+ ```ts
41
+ import {
42
+ scan_importable_skills,
43
+ import_external_skill,
44
+ sync_imported_skill,
45
+ delete_imported_skill,
46
+ } from '@spences10/pi-skill-importer';
47
+ ```
48
+
49
+ ## Development
50
+
51
+ ```bash
52
+ pnpm --filter @spences10/pi-skill-importer run check
53
+ pnpm --filter @spences10/pi-skill-importer run test
54
+ ```
55
+
56
+ ## License
57
+
58
+ MIT
@@ -0,0 +1,2 @@
1
+ import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
+ export default function skill_importer(pi: ExtensionAPI): Promise<void>;
@@ -0,0 +1,404 @@
1
+ import { show_confirm_modal, show_picker_modal, show_settings_modal, show_text_modal, } from '@spences10/pi-tui-modal';
2
+ import { delete_managed_skill as delete_imported_skill, get_imported_skill_sync_status, import_external_skill, sync_imported_skill, } from './importer.js';
3
+ import { scan_importable_skills, scan_managed_skills, } from './scanner.js';
4
+ const WARNING = 'External skills can instruct agent behavior and tool use. Import copies only after reviewing their source.';
5
+ const selected_label = '● selected';
6
+ const skipped_label = '○ skip';
7
+ const delete_label = '✕ delete';
8
+ const keep_label = '○ keep';
9
+ function skill_key(skill) {
10
+ return `${skill.source}/${skill.name}`;
11
+ }
12
+ function imported_skills() {
13
+ return scan_managed_skills().filter((skill) => skill.import_meta);
14
+ }
15
+ function sort_skills(skills) {
16
+ return [...skills].sort((a, b) => `${a.name}\0${a.source}`.localeCompare(`${b.name}\0${b.source}`));
17
+ }
18
+ function find_skill(skills, target) {
19
+ const trimmed = target.trim();
20
+ const match = skills.find((skill) => skill.name === trimmed ||
21
+ skill_key(skill) === trimmed ||
22
+ skill.baseDir === trimmed ||
23
+ skill.skillPath === trimmed);
24
+ if (!match)
25
+ throw new Error(`Skill not found: ${target}`);
26
+ return match;
27
+ }
28
+ function find_imported_for_sync(target) {
29
+ const imported = imported_skills();
30
+ try {
31
+ return find_skill(imported, target);
32
+ }
33
+ catch {
34
+ const external = find_skill(scan_importable_skills(), target);
35
+ const match = imported.find((skill) => skill.import_meta?.source === external.source &&
36
+ skill.import_meta.upstream_base_dir === external.baseDir);
37
+ if (match)
38
+ return match;
39
+ throw new Error(`Imported copy not found for ${target}`);
40
+ }
41
+ }
42
+ function format_plugin(skill) {
43
+ if (!skill.plugin)
44
+ return skill.source;
45
+ return [
46
+ skill.source,
47
+ `version ${skill.plugin.version}`,
48
+ skill.plugin.gitCommitSha
49
+ ? `commit ${skill.plugin.gitCommitSha.slice(0, 12)}`
50
+ : undefined,
51
+ ]
52
+ .filter(Boolean)
53
+ .join(' • ');
54
+ }
55
+ function format_external(skill) {
56
+ return [
57
+ `${skill.name} — ${skill.description}`,
58
+ `key: ${skill_key(skill)}`,
59
+ `source: ${format_plugin(skill)}`,
60
+ `upstream: ${skill.baseDir}`,
61
+ ].join('\n');
62
+ }
63
+ function format_imported(skill) {
64
+ const status = get_imported_skill_sync_status(skill);
65
+ const meta = skill.import_meta;
66
+ return [
67
+ `${skill.name} — ${status.status.replaceAll('-', ' ')}`,
68
+ `key: ${skill_key(skill)}`,
69
+ `source: ${meta.source}`,
70
+ meta.upstream_version
71
+ ? `version: ${meta.upstream_version}`
72
+ : undefined,
73
+ meta.upstream_git_commit_sha
74
+ ? `commit: ${meta.upstream_git_commit_sha.slice(0, 12)}`
75
+ : undefined,
76
+ `upstream: ${meta.upstream_base_dir}`,
77
+ status.detail,
78
+ ]
79
+ .filter(Boolean)
80
+ .join('\n');
81
+ }
82
+ function notify_error(ctx, error) {
83
+ ctx.ui.notify(error instanceof Error ? error.message : String(error), 'warning');
84
+ }
85
+ async function pick_imported(ctx, title) {
86
+ const skills = sort_skills(imported_skills());
87
+ const selected = await show_picker_modal(ctx, {
88
+ title,
89
+ subtitle: 'Only copied Pi-native skills with importer metadata are shown.',
90
+ items: skills.map((skill) => ({
91
+ value: skill_key(skill),
92
+ label: skill.name,
93
+ description: get_imported_skill_sync_status(skill).status,
94
+ })),
95
+ selected_footer: (item) => {
96
+ const skill = item ? find_skill(skills, item.value) : undefined;
97
+ return skill ? format_imported(skill).split('\n') : undefined;
98
+ },
99
+ empty_message: 'No imported skill copies found',
100
+ max_visible: 12,
101
+ });
102
+ return selected ? find_skill(skills, selected) : undefined;
103
+ }
104
+ async function show_home(ctx) {
105
+ while (true) {
106
+ const external = scan_importable_skills();
107
+ const imported = imported_skills();
108
+ const action = await show_picker_modal(ctx, {
109
+ title: 'Skill importer',
110
+ subtitle: `${external.length} external • ${imported.length} imported copies`,
111
+ footer: WARNING,
112
+ items: [
113
+ {
114
+ value: 'list',
115
+ label: 'List skills',
116
+ description: 'Show importable and imported skills',
117
+ },
118
+ {
119
+ value: 'import',
120
+ label: 'Import external skill',
121
+ description: 'Copy an external skill into Pi-native storage',
122
+ },
123
+ {
124
+ value: 'sync',
125
+ label: 'Sync imported copy',
126
+ description: 'Refresh a copied skill when upstream changed',
127
+ },
128
+ {
129
+ value: 'delete',
130
+ label: 'Delete imported copy',
131
+ description: 'Remove only copied skills with importer metadata',
132
+ },
133
+ ],
134
+ });
135
+ if (!action)
136
+ return;
137
+ if (action === 'list')
138
+ await show_list(ctx);
139
+ else if (action === 'import')
140
+ await import_command('', ctx);
141
+ else if (action === 'sync')
142
+ await sync_command('', ctx);
143
+ else if (action === 'delete')
144
+ await delete_command('', ctx);
145
+ }
146
+ }
147
+ async function show_list(ctx) {
148
+ const external = sort_skills(scan_importable_skills());
149
+ const imported = sort_skills(imported_skills());
150
+ if (!ctx.hasUI) {
151
+ const text = [
152
+ WARNING,
153
+ '',
154
+ 'Importable external skills',
155
+ external.length
156
+ ? external.map(format_external).join('\n\n')
157
+ : 'None found.',
158
+ '',
159
+ 'Imported copies',
160
+ imported.length
161
+ ? imported.map(format_imported).join('\n\n')
162
+ : 'None found.',
163
+ ].join('\n');
164
+ ctx.ui.notify(text);
165
+ return;
166
+ }
167
+ const list_items = [
168
+ ...external.map((skill) => ({
169
+ kind: 'external',
170
+ value: `external:${skill_key(skill)}`,
171
+ skill,
172
+ })),
173
+ ...imported.map((skill) => ({
174
+ kind: 'imported',
175
+ value: `imported:${skill_key(skill)}`,
176
+ skill,
177
+ })),
178
+ ];
179
+ const by_value = new Map(list_items.map((item) => [item.value, item]));
180
+ while (true) {
181
+ const selected = await show_picker_modal(ctx, {
182
+ title: 'Browse importable skills',
183
+ subtitle: `${external.length} external • ${imported.length} imported`,
184
+ items: list_items.map(({ kind, value, skill }) => ({
185
+ value,
186
+ label: skill.name,
187
+ description: kind === 'external'
188
+ ? `external • ${skill.source}`
189
+ : `imported • ${get_imported_skill_sync_status(skill).status}`,
190
+ })),
191
+ selected_footer: (item) => {
192
+ const match = item ? by_value.get(item.value) : undefined;
193
+ if (!match)
194
+ return undefined;
195
+ return (match.kind === 'external'
196
+ ? format_external(match.skill)
197
+ : format_imported(match.skill)).split('\n');
198
+ },
199
+ empty_message: 'No external or imported skills found',
200
+ max_visible: 12,
201
+ });
202
+ if (!selected)
203
+ return;
204
+ const match = by_value.get(selected);
205
+ if (!match)
206
+ continue;
207
+ await show_text_modal(ctx, {
208
+ title: match.skill.name,
209
+ text: match.kind === 'external'
210
+ ? format_external(match.skill)
211
+ : format_imported(match.skill),
212
+ });
213
+ }
214
+ }
215
+ function selectable_skill_items(skills, selected_value, unselected_value) {
216
+ return skills.map((skill) => {
217
+ return {
218
+ id: skill_key(skill),
219
+ label: skill.name,
220
+ description: skill.kind === 'external'
221
+ ? format_external(skill)
222
+ : format_imported(skill),
223
+ currentValue: unselected_value,
224
+ values: [unselected_value, selected_value],
225
+ };
226
+ });
227
+ }
228
+ async function pick_external_many(ctx) {
229
+ const skills = sort_skills(scan_importable_skills());
230
+ if (skills.length === 0) {
231
+ ctx.ui.notify('No importable external skills found');
232
+ return [];
233
+ }
234
+ const items = selectable_skill_items(skills, selected_label, skipped_label);
235
+ await show_settings_modal(ctx, {
236
+ title: 'Import external skills',
237
+ subtitle: `${skills.length} importable • toggle any skills to import`,
238
+ footer: 'enter toggles',
239
+ items,
240
+ max_visible: 12,
241
+ enable_search: true,
242
+ metadata: (item) => item?.description?.split('\n'),
243
+ on_change: () => undefined,
244
+ });
245
+ const selected = new Set(items
246
+ .filter((item) => item.currentValue === selected_label)
247
+ .map((item) => item.id));
248
+ return skills.filter((skill) => selected.has(skill_key(skill)));
249
+ }
250
+ async function import_command(target, ctx) {
251
+ try {
252
+ const skills = target
253
+ ? [find_skill(scan_importable_skills(), target)]
254
+ : ctx.hasUI
255
+ ? await pick_external_many(ctx)
256
+ : [];
257
+ if (skills.length === 0) {
258
+ ctx.ui.notify('Usage: /skill-importer import <key|name>', 'warning');
259
+ return;
260
+ }
261
+ if (ctx.hasUI) {
262
+ const ok = await show_confirm_modal(ctx, {
263
+ title: `Import ${skills.length} skill${skills.length === 1 ? '' : 's'}?`,
264
+ message: `${WARNING}\n\n${skills.map(format_external).join('\n\n')}`,
265
+ confirm_label: 'Import selected',
266
+ cancel_label: 'Cancel',
267
+ });
268
+ if (!ok)
269
+ return;
270
+ }
271
+ for (const skill of skills)
272
+ import_external_skill(skill);
273
+ ctx.ui.notify(`Imported ${skills.length} skill${skills.length === 1 ? '' : 's'}. Reloading...`, 'info');
274
+ await ctx.reload();
275
+ }
276
+ catch (error) {
277
+ notify_error(ctx, error);
278
+ }
279
+ }
280
+ async function sync_command(target, ctx) {
281
+ try {
282
+ const skill = target
283
+ ? find_imported_for_sync(target)
284
+ : ctx.hasUI
285
+ ? await pick_imported(ctx, 'Sync imported skill')
286
+ : undefined;
287
+ if (!skill) {
288
+ ctx.ui.notify('Usage: /skill-importer sync <key|name>', 'warning');
289
+ return;
290
+ }
291
+ const result = sync_imported_skill(skill);
292
+ ctx.ui.notify(result.changed
293
+ ? `Synced ${skill.name}. Reloading...`
294
+ : `${skill.name} is already up to date.`, 'info');
295
+ if (result.changed)
296
+ await ctx.reload();
297
+ }
298
+ catch (error) {
299
+ notify_error(ctx, error);
300
+ }
301
+ }
302
+ async function pick_imported_for_delete(ctx) {
303
+ const skills = sort_skills(imported_skills());
304
+ if (skills.length === 0) {
305
+ ctx.ui.notify('No imported skill copies found');
306
+ return [];
307
+ }
308
+ const items = selectable_skill_items(skills, delete_label, keep_label);
309
+ await show_settings_modal(ctx, {
310
+ title: 'Delete imported skill copies',
311
+ subtitle: `${skills.length} imported • toggle copies to delete`,
312
+ footer: 'enter toggles',
313
+ items,
314
+ max_visible: 12,
315
+ enable_search: true,
316
+ metadata: (item) => item?.description?.split('\n'),
317
+ on_change: () => undefined,
318
+ });
319
+ const selected = new Set(items
320
+ .filter((item) => item.currentValue === delete_label)
321
+ .map((item) => item.id));
322
+ return skills.filter((skill) => selected.has(skill_key(skill)));
323
+ }
324
+ async function delete_command(target, ctx) {
325
+ try {
326
+ const skills = target
327
+ ? [find_skill(imported_skills(), target)]
328
+ : ctx.hasUI
329
+ ? await pick_imported_for_delete(ctx)
330
+ : [];
331
+ if (skills.length === 0) {
332
+ ctx.ui.notify('Usage: /skill-importer delete <key|name>', 'warning');
333
+ return;
334
+ }
335
+ if (ctx.hasUI) {
336
+ const ok = await show_confirm_modal(ctx, {
337
+ title: `Delete ${skills.length} imported cop${skills.length === 1 ? 'y' : 'ies'}?`,
338
+ message: `Delete ${skills.map((skill) => skill.name).join(', ')}? Upstream external sources are never deleted.`,
339
+ confirm_label: 'Delete selected',
340
+ cancel_label: 'Keep copies',
341
+ });
342
+ if (!ok)
343
+ return;
344
+ }
345
+ for (const skill of skills)
346
+ delete_imported_skill(skill);
347
+ ctx.ui.notify(`Deleted ${skills.length} imported cop${skills.length === 1 ? 'y' : 'ies'}. Reloading...`, 'info');
348
+ await ctx.reload();
349
+ }
350
+ catch (error) {
351
+ notify_error(ctx, error);
352
+ }
353
+ }
354
+ function completions(prefix) {
355
+ const parts = prefix.trimStart().split(/\s+/);
356
+ const has_trailing_space = /\s$/.test(prefix);
357
+ if (parts.length <= 1 && !has_trailing_space) {
358
+ return ['list', 'import', 'sync', 'delete']
359
+ .filter((item) => item.startsWith(parts[0] ?? ''))
360
+ .map((item) => ({ value: item, label: item }));
361
+ }
362
+ const sub = parts[0];
363
+ const target_prefix = parts.slice(1).join(' ').toLowerCase();
364
+ const skills = sub === 'import' ? scan_importable_skills() : imported_skills();
365
+ return skills
366
+ .flatMap((skill) => [skill_key(skill), skill.name])
367
+ .filter((item) => item.toLowerCase().includes(target_prefix))
368
+ .slice(0, 20)
369
+ .map((item) => ({ value: `${sub} ${item}`, label: item }));
370
+ }
371
+ export default async function skill_importer(pi) {
372
+ pi.registerCommand('skill-importer', {
373
+ description: 'Import external Agent Skills into Pi-native storage',
374
+ getArgumentCompletions: completions,
375
+ handler: async (args, ctx) => {
376
+ const trimmed = args.trim();
377
+ if (!trimmed && ctx.hasUI) {
378
+ await show_home(ctx);
379
+ return;
380
+ }
381
+ const [sub = 'list', ...rest] = trimmed.split(/\s+/);
382
+ const target = rest.join(' ');
383
+ switch (sub) {
384
+ case 'list':
385
+ case 'ls':
386
+ await show_list(ctx);
387
+ break;
388
+ case 'import':
389
+ await import_command(target, ctx);
390
+ break;
391
+ case 'sync':
392
+ await sync_command(target, ctx);
393
+ break;
394
+ case 'delete':
395
+ case 'remove':
396
+ await delete_command(target, ctx);
397
+ break;
398
+ default:
399
+ ctx.ui.notify('Usage: /skill-importer [list|import|sync|delete] [key|name]', 'warning');
400
+ }
401
+ },
402
+ });
403
+ }
404
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAKA,OAAO,EACN,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,oBAAoB,IAAI,qBAAqB,EAC7C,8BAA8B,EAC9B,qBAAqB,EACrB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,sBAAsB,EACtB,mBAAmB,GAEnB,MAAM,cAAc,CAAC;AAEtB,MAAM,OAAO,GACZ,4GAA4G,CAAC;AAC9G,MAAM,cAAc,GAAG,YAAY,CAAC;AACpC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAC/B,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,MAAM,UAAU,GAAG,QAAQ,CAAC;AAE5B,SAAS,SAAS,CAAC,KAAsB;IACxC,OAAO,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,eAAe;IACvB,OAAO,mBAAmB,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,MAAyB;IAC7C,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAChC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAChE,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAClB,MAAyB,EACzB,MAAc;IAEd,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CACxB,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,IAAI,KAAK,OAAO;QACtB,SAAS,CAAC,KAAK,CAAC,KAAK,OAAO;QAC5B,KAAK,CAAC,OAAO,KAAK,OAAO;QACzB,KAAK,CAAC,SAAS,KAAK,OAAO,CAC5B,CAAC;IACF,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAc;IAC7C,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,IAAI,CAAC;QACJ,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,QAAQ,GAAG,UAAU,CAAC,sBAAsB,EAAE,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAC1B,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,WAAW,EAAE,MAAM,KAAK,QAAQ,CAAC,MAAM;YAC7C,KAAK,CAAC,WAAW,CAAC,iBAAiB,KAAK,QAAQ,CAAC,OAAO,CACzD,CAAC;QACF,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;AACF,CAAC;AAED,SAAS,aAAa,CAAC,KAAsB;IAC5C,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IACvC,OAAO;QACN,KAAK,CAAC,MAAM;QACZ,WAAW,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACjC,KAAK,CAAC,MAAM,CAAC,YAAY;YACxB,CAAC,CAAC,UAAU,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;YACpD,CAAC,CAAC,SAAS;KACZ;SACC,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,KAAK,CAAC,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,KAAsB;IAC9C,OAAO;QACN,GAAG,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,WAAW,EAAE;QACtC,QAAQ,SAAS,CAAC,KAAK,CAAC,EAAE;QAC1B,WAAW,aAAa,CAAC,KAAK,CAAC,EAAE;QACjC,aAAa,KAAK,CAAC,OAAO,EAAE;KAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CAAC,KAAsB;IAC9C,MAAM,MAAM,GAAG,8BAA8B,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,KAAK,CAAC,WAAY,CAAC;IAChC,OAAO;QACN,GAAG,KAAK,CAAC,IAAI,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;QACvD,QAAQ,SAAS,CAAC,KAAK,CAAC,EAAE;QAC1B,WAAW,IAAI,CAAC,MAAM,EAAE;QACxB,IAAI,CAAC,gBAAgB;YACpB,CAAC,CAAC,YAAY,IAAI,CAAC,gBAAgB,EAAE;YACrC,CAAC,CAAC,SAAS;QACZ,IAAI,CAAC,uBAAuB;YAC3B,CAAC,CAAC,WAAW,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;YACxD,CAAC,CAAC,SAAS;QACZ,aAAa,IAAI,CAAC,iBAAiB,EAAE;QACrC,MAAM,CAAC,MAAM;KACb;SACC,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CACpB,GAA4B,EAC5B,KAAc;IAEd,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,SAAS,CACT,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC3B,GAA4B,EAC5B,KAAa;IAEb,MAAM,MAAM,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE;QAC7C,KAAK;QACL,QAAQ,EACP,gEAAgE;QACjE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC7B,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC;YACvB,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,WAAW,EAAE,8BAA8B,CAAC,KAAK,CAAC,CAAC,MAAM;SACzD,CAAC,CAAC;QACH,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChE,OAAO,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/D,CAAC;QACD,aAAa,EAAE,gCAAgC;QAC/C,WAAW,EAAE,EAAE;KACf,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,SAAS,CACvB,GAA4B;IAE5B,OAAO,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE;YAC3C,KAAK,EAAE,gBAAgB;YACvB,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,eAAe,QAAQ,CAAC,MAAM,kBAAkB;YAC5E,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACN;oBACC,KAAK,EAAE,MAAM;oBACb,KAAK,EAAE,aAAa;oBACpB,WAAW,EAAE,qCAAqC;iBAClD;gBACD;oBACC,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,uBAAuB;oBAC9B,WAAW,EACV,+CAA+C;iBAChD;gBACD;oBACC,KAAK,EAAE,MAAM;oBACb,KAAK,EAAE,oBAAoB;oBAC3B,WAAW,EAAE,8CAA8C;iBAC3D;gBACD;oBACC,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,sBAAsB;oBAC7B,WAAW,EACV,kDAAkD;iBACnD;aACD;SACD,CAAC,CAAC;QACH,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,MAAM,KAAK,MAAM;YAAE,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;aACvC,IAAI,MAAM,KAAK,QAAQ;YAAE,MAAM,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;aACvD,IAAI,MAAM,KAAK,MAAM;YAAE,MAAM,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;aACnD,IAAI,MAAM,KAAK,QAAQ;YAAE,MAAM,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC7D,CAAC;AACF,CAAC;AAED,KAAK,UAAU,SAAS,CACvB,GAA4B;IAE5B,MAAM,QAAQ,GAAG,WAAW,CAAC,sBAAsB,EAAE,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG;YACZ,OAAO;YACP,EAAE;YACF,4BAA4B;YAC5B,QAAQ,CAAC,MAAM;gBACd,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC5C,CAAC,CAAC,aAAa;YAChB,EAAE;YACF,iBAAiB;YACjB,QAAQ,CAAC,MAAM;gBACd,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC5C,CAAC,CAAC,aAAa;SAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO;IACR,CAAC;IAED,MAAM,UAAU,GAAG;QAClB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI,EAAE,UAAmB;YACzB,KAAK,EAAE,YAAY,SAAS,CAAC,KAAK,CAAC,EAAE;YACrC,KAAK;SACL,CAAC,CAAC;QACH,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI,EAAE,UAAmB;YACzB,KAAK,EAAE,YAAY,SAAS,CAAC,KAAK,CAAC,EAAE;YACrC,KAAK;SACL,CAAC,CAAC;KACH,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,GAAG,CACvB,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAC5C,CAAC;IACF,OAAO,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE;YAC7C,KAAK,EAAE,0BAA0B;YACjC,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,eAAe,QAAQ,CAAC,MAAM,WAAW;YACrE,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;gBAClD,KAAK;gBACL,KAAK,EAAE,KAAK,CAAC,IAAI;gBACjB,WAAW,EACV,IAAI,KAAK,UAAU;oBAClB,CAAC,CAAC,cAAc,KAAK,CAAC,MAAM,EAAE;oBAC9B,CAAC,CAAC,cAAc,8BAA8B,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;aAChE,CAAC,CAAC;YACH,eAAe,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1D,IAAI,CAAC,KAAK;oBAAE,OAAO,SAAS,CAAC;gBAC7B,OAAO,CACN,KAAK,CAAC,IAAI,KAAK,UAAU;oBACxB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC;oBAC9B,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAC/B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;YACD,aAAa,EAAE,sCAAsC;YACrD,WAAW,EAAE,EAAE;SACf,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,eAAe,CAAC,GAAG,EAAE;YAC1B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI;YACvB,IAAI,EACH,KAAK,CAAC,IAAI,KAAK,UAAU;gBACxB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC;gBAC9B,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC;SAChC,CAAC,CAAC;IACJ,CAAC;AACF,CAAC;AAED,SAAS,sBAAsB,CAC9B,MAAyB,EACzB,cAAsB,EACtB,gBAAwB;IAExB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,OAAO;YACN,EAAE,EAAE,SAAS,CAAC,KAAK,CAAC;YACpB,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,WAAW,EACV,KAAK,CAAC,IAAI,KAAK,UAAU;gBACxB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC;gBACxB,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC;YAC1B,YAAY,EAAE,gBAAgB;YAC9B,MAAM,EAAE,CAAC,gBAAgB,EAAE,cAAc,CAAC;SAC1C,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAChC,GAA4B;IAE5B,MAAM,MAAM,GAAG,WAAW,CAAC,sBAAsB,EAAE,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,qCAAqC,CAAC,CAAC;QACrD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,sBAAsB,CACnC,MAAM,EACN,cAAc,EACd,aAAa,CACb,CAAC;IACF,MAAM,mBAAmB,CAAC,GAAG,EAAE;QAC9B,KAAK,EAAE,wBAAwB;QAC/B,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,2CAA2C;QACrE,MAAM,EAAE,eAAe;QACvB,KAAK;QACL,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC;QAClD,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CACvB,KAAK;SACH,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,cAAc,CAAC;SACtD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CACxB,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,KAAK,UAAU,cAAc,CAC5B,MAAc,EACd,GAA4B;IAE5B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM;YACpB,CAAC,CAAC,CAAC,UAAU,CAAC,sBAAsB,EAAE,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC,CAAC,GAAG,CAAC,KAAK;gBACV,CAAC,CAAC,MAAM,kBAAkB,CAAC,GAAG,CAAC;gBAC/B,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,0CAA0C,EAC1C,SAAS,CACT,CAAC;YACF,OAAO;QACR,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE;gBACxC,KAAK,EAAE,UAAU,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG;gBACxE,OAAO,EAAE,GAAG,OAAO,OAAO,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBACpE,aAAa,EAAE,iBAAiB;gBAChC,YAAY,EAAE,QAAQ;aACtB,CAAC,CAAC;YACH,IAAI,CAAC,EAAE;gBAAE,OAAO;QACjB,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzD,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,YAAY,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,gBAAgB,EAChF,MAAM,CACN,CAAC;QACF,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;AACF,CAAC;AAED,KAAK,UAAU,YAAY,CAC1B,MAAc,EACd,GAA4B;IAE5B,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,MAAM;YACnB,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,GAAG,CAAC,KAAK;gBACV,CAAC,CAAC,MAAM,aAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC;gBACjD,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,wCAAwC,EACxC,SAAS,CACT,CAAC;YACF,OAAO;QACR,CAAC;QACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,MAAM,CAAC,OAAO;YACb,CAAC,CAAC,UAAU,KAAK,CAAC,IAAI,gBAAgB;YACtC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,yBAAyB,EACzC,MAAM,CACN,CAAC;QACF,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;AACF,CAAC;AAED,KAAK,UAAU,wBAAwB,CACtC,GAA4B;IAE5B,MAAM,MAAM,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,sBAAsB,CACnC,MAAM,EACN,YAAY,EACZ,UAAU,CACV,CAAC;IACF,MAAM,mBAAmB,CAAC,GAAG,EAAE;QAC9B,KAAK,EAAE,8BAA8B;QACrC,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,qCAAqC;QAC/D,MAAM,EAAE,eAAe;QACvB,KAAK;QACL,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC;QAClD,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CACvB,KAAK;SACH,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,YAAY,CAAC;SACpD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CACxB,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,KAAK,UAAU,cAAc,CAC5B,MAAc,EACd,GAA4B;IAE5B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM;YACpB,CAAC,CAAC,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC,CAAC,GAAG,CAAC,KAAK;gBACV,CAAC,CAAC,MAAM,wBAAwB,CAAC,GAAG,CAAC;gBACrC,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,0CAA0C,EAC1C,SAAS,CACT,CAAC;YACF,OAAO;QACR,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE;gBACxC,KAAK,EAAE,UAAU,MAAM,CAAC,MAAM,gBAAgB,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG;gBAClF,OAAO,EAAE,UAAU,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gDAAgD;gBAC/G,aAAa,EAAE,iBAAiB;gBAChC,YAAY,EAAE,aAAa;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,EAAE;gBAAE,OAAO;QACjB,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACzD,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,WAAW,MAAM,CAAC,MAAM,gBAAgB,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,gBAAgB,EACzF,MAAM,CACN,CAAC;QACF,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IAClC,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,kBAAkB,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC9C,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;aACzC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;aACjD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7D,MAAM,MAAM,GACX,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;IACjE,OAAO,MAAM;SACX,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;SAClD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;SAC5D,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,cAAc,CAC3C,EAAgB;IAEhB,EAAE,CAAC,eAAe,CAAC,gBAAgB,EAAE;QACpC,WAAW,EACV,qDAAqD;QACtD,sBAAsB,EAAE,WAAW;QACnC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC3B,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;gBACrB,OAAO;YACR,CAAC;YAED,MAAM,CAAC,GAAG,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9B,QAAQ,GAAG,EAAE,CAAC;gBACb,KAAK,MAAM,CAAC;gBACZ,KAAK,IAAI;oBACR,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;oBACrB,MAAM;gBACP,KAAK,QAAQ;oBACZ,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;oBAClC,MAAM;gBACP,KAAK,MAAM;oBACV,MAAM,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;oBAChC,MAAM;gBACP,KAAK,QAAQ,CAAC;gBACd,KAAK,QAAQ;oBACZ,MAAM,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;oBAClC,MAAM;gBACP;oBACC,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,6DAA6D,EAC7D,SAAS,CACT,CAAC;YACJ,CAAC;QACF,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { type DiscoveredSkill, type ImportedSkillMetadata } from './scanner.js';
2
+ export declare function validate_imported_skill_name(name: string): string;
3
+ export interface ImportSkillResult {
4
+ skillDir: string;
5
+ metadata: ImportedSkillMetadata;
6
+ }
7
+ export declare function import_external_skill(skill: DiscoveredSkill): ImportSkillResult;
8
+ export interface SyncSkillResult {
9
+ skillDir: string;
10
+ metadata: ImportedSkillMetadata;
11
+ changed: boolean;
12
+ }
13
+ export interface ImportedSkillSyncStatus {
14
+ status: 'up-to-date' | 'update-available' | 'local-changes' | 'missing-upstream';
15
+ detail: string;
16
+ currentHash?: string;
17
+ upstreamHash?: string;
18
+ }
19
+ export interface DeleteSkillResult {
20
+ skillDir: string;
21
+ }
22
+ export declare function get_imported_skill_sync_status(skill: DiscoveredSkill): ImportedSkillSyncStatus;
23
+ export declare function delete_managed_skill(skill: DiscoveredSkill): DeleteSkillResult;
24
+ export declare function sync_imported_skill(skill: DiscoveredSkill): SyncSkillResult;
@@ -0,0 +1,234 @@
1
+ import { getAgentDir } from '@earendil-works/pi-coding-agent';
2
+ import { createHash } from 'node:crypto';
3
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from 'node:fs';
4
+ import { dirname, isAbsolute, join, relative, resolve, } from 'node:path';
5
+ import { IMPORT_METADATA_FILE, } from './scanner.js';
6
+ const IMPORT_METADATA_VERSION = 1;
7
+ function get_managed_skills_dir() {
8
+ return join(getAgentDir(), 'skills');
9
+ }
10
+ function ensure_dir(path) {
11
+ mkdirSync(path, { recursive: true, mode: 0o700 });
12
+ }
13
+ function list_files_recursively(dir) {
14
+ const files = [];
15
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
16
+ const full_path = join(dir, entry.name);
17
+ if (entry.name === IMPORT_METADATA_FILE)
18
+ continue;
19
+ if (entry.isDirectory()) {
20
+ files.push(...list_files_recursively(full_path));
21
+ continue;
22
+ }
23
+ if (entry.isFile()) {
24
+ files.push(full_path);
25
+ }
26
+ }
27
+ return files.sort((a, b) => a.localeCompare(b));
28
+ }
29
+ function hash_directory(dir) {
30
+ const hash = createHash('sha256');
31
+ for (const file of list_files_recursively(dir)) {
32
+ hash.update(relative(dir, file));
33
+ hash.update('\0');
34
+ hash.update(readFileSync(file));
35
+ hash.update('\0');
36
+ }
37
+ return hash.digest('hex');
38
+ }
39
+ function read_metadata(base_dir) {
40
+ const path = join(base_dir, IMPORT_METADATA_FILE);
41
+ if (!existsSync(path))
42
+ return undefined;
43
+ try {
44
+ return JSON.parse(readFileSync(path, 'utf-8'));
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ function write_metadata(base_dir, metadata) {
51
+ writeFileSync(join(base_dir, IMPORT_METADATA_FILE), JSON.stringify(metadata, null, '\t') + '\n', { mode: 0o600 });
52
+ }
53
+ function has_control_character(value) {
54
+ return Array.from(value).some((char) => {
55
+ const code = char.codePointAt(0) ?? 0;
56
+ return code < 0x20 || code === 0x7f;
57
+ });
58
+ }
59
+ export function validate_imported_skill_name(name) {
60
+ if (!name.trim()) {
61
+ throw new Error('Skill name must not be empty');
62
+ }
63
+ if (name !== name.trim()) {
64
+ throw new Error(`Invalid skill name "${name}": leading or trailing whitespace is not allowed`);
65
+ }
66
+ if (name === '.' ||
67
+ name === '..' ||
68
+ isAbsolute(name) ||
69
+ /[\\/]/.test(name) ||
70
+ has_control_character(name)) {
71
+ throw new Error(`Invalid skill name "${name}": must be a single safe path segment`);
72
+ }
73
+ return name;
74
+ }
75
+ function resolve_managed_skill_dir(managed_root, name) {
76
+ const safe_name = validate_imported_skill_name(name);
77
+ const skill_dir = resolve(managed_root, safe_name);
78
+ const relative_path = relative(managed_root, skill_dir);
79
+ if (!relative_path ||
80
+ relative_path.startsWith('..') ||
81
+ isAbsolute(relative_path)) {
82
+ throw new Error(`Invalid skill name "${name}": destination escapes managed skills directory`);
83
+ }
84
+ return skill_dir;
85
+ }
86
+ function replace_directory(source_dir, dest_dir) {
87
+ const parent_dir = dirname(dest_dir);
88
+ ensure_dir(parent_dir);
89
+ const tmp_dir = join(parent_dir, `.${resolve(dest_dir).split('/').pop()}.tmp-${Date.now()}`);
90
+ rmSync(tmp_dir, { recursive: true, force: true });
91
+ cpSync(source_dir, tmp_dir, {
92
+ recursive: true,
93
+ preserveTimestamps: true,
94
+ verbatimSymlinks: false,
95
+ });
96
+ rmSync(dest_dir, { recursive: true, force: true });
97
+ cpSync(tmp_dir, dest_dir, {
98
+ recursive: true,
99
+ preserveTimestamps: true,
100
+ verbatimSymlinks: false,
101
+ });
102
+ rmSync(tmp_dir, { recursive: true, force: true });
103
+ }
104
+ export function import_external_skill(skill) {
105
+ if (skill.kind !== 'external') {
106
+ throw new Error(`Skill ${skill.name} is not importable`);
107
+ }
108
+ const managed_root = get_managed_skills_dir();
109
+ ensure_dir(managed_root);
110
+ const skill_dir = resolve_managed_skill_dir(managed_root, skill.name);
111
+ const existing = existsSync(skill_dir);
112
+ if (existing) {
113
+ const existing_stat = statSync(skill_dir);
114
+ if (!existing_stat.isDirectory()) {
115
+ throw new Error(`${skill_dir} exists and is not a directory`);
116
+ }
117
+ const existing_metadata = read_metadata(skill_dir);
118
+ if (!existing_metadata) {
119
+ throw new Error(`Refusing to overwrite existing unmanaged skill at ${skill_dir}`);
120
+ }
121
+ }
122
+ replace_directory(skill.baseDir, skill_dir);
123
+ const upstream_hash = hash_directory(skill.baseDir);
124
+ const imported_hash = hash_directory(skill_dir);
125
+ const now = new Date().toISOString();
126
+ const metadata = {
127
+ version: IMPORT_METADATA_VERSION,
128
+ source: skill.source,
129
+ upstream_skill_path: skill.skillPath,
130
+ upstream_base_dir: skill.baseDir,
131
+ upstream_install_path: skill.plugin?.installPath,
132
+ upstream_version: skill.plugin?.version,
133
+ upstream_git_commit_sha: skill.plugin?.gitCommitSha,
134
+ imported_at: now,
135
+ last_synced_at: now,
136
+ imported_hash,
137
+ upstream_hash,
138
+ };
139
+ write_metadata(skill_dir, metadata);
140
+ return {
141
+ skillDir: skill_dir,
142
+ metadata,
143
+ };
144
+ }
145
+ function assert_imported_skill(skill) {
146
+ if (skill.kind !== 'managed' || !skill.import_meta) {
147
+ throw new Error(`Skill ${skill.name} is not an imported Pi-native copy`);
148
+ }
149
+ return skill.import_meta;
150
+ }
151
+ export function get_imported_skill_sync_status(skill) {
152
+ const metadata = assert_imported_skill(skill);
153
+ if (!existsSync(metadata.upstream_base_dir)) {
154
+ return {
155
+ status: 'missing-upstream',
156
+ detail: `Upstream source no longer exists: ${metadata.upstream_base_dir}`,
157
+ };
158
+ }
159
+ const current_hash = hash_directory(skill.baseDir);
160
+ if (current_hash !== metadata.imported_hash) {
161
+ return {
162
+ status: 'local-changes',
163
+ detail: `Local changes detected in ${skill.baseDir}`,
164
+ currentHash: current_hash,
165
+ };
166
+ }
167
+ const upstream_hash = hash_directory(metadata.upstream_base_dir);
168
+ if (upstream_hash !== metadata.upstream_hash) {
169
+ return {
170
+ status: 'update-available',
171
+ detail: `Upstream changed since ${metadata.last_synced_at}`,
172
+ currentHash: current_hash,
173
+ upstreamHash: upstream_hash,
174
+ };
175
+ }
176
+ return {
177
+ status: 'up-to-date',
178
+ detail: `Last synced ${metadata.last_synced_at}`,
179
+ currentHash: current_hash,
180
+ upstreamHash: upstream_hash,
181
+ };
182
+ }
183
+ export function delete_managed_skill(skill) {
184
+ assert_imported_skill(skill);
185
+ if (!existsSync(skill.baseDir)) {
186
+ throw new Error(`Skill directory no longer exists: ${skill.baseDir}`);
187
+ }
188
+ if (!existsSync(skill.skillPath)) {
189
+ throw new Error(`Skill file no longer exists: ${skill.skillPath}`);
190
+ }
191
+ const skill_dir = resolve(skill.baseDir);
192
+ const skill_file = resolve(skill.skillPath);
193
+ const relative_skill_path = relative(skill_dir, skill_file);
194
+ if (!relative_skill_path ||
195
+ relative_skill_path.startsWith('..') ||
196
+ isAbsolute(relative_skill_path)) {
197
+ throw new Error(`Refusing to delete unsafe skill path: ${skill.baseDir}`);
198
+ }
199
+ rmSync(skill_dir, { recursive: true, force: true });
200
+ return { skillDir: skill_dir };
201
+ }
202
+ export function sync_imported_skill(skill) {
203
+ const metadata = assert_imported_skill(skill);
204
+ if (!existsSync(metadata.upstream_base_dir)) {
205
+ throw new Error(`Upstream source no longer exists: ${metadata.upstream_base_dir}`);
206
+ }
207
+ const current_hash = hash_directory(skill.baseDir);
208
+ if (current_hash !== metadata.imported_hash) {
209
+ throw new Error(`Refusing to sync ${skill.name}; local changes detected in ${skill.baseDir}`);
210
+ }
211
+ const upstream_hash = hash_directory(metadata.upstream_base_dir);
212
+ if (upstream_hash === metadata.upstream_hash) {
213
+ return {
214
+ skillDir: skill.baseDir,
215
+ metadata,
216
+ changed: false,
217
+ };
218
+ }
219
+ replace_directory(metadata.upstream_base_dir, skill.baseDir);
220
+ const imported_hash = hash_directory(skill.baseDir);
221
+ const updated = {
222
+ ...metadata,
223
+ last_synced_at: new Date().toISOString(),
224
+ imported_hash,
225
+ upstream_hash,
226
+ };
227
+ write_metadata(skill.baseDir, updated);
228
+ return {
229
+ skillDir: skill.baseDir,
230
+ metadata: updated,
231
+ changed: true,
232
+ };
233
+ }
234
+ //# sourceMappingURL=importer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importer.js","sourceRoot":"","sources":["../src/importer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { default } from './extension.js';
2
+ export { IMPORT_METADATA_FILE, scan_importable_skills, scan_managed_skills, type DiscoveredSkill, type ImportedSkillMetadata, type InstalledPlugin, type PluginSkillSource, type SkillScope, } from './scanner.js';
3
+ export { delete_managed_skill as delete_imported_skill, get_imported_skill_sync_status, import_external_skill, sync_imported_skill, validate_imported_skill_name, type DeleteSkillResult, type ImportedSkillSyncStatus, type ImportSkillResult, type SyncSkillResult, } from './importer.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default } from './extension.js';
2
+ export { IMPORT_METADATA_FILE, scan_importable_skills, scan_managed_skills, } from './scanner.js';
3
+ export { delete_managed_skill as delete_imported_skill, get_imported_skill_sync_status, import_external_skill, sync_imported_skill, validate_imported_skill_name, } from './importer.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EACN,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,GAMnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACN,oBAAoB,IAAI,qBAAqB,EAC7C,8BAA8B,EAC9B,qBAAqB,EACrB,mBAAmB,EACnB,4BAA4B,GAK5B,MAAM,eAAe,CAAC"}
@@ -0,0 +1,44 @@
1
+ export declare const IMPORT_METADATA_FILE = ".my-pi-source.json";
2
+ export interface InstalledPlugin {
3
+ scope: string;
4
+ installPath: string;
5
+ version: string;
6
+ installedAt?: string;
7
+ lastUpdated?: string;
8
+ gitCommitSha?: string;
9
+ }
10
+ export interface ImportedSkillMetadata {
11
+ version: number;
12
+ source: string;
13
+ upstream_skill_path: string;
14
+ upstream_base_dir: string;
15
+ upstream_install_path?: string;
16
+ upstream_version?: string;
17
+ upstream_git_commit_sha?: string;
18
+ imported_at: string;
19
+ last_synced_at: string;
20
+ imported_hash: string;
21
+ upstream_hash: string;
22
+ }
23
+ export interface PluginSkillSource {
24
+ pluginId: string;
25
+ installPath: string;
26
+ version: string;
27
+ gitCommitSha?: string;
28
+ }
29
+ export type SkillScope = 'global' | 'project' | 'plugin';
30
+ export interface DiscoveredSkill {
31
+ name: string;
32
+ description: string;
33
+ skillPath: string;
34
+ baseDir: string;
35
+ source: string;
36
+ scope: SkillScope;
37
+ kind: 'managed' | 'external';
38
+ plugin?: PluginSkillSource;
39
+ import_meta?: ImportedSkillMetadata;
40
+ }
41
+ export declare function scan_managed_skills(): DiscoveredSkill[];
42
+ export declare function scan_project_skills(cwd?: string): DiscoveredSkill[];
43
+ export declare function scan_importable_skills(): DiscoveredSkill[];
44
+ export declare function scan_all_skills(cwd?: string): DiscoveredSkill[];
@@ -0,0 +1,237 @@
1
+ import { getAgentDir, parseFrontmatter, } from '@earendil-works/pi-coding-agent';
2
+ import { existsSync, globSync, readFileSync, statSync, } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { basename, dirname, join, parse, resolve } from 'node:path';
5
+ export const IMPORT_METADATA_FILE = '.my-pi-source.json';
6
+ function read_installed_plugins() {
7
+ const path = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');
8
+ if (!existsSync(path))
9
+ return null;
10
+ try {
11
+ return JSON.parse(readFileSync(path, 'utf-8'));
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ function parse_skill_md(skill_path) {
18
+ try {
19
+ const content = readFileSync(skill_path, 'utf-8');
20
+ const { frontmatter } = parseFrontmatter(content);
21
+ const description = frontmatter?.description;
22
+ if (!description)
23
+ return null;
24
+ const name = frontmatter?.name || basename(dirname(skill_path));
25
+ return { name, description: description.trim() };
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ function read_import_metadata(base_dir) {
32
+ const metadata_path = join(base_dir, IMPORT_METADATA_FILE);
33
+ if (!existsSync(metadata_path))
34
+ return undefined;
35
+ try {
36
+ return JSON.parse(readFileSync(metadata_path, 'utf-8'));
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ function scan_dir_for_skills(dir, options) {
43
+ if (!existsSync(dir))
44
+ return [];
45
+ const results = [];
46
+ const direct = join(dir, 'SKILL.md');
47
+ const include_direct_root_skill = options.include_direct_root_skill ?? true;
48
+ if (include_direct_root_skill && existsSync(direct)) {
49
+ const parsed = parse_skill_md(direct);
50
+ if (parsed) {
51
+ results.push({
52
+ ...parsed,
53
+ skillPath: direct,
54
+ baseDir: dir,
55
+ source: options.source,
56
+ scope: options.scope,
57
+ kind: options.kind,
58
+ plugin: options.plugin,
59
+ import_meta: options.kind === 'managed'
60
+ ? read_import_metadata(dir)
61
+ : undefined,
62
+ });
63
+ }
64
+ return results;
65
+ }
66
+ try {
67
+ const matches = globSync('*/SKILL.md', { cwd: dir });
68
+ for (const match of matches) {
69
+ const full_path = resolve(dir, match);
70
+ const parsed = parse_skill_md(full_path);
71
+ if (parsed) {
72
+ const base_dir = dirname(full_path);
73
+ results.push({
74
+ ...parsed,
75
+ skillPath: full_path,
76
+ baseDir: base_dir,
77
+ source: options.source,
78
+ scope: options.scope,
79
+ kind: options.kind,
80
+ plugin: options.plugin,
81
+ import_meta: options.kind === 'managed'
82
+ ? read_import_metadata(base_dir)
83
+ : undefined,
84
+ });
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // skip inaccessible dirs
90
+ }
91
+ return results;
92
+ }
93
+ function dedupe_by_skill_path(skills) {
94
+ const seen = new Set();
95
+ const deduped = [];
96
+ for (const skill of skills) {
97
+ if (seen.has(skill.skillPath))
98
+ continue;
99
+ seen.add(skill.skillPath);
100
+ deduped.push(skill);
101
+ }
102
+ return deduped;
103
+ }
104
+ export function scan_managed_skills() {
105
+ const skills = [];
106
+ for (const skill of scan_dir_for_skills(join(homedir(), '.claude', 'skills'), {
107
+ source: 'user-local',
108
+ scope: 'global',
109
+ kind: 'managed',
110
+ })) {
111
+ skills.push(skill);
112
+ }
113
+ for (const skill of scan_dir_for_skills(join(getAgentDir(), 'skills'), {
114
+ source: 'pi-native',
115
+ scope: 'global',
116
+ kind: 'managed',
117
+ include_direct_root_skill: false,
118
+ })) {
119
+ skills.push(skill);
120
+ }
121
+ return dedupe_by_skill_path(skills);
122
+ }
123
+ function parent_dir(path) {
124
+ const parsed = parse(path);
125
+ const parent = dirname(path);
126
+ return parent === path || parent === parsed.root ? null : parent;
127
+ }
128
+ function is_directory(path) {
129
+ try {
130
+ return statSync(path).isDirectory();
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
136
+ function project_roots(cwd) {
137
+ const roots = [];
138
+ let current = resolve(cwd);
139
+ while (true) {
140
+ roots.push(current);
141
+ if (is_directory(join(current, '.git')))
142
+ break;
143
+ const parent = parent_dir(current);
144
+ if (!parent)
145
+ break;
146
+ current = parent;
147
+ }
148
+ return roots;
149
+ }
150
+ export function scan_project_skills(cwd = process.cwd()) {
151
+ const skills = [];
152
+ for (const root of project_roots(cwd)) {
153
+ for (const skill of scan_dir_for_skills(join(root, '.agents'), {
154
+ source: 'project:.agents',
155
+ scope: 'project',
156
+ kind: 'managed',
157
+ include_direct_root_skill: false,
158
+ })) {
159
+ skills.push(skill);
160
+ }
161
+ for (const skill of scan_dir_for_skills(join(root, '.agents', 'skills'), {
162
+ source: 'project:.agents/skills',
163
+ scope: 'project',
164
+ kind: 'managed',
165
+ include_direct_root_skill: false,
166
+ })) {
167
+ skills.push(skill);
168
+ }
169
+ for (const skill of scan_dir_for_skills(join(root, '.pi', 'skills'), {
170
+ source: 'project:.pi/skills',
171
+ scope: 'project',
172
+ kind: 'managed',
173
+ include_direct_root_skill: false,
174
+ })) {
175
+ skills.push(skill);
176
+ }
177
+ }
178
+ return dedupe_by_skill_path(skills);
179
+ }
180
+ export function scan_importable_skills() {
181
+ const skills = [];
182
+ const plugins = read_installed_plugins();
183
+ if (!plugins?.plugins)
184
+ return skills;
185
+ for (const [plugin_id, entries] of Object.entries(plugins.plugins)) {
186
+ const entry = entries[0];
187
+ if (!entry?.installPath || !existsSync(entry.installPath))
188
+ continue;
189
+ const source = `plugin:${plugin_id}`;
190
+ const plugin = {
191
+ pluginId: plugin_id,
192
+ installPath: entry.installPath,
193
+ version: entry.version,
194
+ gitCommitSha: entry.gitCommitSha,
195
+ };
196
+ for (const skill of scan_dir_for_skills(join(entry.installPath, 'skills'), {
197
+ source,
198
+ scope: 'plugin',
199
+ kind: 'external',
200
+ plugin,
201
+ })) {
202
+ skills.push(skill);
203
+ }
204
+ for (const skill of scan_dir_for_skills(join(entry.installPath, '.pi', 'skills'), {
205
+ source,
206
+ scope: 'plugin',
207
+ kind: 'external',
208
+ plugin,
209
+ })) {
210
+ skills.push(skill);
211
+ }
212
+ const direct_root_skill = join(entry.installPath, 'SKILL.md');
213
+ if (existsSync(direct_root_skill)) {
214
+ const parsed = parse_skill_md(direct_root_skill);
215
+ if (parsed) {
216
+ skills.push({
217
+ ...parsed,
218
+ skillPath: direct_root_skill,
219
+ baseDir: entry.installPath,
220
+ source,
221
+ scope: 'plugin',
222
+ kind: 'external',
223
+ plugin,
224
+ });
225
+ }
226
+ }
227
+ }
228
+ return dedupe_by_skill_path(skills);
229
+ }
230
+ export function scan_all_skills(cwd = process.cwd()) {
231
+ return [
232
+ ...scan_managed_skills(),
233
+ ...scan_project_skills(cwd),
234
+ ...scan_importable_skills(),
235
+ ];
236
+ }
237
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@spences10/pi-skill-importer",
3
+ "version": "0.0.2",
4
+ "description": "Pi extension helpers for importing external Agent Skills into Pi-native storage",
5
+ "keywords": [
6
+ "agent-skills",
7
+ "importer",
8
+ "pi",
9
+ "pi-package",
10
+ "skills"
11
+ ],
12
+ "homepage": "https://github.com/spences10/my-pi/tree/main/packages/pi-skill-importer#readme",
13
+ "license": "MIT",
14
+ "author": "Scott Spence <me@scottspence.com>",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/spences10/my-pi.git",
18
+ "directory": "packages/pi-skill-importer"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ }
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "dependencies": {
37
+ "@spences10/pi-tui-modal": "0.0.15"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.8.0",
41
+ "typescript": "^6.0.3",
42
+ "vitest": "^4.1.6"
43
+ },
44
+ "peerDependencies": {
45
+ "@earendil-works/pi-coding-agent": "*",
46
+ "@earendil-works/pi-tui": "*"
47
+ },
48
+ "engines": {
49
+ "node": ">=24.15.0"
50
+ },
51
+ "pi": {
52
+ "extensions": [
53
+ "./dist/index.js"
54
+ ],
55
+ "image": "https://raw.githubusercontent.com/spences10/my-pi/main/assets/pi-package-preview.png"
56
+ },
57
+ "scripts": {
58
+ "build": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run build:self",
59
+ "build:self": "tsc -p tsconfig.build.json",
60
+ "check": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run check:self",
61
+ "check:self": "tsc --noEmit -p tsconfig.json",
62
+ "test": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run test:self",
63
+ "test:self": "vitest run",
64
+ "coverage:self": "vitest run --coverage",
65
+ "coverage": "pnpm --filter \"$npm_package_name^...\" run build:self && pnpm run coverage:self"
66
+ }
67
+ }