@slats/claude-assets-sync 0.0.3 → 0.0.5
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/dist/commands/add.cjs +2 -7
- package/dist/commands/add.mjs +2 -7
- package/dist/commands/index.d.ts +22 -0
- package/dist/commands/remove.cjs +13 -13
- package/dist/commands/remove.mjs +7 -7
- package/dist/commands/types.d.ts +2 -4
- package/dist/commands/update.cjs +178 -0
- package/dist/commands/update.d.ts +13 -0
- package/dist/commands/update.mjs +176 -0
- package/dist/components/add/AddCommand.cjs +11 -0
- package/dist/components/add/AddCommand.mjs +11 -0
- package/dist/components/list/ListCommand.cjs +65 -47
- package/dist/components/list/ListCommand.mjs +66 -48
- package/dist/components/status/StatusDisplay.cjs +4 -3
- package/dist/components/status/StatusDisplay.d.ts +2 -4
- package/dist/components/status/StatusDisplay.mjs +4 -3
- package/dist/components/tree/AssetTreeNode.cjs +21 -4
- package/dist/components/tree/AssetTreeNode.d.ts +1 -1
- package/dist/components/tree/AssetTreeNode.mjs +21 -4
- package/dist/components/tree/TreeSelect.cjs +14 -6
- package/dist/components/tree/TreeSelect.mjs +14 -6
- package/dist/core/assetStructure.d.ts +1 -1
- package/dist/core/cli.cjs +18 -0
- package/dist/core/cli.mjs +18 -0
- package/dist/core/constants.cjs +4 -1
- package/dist/core/constants.d.ts +8 -1
- package/dist/core/constants.mjs +4 -1
- package/dist/core/filesystem.cjs +18 -12
- package/dist/core/filesystem.d.ts +3 -2
- package/dist/core/filesystem.mjs +18 -12
- package/dist/core/github.cjs +31 -3
- package/dist/core/github.d.ts +14 -1
- package/dist/core/github.mjs +31 -4
- package/dist/core/migration.cjs +17 -15
- package/dist/core/migration.mjs +12 -10
- package/dist/core/packageScanner.cjs +110 -29
- package/dist/core/packageScanner.d.ts +6 -1
- package/dist/core/packageScanner.mjs +109 -30
- package/dist/core/sync.cjs +83 -59
- package/dist/core/sync.mjs +55 -31
- package/dist/core/syncMeta.cjs +153 -9
- package/dist/core/syncMeta.d.ts +22 -18
- package/dist/core/syncMeta.mjs +149 -9
- package/dist/utils/nameTransform.cjs +7 -6
- package/dist/utils/nameTransform.d.ts +22 -33
- package/dist/utils/nameTransform.mjs +8 -6
- package/dist/utils/types.d.ts +24 -7
- package/dist/version.cjs +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +2 -2
- package/CHANGELOG.md +0 -189
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var fs = require('node:fs');
|
|
4
4
|
var path = require('node:path');
|
|
5
5
|
var _package = require('../utils/package.cjs');
|
|
6
|
+
var nameTransform = require('../utils/nameTransform.cjs');
|
|
6
7
|
var constants = require('./constants.cjs');
|
|
7
8
|
var github = require('./github.cjs');
|
|
8
9
|
|
|
@@ -72,15 +73,25 @@ async function scanRemoteAssets(packageName, ref) {
|
|
|
72
73
|
throw new Error(`Invalid GitHub repository URL in package ${packageName}`);
|
|
73
74
|
}
|
|
74
75
|
const assetBasePath = pkgInfo.claude.assetPath;
|
|
76
|
+
const tag = ref ?? 'HEAD';
|
|
75
77
|
const trees = [];
|
|
76
78
|
for (const assetType of constants.DEFAULT_ASSET_TYPES) {
|
|
77
79
|
const assetPath = repoInfo.directory
|
|
78
80
|
? `${repoInfo.directory}/${assetBasePath}/${assetType}`
|
|
79
81
|
: `${assetBasePath}/${assetType}`;
|
|
80
82
|
try {
|
|
81
|
-
const entries = await github.fetchDirectoryContents(repoInfo, assetPath,
|
|
83
|
+
const entries = await github.fetchDirectoryContents(repoInfo, assetPath, tag);
|
|
82
84
|
if (entries && entries.length > 0) {
|
|
83
|
-
const
|
|
85
|
+
const dirContentsMap = new Map();
|
|
86
|
+
for (const entry of entries) {
|
|
87
|
+
if (entry.type === 'dir') {
|
|
88
|
+
const dirEntries = await github.fetchDirectoryContents(repoInfo, `${assetPath}/${entry.name}`, tag);
|
|
89
|
+
if (dirEntries) {
|
|
90
|
+
dirContentsMap.set(entry.name, dirEntries);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const tree = buildTreeFromGitHubEntries(assetType, entries, assetType, dirContentsMap);
|
|
84
95
|
if (tree.children && tree.children.length > 0) {
|
|
85
96
|
trees.push(tree);
|
|
86
97
|
}
|
|
@@ -92,6 +103,26 @@ async function scanRemoteAssets(packageName, ref) {
|
|
|
92
103
|
}
|
|
93
104
|
return trees;
|
|
94
105
|
}
|
|
106
|
+
function scanDirectoryRecursive(dirPath, prefix) {
|
|
107
|
+
const results = [];
|
|
108
|
+
try {
|
|
109
|
+
const entries = fs.readdirSync(dirPath);
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
const fullPath = path.join(dirPath, entry);
|
|
112
|
+
const relativePath = prefix ? `${prefix}/${entry}` : entry;
|
|
113
|
+
const stat = fs.statSync(fullPath);
|
|
114
|
+
if (stat.isDirectory()) {
|
|
115
|
+
results.push(...scanDirectoryRecursive(fullPath, relativePath));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
results.push(relativePath);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
95
126
|
function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
96
127
|
const entries = fs.readdirSync(dirPath);
|
|
97
128
|
const children = [];
|
|
@@ -100,13 +131,26 @@ function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
|
100
131
|
const stat = fs.statSync(fullPath);
|
|
101
132
|
const relativePath = path.join(basePath, entry);
|
|
102
133
|
if (stat.isDirectory()) {
|
|
103
|
-
const isSkill = fs.existsSync(path.join(fullPath, '
|
|
134
|
+
const isSkill = fs.existsSync(path.join(fullPath, 'SKILL.md')) ||
|
|
135
|
+
fs.existsSync(path.join(fullPath, 'Skill.md'));
|
|
104
136
|
if (isSkill) {
|
|
137
|
+
const internalFiles = scanDirectoryRecursive(fullPath, '');
|
|
138
|
+
const internalChildren = internalFiles.map((f) => ({
|
|
139
|
+
id: `${relativePath}/${f}`,
|
|
140
|
+
label: f,
|
|
141
|
+
path: `${relativePath}/${f}`,
|
|
142
|
+
type: 'file',
|
|
143
|
+
selected: true,
|
|
144
|
+
expanded: false,
|
|
145
|
+
disabled: true,
|
|
146
|
+
}));
|
|
105
147
|
children.push({
|
|
106
148
|
id: relativePath,
|
|
107
149
|
label: entry,
|
|
108
150
|
path: relativePath,
|
|
109
151
|
type: 'skill-directory',
|
|
152
|
+
children: internalChildren,
|
|
153
|
+
viewOnly: true,
|
|
110
154
|
selected: true,
|
|
111
155
|
expanded: false,
|
|
112
156
|
});
|
|
@@ -139,36 +183,50 @@ function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
|
139
183
|
expanded: true,
|
|
140
184
|
};
|
|
141
185
|
}
|
|
142
|
-
function buildTreeFromGitHubEntries(label, entries, basePath) {
|
|
186
|
+
function buildTreeFromGitHubEntries(label, entries, basePath, dirContentsMap) {
|
|
143
187
|
const children = [];
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
if (items.length === 1 && items[0].type === 'file') {
|
|
147
|
-
const filePath = items[0].path;
|
|
188
|
+
for (const entry of entries) {
|
|
189
|
+
if (entry.type === 'file') {
|
|
148
190
|
children.push({
|
|
149
|
-
id:
|
|
150
|
-
label: name,
|
|
151
|
-
path:
|
|
191
|
+
id: entry.path,
|
|
192
|
+
label: entry.name,
|
|
193
|
+
path: entry.path,
|
|
152
194
|
type: 'file',
|
|
153
195
|
selected: true,
|
|
154
196
|
expanded: false,
|
|
155
197
|
});
|
|
156
198
|
}
|
|
157
|
-
else {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
199
|
+
else if (entry.type === 'dir') {
|
|
200
|
+
const dirEntries = dirContentsMap?.get(entry.name);
|
|
201
|
+
const hasSkillMd = dirEntries
|
|
202
|
+
? isDirectorySkill(dirEntries)
|
|
203
|
+
: false;
|
|
204
|
+
if (hasSkillMd) {
|
|
205
|
+
const skillPath = `${basePath}/${entry.name}`;
|
|
206
|
+
const internalChildren = dirEntries
|
|
207
|
+
? dirEntries.map((de) => ({
|
|
208
|
+
id: `${skillPath}/${de.name}`,
|
|
209
|
+
label: de.name,
|
|
210
|
+
path: `${skillPath}/${de.name}`,
|
|
211
|
+
type: 'file',
|
|
212
|
+
selected: true,
|
|
213
|
+
expanded: false,
|
|
214
|
+
disabled: true,
|
|
215
|
+
}))
|
|
216
|
+
: [];
|
|
161
217
|
children.push({
|
|
162
218
|
id: skillPath,
|
|
163
|
-
label: name,
|
|
219
|
+
label: entry.name,
|
|
164
220
|
path: skillPath,
|
|
165
221
|
type: 'skill-directory',
|
|
222
|
+
children: internalChildren,
|
|
223
|
+
viewOnly: true,
|
|
166
224
|
selected: true,
|
|
167
225
|
expanded: false,
|
|
168
226
|
});
|
|
169
227
|
}
|
|
170
|
-
else {
|
|
171
|
-
const subTree = buildTreeFromGitHubEntries(name,
|
|
228
|
+
else if (dirEntries && dirEntries.length > 0) {
|
|
229
|
+
const subTree = buildTreeFromGitHubEntries(entry.name, dirEntries, `${basePath}/${entry.name}`);
|
|
172
230
|
if (subTree.children && subTree.children.length > 0) {
|
|
173
231
|
children.push(subTree);
|
|
174
232
|
}
|
|
@@ -185,17 +243,9 @@ function buildTreeFromGitHubEntries(label, entries, basePath) {
|
|
|
185
243
|
expanded: true,
|
|
186
244
|
};
|
|
187
245
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const parts = entry.path.split('/');
|
|
192
|
-
const topLevel = parts[parts.length - (entry.type === 'file' ? 1 : 0)];
|
|
193
|
-
if (!groups[topLevel]) {
|
|
194
|
-
groups[topLevel] = [];
|
|
195
|
-
}
|
|
196
|
-
groups[topLevel].push(entry);
|
|
197
|
-
}
|
|
198
|
-
return groups;
|
|
246
|
+
function isDirectorySkill(entries) {
|
|
247
|
+
return entries.some((entry) => entry.type === 'file' &&
|
|
248
|
+
(entry.name === 'SKILL.md' || entry.name === 'Skill.md'));
|
|
199
249
|
}
|
|
200
250
|
function findLocalPackage(packageName, cwd) {
|
|
201
251
|
const monorepoRoot = findMonorepoRoot(cwd);
|
|
@@ -255,5 +305,36 @@ function searchPackagesRecursively(dir, packageName) {
|
|
|
255
305
|
}
|
|
256
306
|
return null;
|
|
257
307
|
}
|
|
308
|
+
function buildSkillUnitsFromTree(tree, prefix) {
|
|
309
|
+
if (!tree.children)
|
|
310
|
+
return [];
|
|
311
|
+
const units = [];
|
|
312
|
+
for (const child of tree.children) {
|
|
313
|
+
if (child.type === 'skill-directory') {
|
|
314
|
+
const internalFiles = child.children
|
|
315
|
+
? child.children.map((c) => c.label)
|
|
316
|
+
: [];
|
|
317
|
+
units.push({
|
|
318
|
+
name: child.label,
|
|
319
|
+
isDirectory: true,
|
|
320
|
+
transformed: nameTransform.toFlatFileName(prefix, child.label),
|
|
321
|
+
internalFiles,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
else if (child.type === 'file') {
|
|
325
|
+
units.push({
|
|
326
|
+
name: child.label,
|
|
327
|
+
isDirectory: false,
|
|
328
|
+
transformed: nameTransform.toFlatFileName(prefix, child.label),
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
else if (child.type === 'directory') {
|
|
332
|
+
units.push(...buildSkillUnitsFromTree(child, prefix));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return units;
|
|
336
|
+
}
|
|
258
337
|
|
|
338
|
+
exports.buildSkillUnitsFromTree = buildSkillUnitsFromTree;
|
|
339
|
+
exports.isDirectorySkill = isDirectorySkill;
|
|
259
340
|
exports.scanPackageAssets = scanPackageAssets;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GitHubEntry, TreeNode } from '../utils/types.js';
|
|
1
|
+
import type { GitHubEntry, SkillUnit, TreeNode } from '../utils/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Scan package assets from local workspace or GitHub
|
|
4
4
|
*
|
|
@@ -15,3 +15,8 @@ export declare function scanPackageAssets(packageName: string, options: {
|
|
|
15
15
|
* Check if entries represent a directory-based skill
|
|
16
16
|
*/
|
|
17
17
|
export declare function isDirectorySkill(entries: GitHubEntry[]): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Convert a TreeNode asset-type subtree into SkillUnit[] for writing to meta.
|
|
20
|
+
* Used by both `add` and `list` commands when saving.
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildSkillUnitsFromTree(tree: TreeNode, prefix: string): SkillUnit[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { parseGitHubRepo } from '../utils/package.mjs';
|
|
4
|
+
import { toFlatFileName } from '../utils/nameTransform.mjs';
|
|
4
5
|
import { DEFAULT_ASSET_TYPES } from './constants.mjs';
|
|
5
6
|
import { fetchDirectoryContents } from './github.mjs';
|
|
6
7
|
|
|
@@ -70,15 +71,25 @@ async function scanRemoteAssets(packageName, ref) {
|
|
|
70
71
|
throw new Error(`Invalid GitHub repository URL in package ${packageName}`);
|
|
71
72
|
}
|
|
72
73
|
const assetBasePath = pkgInfo.claude.assetPath;
|
|
74
|
+
const tag = ref ?? 'HEAD';
|
|
73
75
|
const trees = [];
|
|
74
76
|
for (const assetType of DEFAULT_ASSET_TYPES) {
|
|
75
77
|
const assetPath = repoInfo.directory
|
|
76
78
|
? `${repoInfo.directory}/${assetBasePath}/${assetType}`
|
|
77
79
|
: `${assetBasePath}/${assetType}`;
|
|
78
80
|
try {
|
|
79
|
-
const entries = await fetchDirectoryContents(repoInfo, assetPath,
|
|
81
|
+
const entries = await fetchDirectoryContents(repoInfo, assetPath, tag);
|
|
80
82
|
if (entries && entries.length > 0) {
|
|
81
|
-
const
|
|
83
|
+
const dirContentsMap = new Map();
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (entry.type === 'dir') {
|
|
86
|
+
const dirEntries = await fetchDirectoryContents(repoInfo, `${assetPath}/${entry.name}`, tag);
|
|
87
|
+
if (dirEntries) {
|
|
88
|
+
dirContentsMap.set(entry.name, dirEntries);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const tree = buildTreeFromGitHubEntries(assetType, entries, assetType, dirContentsMap);
|
|
82
93
|
if (tree.children && tree.children.length > 0) {
|
|
83
94
|
trees.push(tree);
|
|
84
95
|
}
|
|
@@ -90,6 +101,26 @@ async function scanRemoteAssets(packageName, ref) {
|
|
|
90
101
|
}
|
|
91
102
|
return trees;
|
|
92
103
|
}
|
|
104
|
+
function scanDirectoryRecursive(dirPath, prefix) {
|
|
105
|
+
const results = [];
|
|
106
|
+
try {
|
|
107
|
+
const entries = readdirSync(dirPath);
|
|
108
|
+
for (const entry of entries) {
|
|
109
|
+
const fullPath = join(dirPath, entry);
|
|
110
|
+
const relativePath = prefix ? `${prefix}/${entry}` : entry;
|
|
111
|
+
const stat = statSync(fullPath);
|
|
112
|
+
if (stat.isDirectory()) {
|
|
113
|
+
results.push(...scanDirectoryRecursive(fullPath, relativePath));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
results.push(relativePath);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
}
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
93
124
|
function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
94
125
|
const entries = readdirSync(dirPath);
|
|
95
126
|
const children = [];
|
|
@@ -98,13 +129,26 @@ function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
|
98
129
|
const stat = statSync(fullPath);
|
|
99
130
|
const relativePath = join(basePath, entry);
|
|
100
131
|
if (stat.isDirectory()) {
|
|
101
|
-
const isSkill = existsSync(join(fullPath, '
|
|
132
|
+
const isSkill = existsSync(join(fullPath, 'SKILL.md')) ||
|
|
133
|
+
existsSync(join(fullPath, 'Skill.md'));
|
|
102
134
|
if (isSkill) {
|
|
135
|
+
const internalFiles = scanDirectoryRecursive(fullPath, '');
|
|
136
|
+
const internalChildren = internalFiles.map((f) => ({
|
|
137
|
+
id: `${relativePath}/${f}`,
|
|
138
|
+
label: f,
|
|
139
|
+
path: `${relativePath}/${f}`,
|
|
140
|
+
type: 'file',
|
|
141
|
+
selected: true,
|
|
142
|
+
expanded: false,
|
|
143
|
+
disabled: true,
|
|
144
|
+
}));
|
|
103
145
|
children.push({
|
|
104
146
|
id: relativePath,
|
|
105
147
|
label: entry,
|
|
106
148
|
path: relativePath,
|
|
107
149
|
type: 'skill-directory',
|
|
150
|
+
children: internalChildren,
|
|
151
|
+
viewOnly: true,
|
|
108
152
|
selected: true,
|
|
109
153
|
expanded: false,
|
|
110
154
|
});
|
|
@@ -137,36 +181,50 @@ function buildTreeFromLocalDir(label, dirPath, basePath) {
|
|
|
137
181
|
expanded: true,
|
|
138
182
|
};
|
|
139
183
|
}
|
|
140
|
-
function buildTreeFromGitHubEntries(label, entries, basePath) {
|
|
184
|
+
function buildTreeFromGitHubEntries(label, entries, basePath, dirContentsMap) {
|
|
141
185
|
const children = [];
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
if (items.length === 1 && items[0].type === 'file') {
|
|
145
|
-
const filePath = items[0].path;
|
|
186
|
+
for (const entry of entries) {
|
|
187
|
+
if (entry.type === 'file') {
|
|
146
188
|
children.push({
|
|
147
|
-
id:
|
|
148
|
-
label: name,
|
|
149
|
-
path:
|
|
189
|
+
id: entry.path,
|
|
190
|
+
label: entry.name,
|
|
191
|
+
path: entry.path,
|
|
150
192
|
type: 'file',
|
|
151
193
|
selected: true,
|
|
152
194
|
expanded: false,
|
|
153
195
|
});
|
|
154
196
|
}
|
|
155
|
-
else {
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
197
|
+
else if (entry.type === 'dir') {
|
|
198
|
+
const dirEntries = dirContentsMap?.get(entry.name);
|
|
199
|
+
const hasSkillMd = dirEntries
|
|
200
|
+
? isDirectorySkill(dirEntries)
|
|
201
|
+
: false;
|
|
202
|
+
if (hasSkillMd) {
|
|
203
|
+
const skillPath = `${basePath}/${entry.name}`;
|
|
204
|
+
const internalChildren = dirEntries
|
|
205
|
+
? dirEntries.map((de) => ({
|
|
206
|
+
id: `${skillPath}/${de.name}`,
|
|
207
|
+
label: de.name,
|
|
208
|
+
path: `${skillPath}/${de.name}`,
|
|
209
|
+
type: 'file',
|
|
210
|
+
selected: true,
|
|
211
|
+
expanded: false,
|
|
212
|
+
disabled: true,
|
|
213
|
+
}))
|
|
214
|
+
: [];
|
|
159
215
|
children.push({
|
|
160
216
|
id: skillPath,
|
|
161
|
-
label: name,
|
|
217
|
+
label: entry.name,
|
|
162
218
|
path: skillPath,
|
|
163
219
|
type: 'skill-directory',
|
|
220
|
+
children: internalChildren,
|
|
221
|
+
viewOnly: true,
|
|
164
222
|
selected: true,
|
|
165
223
|
expanded: false,
|
|
166
224
|
});
|
|
167
225
|
}
|
|
168
|
-
else {
|
|
169
|
-
const subTree = buildTreeFromGitHubEntries(name,
|
|
226
|
+
else if (dirEntries && dirEntries.length > 0) {
|
|
227
|
+
const subTree = buildTreeFromGitHubEntries(entry.name, dirEntries, `${basePath}/${entry.name}`);
|
|
170
228
|
if (subTree.children && subTree.children.length > 0) {
|
|
171
229
|
children.push(subTree);
|
|
172
230
|
}
|
|
@@ -183,17 +241,9 @@ function buildTreeFromGitHubEntries(label, entries, basePath) {
|
|
|
183
241
|
expanded: true,
|
|
184
242
|
};
|
|
185
243
|
}
|
|
186
|
-
function
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const parts = entry.path.split('/');
|
|
190
|
-
const topLevel = parts[parts.length - (entry.type === 'file' ? 1 : 0)];
|
|
191
|
-
if (!groups[topLevel]) {
|
|
192
|
-
groups[topLevel] = [];
|
|
193
|
-
}
|
|
194
|
-
groups[topLevel].push(entry);
|
|
195
|
-
}
|
|
196
|
-
return groups;
|
|
244
|
+
function isDirectorySkill(entries) {
|
|
245
|
+
return entries.some((entry) => entry.type === 'file' &&
|
|
246
|
+
(entry.name === 'SKILL.md' || entry.name === 'Skill.md'));
|
|
197
247
|
}
|
|
198
248
|
function findLocalPackage(packageName, cwd) {
|
|
199
249
|
const monorepoRoot = findMonorepoRoot(cwd);
|
|
@@ -253,5 +303,34 @@ function searchPackagesRecursively(dir, packageName) {
|
|
|
253
303
|
}
|
|
254
304
|
return null;
|
|
255
305
|
}
|
|
306
|
+
function buildSkillUnitsFromTree(tree, prefix) {
|
|
307
|
+
if (!tree.children)
|
|
308
|
+
return [];
|
|
309
|
+
const units = [];
|
|
310
|
+
for (const child of tree.children) {
|
|
311
|
+
if (child.type === 'skill-directory') {
|
|
312
|
+
const internalFiles = child.children
|
|
313
|
+
? child.children.map((c) => c.label)
|
|
314
|
+
: [];
|
|
315
|
+
units.push({
|
|
316
|
+
name: child.label,
|
|
317
|
+
isDirectory: true,
|
|
318
|
+
transformed: toFlatFileName(prefix, child.label),
|
|
319
|
+
internalFiles,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
else if (child.type === 'file') {
|
|
323
|
+
units.push({
|
|
324
|
+
name: child.label,
|
|
325
|
+
isDirectory: false,
|
|
326
|
+
transformed: toFlatFileName(prefix, child.label),
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else if (child.type === 'directory') {
|
|
330
|
+
units.push(...buildSkillUnitsFromTree(child, prefix));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return units;
|
|
334
|
+
}
|
|
256
335
|
|
|
257
|
-
export { scanPackageAssets };
|
|
336
|
+
export { buildSkillUnitsFromTree, isDirectorySkill, scanPackageAssets };
|