agent-skills-standard 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,6 +71,30 @@ npx agent-skills-standard sync
71
71
 
72
72
  ---
73
73
 
74
+ ## ⚙️ Configuration (`.skillsrc`)
75
+
76
+ The `.skillsrc` file allows you to customize how skills are synced to your project.
77
+
78
+ ```yaml
79
+ registry: https://github.com/HoangNguyen0403/agent-skills-standard
80
+ agents: [cursor, copilot]
81
+ skills:
82
+ flutter:
83
+ ref: flutter-v1.1.0
84
+ # 🚫 Exclude specific sub-skills from being synced
85
+ exclude: ['getx-navigation']
86
+ # 🔒 Protect local modifications from being overwritten
87
+ custom_overrides: ['bloc-state-management']
88
+ ```
89
+
90
+ ### Key Options
91
+
92
+ - **`exclude`**: A list of skill IDs to skip during synchronization. Useful if you want the main framework guidelines but use a different library for a specific sub-task (e.g., excluding `auto-route` if you use `go_router`).
93
+ - **`custom_overrides`**: A list of skill IDs that the CLI should **never** overwrite. Use this when you have modified a standard skill locally to fit your project's unique needs. The CLI will detect these and preserve your local version.
94
+ - **`ref`**: Specify a specific version or tag of the skills from the registry.
95
+
96
+ ---
97
+
74
98
  ## ✨ Key Features
75
99
 
76
100
  - **🎯 Efficiency First**: Uses a "Search-on-Demand" pattern that only loads information when the AI needs it, saving its "brain power" for your code.
@@ -1,3 +1,6 @@
1
1
  export declare class InitCommand {
2
+ private detectionService;
3
+ private registryService;
4
+ private configService;
2
5
  run(): Promise<void>;
3
6
  }
@@ -7,103 +7,33 @@ exports.InitCommand = void 0;
7
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const inquirer_1 = __importDefault(require("inquirer"));
9
9
  const js_yaml_1 = __importDefault(require("js-yaml"));
10
- const node_fetch_1 = __importDefault(require("node-fetch"));
11
10
  const path_1 = __importDefault(require("path"));
12
11
  const picocolors_1 = __importDefault(require("picocolors"));
13
12
  const constants_1 = require("../constants");
14
- const github_1 = require("../utils/github");
13
+ const ConfigService_1 = require("../services/ConfigService");
14
+ const DetectionService_1 = require("../services/DetectionService");
15
+ const RegistryService_1 = require("../services/RegistryService");
15
16
  const project_1 = require("../utils/project");
16
17
  class InitCommand {
18
+ constructor() {
19
+ this.detectionService = new DetectionService_1.DetectionService();
20
+ this.registryService = new RegistryService_1.RegistryService();
21
+ this.configService = new ConfigService_1.ConfigService();
22
+ }
17
23
  async run() {
18
24
  const configPath = path_1.default.join(process.cwd(), '.skillsrc');
19
- // Load package.json for dependency checks (for framework detection)
20
- const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
21
- let packageDeps = {};
22
- if (await fs_extra_1.default.pathExists(packageJsonPath)) {
23
- try {
24
- const pkg = await fs_extra_1.default.readJson(packageJsonPath);
25
- packageDeps = { ...pkg.dependencies, ...pkg.devDependencies };
26
- }
27
- catch (e) {
28
- console.error(picocolors_1.default.red(`❌ Failed to read package.json: ${e instanceof Error ? e.message : String(e)}`));
29
- }
30
- }
31
- // Project detection
32
- const detectionResults = {};
33
- for (const framework of constants_1.SUPPORTED_FRAMEWORKS) {
34
- let detected = false;
35
- // 1. Check characteristic files
36
- for (const file of framework.detectionFiles) {
37
- if (await fs_extra_1.default.pathExists(file)) {
38
- detected = true;
39
- break;
40
- }
41
- }
42
- // 2. Check dependencies (if not yet detected)
43
- if (!detected &&
44
- framework.detectionDependencies &&
45
- framework.detectionDependencies.length > 0) {
46
- detected = framework.detectionDependencies.some((dep) => Object.prototype.hasOwnProperty.call(packageDeps, dep));
47
- }
48
- detectionResults[framework.id] = detected;
49
- }
50
- // Agent detection
51
- const agentDetection = {};
52
- for (const agent of constants_1.SUPPORTED_AGENTS) {
53
- let detected = false;
54
- for (const file of agent.detectionFiles) {
55
- if (await fs_extra_1.default.pathExists(file)) {
56
- detected = true;
57
- break;
58
- }
59
- }
60
- agentDetection[agent.id] = detected;
61
- }
25
+ const detectionResults = await this.detectionService.detectFrameworks();
26
+ const agentDetection = await this.detectionService.detectAgents();
62
27
  const anyAgentDetected = Object.values(agentDetection).some((d) => d);
63
- // Helper to determine if an agent should be pre-selected
64
28
  const shouldCheck = (id) => anyAgentDetected ? agentDetection[id] : true;
65
- // Supported categories are now determined by the registry contents if possible
66
- // Default to a sane list if registry is unreachable
67
- let supportedCategories = ['flutter', 'dart'];
68
- let metadata = {};
69
- // Attempt to discover available categories and registry metadata from the canonical registry
70
- try {
71
- const defaultRegistry = 'https://github.com/HoangNguyen0403/agent-skills-standard';
72
- const parsed = (0, github_1.parseRegistryUrl)(defaultRegistry);
73
- if (parsed) {
74
- const treeResult = await (0, github_1.fetchRepoTree)(parsed.owner, parsed.repo);
75
- if (treeResult && Array.isArray(treeResult.data.tree)) {
76
- const allFiles = treeResult.data.tree || [];
77
- const categories = new Set();
78
- allFiles.forEach((f) => {
79
- if (f.path.startsWith('skills/') && f.type === 'tree') {
80
- const parts = f.path.split('/');
81
- if (parts.length === 2)
82
- categories.add(parts[1]);
83
- }
84
- });
85
- if (categories.size > 0)
86
- supportedCategories = Array.from(categories);
87
- // Try to fetch metadata.json at the resolved branch
88
- const metaUrl = `https://raw.githubusercontent.com/${parsed.owner}/${parsed.repo}/${treeResult.branch}/skills/metadata.json`;
89
- const metaRes = await (0, node_fetch_1.default)(metaUrl);
90
- if (metaRes.ok) {
91
- metadata = (await metaRes.json());
92
- }
93
- }
94
- }
95
- }
96
- catch (e) {
97
- const msg = e instanceof Error ? e.message : String(e);
98
- console.error(picocolors_1.default.red(`❌ Failed to fetch registry metadata or tree: ${msg}`));
99
- }
100
- const choices = constants_1.SUPPORTED_FRAMEWORKS.map((f) => {
101
- const isSupported = supportedCategories.includes(f.id);
102
- return {
103
- name: isSupported ? f.name : `${f.name} (Coming Soon)`,
104
- value: f.id,
105
- };
106
- });
29
+ const defaultRegistry = 'https://github.com/HoangNguyen0403/agent-skills-standard';
30
+ const { categories: supportedCategories, metadata } = await this.registryService.discoverRegistry(defaultRegistry);
31
+ const choices = constants_1.SUPPORTED_FRAMEWORKS.map((f) => ({
32
+ name: supportedCategories.includes(f.id)
33
+ ? f.name
34
+ : `${f.name} (Coming Soon)`,
35
+ value: f.id,
36
+ }));
107
37
  if (await fs_extra_1.default.pathExists(configPath)) {
108
38
  const { overwrite } = await inquirer_1.default.prompt([
109
39
  {
@@ -141,75 +71,20 @@ class InitCommand {
141
71
  type: 'input',
142
72
  name: 'registry',
143
73
  message: 'Skills Registry URL:',
144
- default: 'https://github.com/HoangNguyen0403/agent-skills-standard',
74
+ default: defaultRegistry,
145
75
  },
146
76
  ]);
147
77
  const framework = answers.framework;
148
- const selectedFramework = constants_1.SUPPORTED_FRAMEWORKS.find((f) => f.id === framework);
149
- const isSupported = supportedCategories.includes(framework);
150
- if (!isSupported) {
78
+ if (!supportedCategories.includes(framework)) {
151
79
  console.log(picocolors_1.default.yellow(`\nNotice: Skills for ${framework} are not yet strictly defined and will be added soon.`));
152
80
  console.log(picocolors_1.default.gray('The CLI will still generate rule files with global standards.\n'));
153
81
  }
154
- const neededSkills = new Set();
155
- neededSkills.add(framework);
156
- if (selectedFramework) {
157
- selectedFramework.languages.forEach((l) => neededSkills.add(l));
158
- }
159
- // Special case: Next.js and React Native imply React
160
- if (framework === constants_1.Framework.NextJS || framework === constants_1.Framework.ReactNative) {
161
- neededSkills.add(constants_1.Framework.React);
162
- }
163
- // Add framework-specific skills from the registry to potential skills
164
- const frameworkSkills = constants_1.SKILL_DETECTION_REGISTRY[framework] || [];
165
- frameworkSkills.forEach((s) => neededSkills.add(s.id));
166
- const config = {
167
- registry: answers.registry,
168
- agents: answers.agents,
169
- skills: {},
170
- custom_overrides: [],
171
- };
172
- // Initialize all potential skills from the registry folders we know
173
- // This will be expanded as more frameworks are added to the repo
174
- const allKnownCategories = [
175
- ...constants_1.SUPPORTED_FRAMEWORKS.map((f) => f.id),
176
- ...constants_1.SUPPORTED_FRAMEWORKS.flatMap((f) => f.languages),
177
- ...Object.values(constants_1.SKILL_DETECTION_REGISTRY).flatMap((skills) => skills.map((s) => s.id)),
178
- ];
179
- for (const skill of [...new Set(allKnownCategories)]) {
180
- if (neededSkills.has(skill)) {
181
- const skillMeta = metadata.categories?.[skill];
182
- let refStr;
183
- if (skillMeta?.version && skillMeta?.tag_prefix) {
184
- refStr = `${skillMeta.tag_prefix}${skillMeta.version}`;
185
- }
186
- config.skills[skill] = {
187
- enabled: true,
188
- ref: refStr,
189
- };
190
- }
191
- }
192
- // Detect common framework skills and disable them if not used
82
+ const config = this.configService.buildInitialConfig(framework, answers.agents, answers.registry, metadata);
193
83
  const projectDeps = await (0, project_1.buildProjectDeps)();
194
- for (const skill of frameworkSkills) {
195
- const entry = config.skills[skill.id];
196
- if (!entry)
197
- continue;
198
- // Only rely on declared dependencies for detection.
199
- const used = skill.packages.some((p) => projectDeps.has(p));
200
- // If not used, add to parent framework's exclude list so users
201
- // see which sub-skills were disabled by detection and can opt-in.
202
- if (!used) {
203
- const parent = config.skills[framework] || { enabled: true };
204
- const excludes = parent.exclude ? [...parent.exclude] : [];
205
- if (!excludes.includes(skill.id))
206
- excludes.push(skill.id);
207
- parent.exclude = excludes;
208
- config.skills[framework] = parent;
209
- }
210
- }
84
+ this.configService.applyDependencyExclusions(config, framework, projectDeps);
211
85
  const commentHeader = `# Auto-detected configuration generated by agent-skills-standard init
212
86
  #
87
+ # Presence in 'skills' list = Active. To disable a skill, remove it from the list.
213
88
  # 'exclude': IDs of sub-skills to skip during sync (auto-populated with undetected skills).
214
89
  # 'custom_overrides': IDs of skills to PROTECT. Use this if you have modified a standard
215
90
  # skill locally and don't want the CLI to overwrite it.
@@ -219,9 +94,6 @@ class InitCommand {
219
94
  await fs_extra_1.default.writeFile(configPath, commentHeader + js_yaml_1.default.dump(config));
220
95
  console.log(picocolors_1.default.green('\n✅ Initialized .skillsrc with your preferences!'));
221
96
  console.log(picocolors_1.default.gray(` Selected framework: ${framework}`));
222
- console.log(picocolors_1.default.gray(` Auto-enabled languages: ${Array.from(neededSkills)
223
- .filter((s) => s !== framework)
224
- .join(', ') || 'none'}`));
225
97
  console.log(picocolors_1.default.cyan('\nNext step: Run `agent-skills-standard sync` to generate rule files.'));
226
98
  }
227
99
  }
@@ -27,9 +27,7 @@ class SyncCommand {
27
27
  // 2. Check for skill updates before syncing
28
28
  config = await this.checkForUpdates(config, configPath);
29
29
  console.log(picocolors_1.default.cyan(`🚀 Syncing skills from ${config.registry}...`));
30
- const enabledCategories = Object.entries(config.skills)
31
- .filter(([, value]) => value.enabled)
32
- .map(([key]) => key);
30
+ const enabledCategories = Object.keys(config.skills);
33
31
  const skills = await this.assembleFromRemote(enabledCategories, config);
34
32
  await this.writeToTargets(skills, config);
35
33
  console.log(picocolors_1.default.green('✅ All skills synced successfully!'));
@@ -83,8 +81,6 @@ class SyncCommand {
83
81
  const remoteMeta = (await metaRes.json());
84
82
  const updates = [];
85
83
  for (const [cat, catConfig] of Object.entries(config.skills)) {
86
- if (!catConfig.enabled)
87
- continue;
88
84
  const remoteCat = remoteMeta.categories?.[cat];
89
85
  if (!remoteCat || !remoteCat.version || !remoteCat.tag_prefix)
90
86
  continue;
@@ -7,7 +7,8 @@ export declare enum Agent {
7
7
  OpenAI = "openai",
8
8
  OpenCode = "opencode",
9
9
  Gemini = "gemini",
10
- Roo = "roo"
10
+ Roo = "roo",
11
+ Windsurf = "windsurf"
11
12
  }
12
13
  export declare enum Framework {
13
14
  Flutter = "flutter",
@@ -18,6 +19,7 @@ export declare enum Framework {
18
19
  ReactNative = "react-native",
19
20
  Angular = "angular"
20
21
  }
22
+ export declare const UNIVERSAL_SKILLS: string[];
21
23
  export interface AgentDefinition {
22
24
  id: Agent;
23
25
  name: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SKILL_DETECTION_REGISTRY = exports.SUPPORTED_FRAMEWORKS = exports.SUPPORTED_AGENTS = exports.getFrameworkDefinition = exports.getAgentDefinition = exports.Framework = exports.Agent = void 0;
3
+ exports.SKILL_DETECTION_REGISTRY = exports.SUPPORTED_FRAMEWORKS = exports.SUPPORTED_AGENTS = exports.getFrameworkDefinition = exports.getAgentDefinition = exports.UNIVERSAL_SKILLS = exports.Framework = exports.Agent = void 0;
4
4
  var Agent;
5
5
  (function (Agent) {
6
6
  Agent["Cursor"] = "cursor";
@@ -12,6 +12,7 @@ var Agent;
12
12
  Agent["OpenCode"] = "opencode";
13
13
  Agent["Gemini"] = "gemini";
14
14
  Agent["Roo"] = "roo";
15
+ Agent["Windsurf"] = "windsurf";
15
16
  })(Agent || (exports.Agent = Agent = {}));
16
17
  var Framework;
17
18
  (function (Framework) {
@@ -23,6 +24,7 @@ var Framework;
23
24
  Framework["ReactNative"] = "react-native";
24
25
  Framework["Angular"] = "angular";
25
26
  })(Framework || (exports.Framework = Framework = {}));
27
+ exports.UNIVERSAL_SKILLS = ['common'];
26
28
  const getAgentDefinition = (id) => {
27
29
  switch (id) {
28
30
  case Agent.Cursor:
@@ -88,6 +90,13 @@ const getAgentDefinition = (id) => {
88
90
  path: '.roo/skills',
89
91
  detectionFiles: ['.roo'],
90
92
  };
93
+ case Agent.Windsurf:
94
+ return {
95
+ id,
96
+ name: 'Windsurf',
97
+ path: '.windsurf/skills',
98
+ detectionFiles: ['.windsurf', '.windsurfrules'],
99
+ };
91
100
  }
92
101
  };
93
102
  exports.getAgentDefinition = getAgentDefinition;
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@ const sync_1 = require("./commands/sync");
8
8
  const program = new commander_1.Command();
9
9
  program
10
10
  .name('agent-skills-standard')
11
- .description('A CLI to manage and sync AI agent skills for Cursor, Claude, Copilot, and more.')
12
- .version('1.1.2');
11
+ .description('A CLI to manage and sync AI agent skills for Cursor, Claude, Copilot, Windsurf, and more.')
12
+ .version('1.2.0');
13
13
  program
14
14
  .command('init')
15
15
  .description('Initialize a .skillsrc configuration file interactively')
@@ -1,13 +1,13 @@
1
+ export interface SkillEntry {
2
+ ref?: string;
3
+ exclude?: string[];
4
+ include?: string[];
5
+ }
1
6
  export interface SkillConfig {
2
7
  registry: string;
3
8
  agents: string[];
4
9
  skills: {
5
- [key: string]: {
6
- enabled: boolean;
7
- ref?: string;
8
- exclude?: string[];
9
- include?: string[];
10
- };
10
+ [key: string]: SkillEntry;
11
11
  };
12
12
  custom_overrides?: string[];
13
13
  }
@@ -0,0 +1,8 @@
1
+ import { SkillConfig } from '../models/config';
2
+ import { RegistryMetadata } from '../models/types';
3
+ export declare class ConfigService {
4
+ buildInitialConfig(framework: string, agents: string[], registry: string, metadata: Partial<RegistryMetadata>): SkillConfig;
5
+ private getAllKnownCategories;
6
+ private createSkillEntry;
7
+ applyDependencyExclusions(config: SkillConfig, framework: string, projectDeps: Set<string>): void;
8
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigService = void 0;
4
+ const constants_1 = require("../constants");
5
+ class ConfigService {
6
+ buildInitialConfig(framework, agents, registry, metadata) {
7
+ const selectedFramework = constants_1.SUPPORTED_FRAMEWORKS.find((f) => f.id === framework);
8
+ const neededSkills = new Set();
9
+ constants_1.UNIVERSAL_SKILLS.forEach((s) => neededSkills.add(s));
10
+ neededSkills.add(framework);
11
+ if (selectedFramework) {
12
+ selectedFramework.languages.forEach((l) => neededSkills.add(l));
13
+ }
14
+ // Special cases
15
+ if (framework === constants_1.Framework.NextJS || framework === constants_1.Framework.ReactNative) {
16
+ neededSkills.add(constants_1.Framework.React);
17
+ }
18
+ const frameworkSkills = constants_1.SKILL_DETECTION_REGISTRY[framework] || [];
19
+ frameworkSkills.forEach((s) => neededSkills.add(s.id));
20
+ const config = {
21
+ registry,
22
+ agents,
23
+ skills: {},
24
+ custom_overrides: [],
25
+ };
26
+ const allKnownCategories = this.getAllKnownCategories();
27
+ for (const skill of [...new Set(allKnownCategories)]) {
28
+ if (neededSkills.has(skill)) {
29
+ config.skills[skill] = this.createSkillEntry(skill, metadata);
30
+ }
31
+ }
32
+ return config;
33
+ }
34
+ getAllKnownCategories() {
35
+ return [
36
+ ...constants_1.UNIVERSAL_SKILLS,
37
+ ...constants_1.SUPPORTED_FRAMEWORKS.map((f) => f.id),
38
+ ...constants_1.SUPPORTED_FRAMEWORKS.flatMap((f) => f.languages),
39
+ ...Object.values(constants_1.SKILL_DETECTION_REGISTRY).flatMap((skills) => skills.map((s) => s.id)),
40
+ ];
41
+ }
42
+ createSkillEntry(skill, metadata) {
43
+ const skillMeta = metadata.categories?.[skill];
44
+ let refStr;
45
+ if (skillMeta?.version && skillMeta?.tag_prefix) {
46
+ refStr = `${skillMeta.tag_prefix}${skillMeta.version}`;
47
+ }
48
+ return {
49
+ ref: refStr,
50
+ };
51
+ }
52
+ applyDependencyExclusions(config, framework, projectDeps) {
53
+ const frameworkSkills = constants_1.SKILL_DETECTION_REGISTRY[framework] || [];
54
+ for (const skill of frameworkSkills) {
55
+ const entry = config.skills[skill.id];
56
+ if (!entry)
57
+ continue;
58
+ const used = skill.packages.some((p) => projectDeps.has(p));
59
+ if (!used) {
60
+ const parent = config.skills[framework] || {};
61
+ const excludes = parent.exclude ? [...parent.exclude] : [];
62
+ if (!excludes.includes(skill.id))
63
+ excludes.push(skill.id);
64
+ parent.exclude = excludes;
65
+ config.skills[framework] = parent;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ exports.ConfigService = ConfigService;
@@ -0,0 +1,5 @@
1
+ export declare class DetectionService {
2
+ detectFrameworks(): Promise<Record<string, boolean>>;
3
+ detectAgents(): Promise<Record<string, boolean>>;
4
+ private getPackageDeps;
5
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DetectionService = void 0;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const constants_1 = require("../constants");
10
+ class DetectionService {
11
+ async detectFrameworks() {
12
+ const packageDeps = await this.getPackageDeps();
13
+ const results = {};
14
+ for (const framework of constants_1.SUPPORTED_FRAMEWORKS) {
15
+ let detected = false;
16
+ // 1. Check characteristic files
17
+ for (const file of framework.detectionFiles) {
18
+ if (await fs_extra_1.default.pathExists(path_1.default.join(process.cwd(), file))) {
19
+ detected = true;
20
+ break;
21
+ }
22
+ }
23
+ // 2. Check dependencies (if not yet detected)
24
+ if (!detected &&
25
+ framework.detectionDependencies &&
26
+ framework.detectionDependencies.length > 0) {
27
+ detected = framework.detectionDependencies.some((dep) => Object.prototype.hasOwnProperty.call(packageDeps, dep));
28
+ }
29
+ results[framework.id] = detected;
30
+ }
31
+ return results;
32
+ }
33
+ async detectAgents() {
34
+ const results = {};
35
+ for (const agent of constants_1.SUPPORTED_AGENTS) {
36
+ let detected = false;
37
+ for (const file of agent.detectionFiles) {
38
+ if (await fs_extra_1.default.pathExists(path_1.default.join(process.cwd(), file))) {
39
+ detected = true;
40
+ break;
41
+ }
42
+ }
43
+ results[agent.id] = detected;
44
+ }
45
+ return results;
46
+ }
47
+ async getPackageDeps() {
48
+ const packageJsonPath = path_1.default.join(process.cwd(), 'package.json');
49
+ if (await fs_extra_1.default.pathExists(packageJsonPath)) {
50
+ try {
51
+ const pkg = await fs_extra_1.default.readJson(packageJsonPath);
52
+ return { ...pkg.dependencies, ...pkg.devDependencies };
53
+ }
54
+ catch {
55
+ return {};
56
+ }
57
+ }
58
+ return {};
59
+ }
60
+ }
61
+ exports.DetectionService = DetectionService;
@@ -0,0 +1,7 @@
1
+ import { RegistryMetadata } from '../models/types';
2
+ export declare class RegistryService {
3
+ discoverRegistry(registryUrl: string): Promise<{
4
+ categories: string[];
5
+ metadata: Partial<RegistryMetadata>;
6
+ }>;
7
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RegistryService = void 0;
7
+ const node_fetch_1 = __importDefault(require("node-fetch"));
8
+ const github_1 = require("../utils/github");
9
+ class RegistryService {
10
+ async discoverRegistry(registryUrl) {
11
+ let categories = ['flutter', 'dart'];
12
+ let metadata = {};
13
+ try {
14
+ const parsed = (0, github_1.parseRegistryUrl)(registryUrl);
15
+ if (parsed) {
16
+ const treeResult = await (0, github_1.fetchRepoTree)(parsed.owner, parsed.repo);
17
+ if (treeResult && Array.isArray(treeResult.data.tree)) {
18
+ const allFiles = treeResult.data.tree || [];
19
+ const foundCategories = new Set();
20
+ allFiles.forEach((f) => {
21
+ if (f.path.startsWith('skills/') && f.type === 'tree') {
22
+ const parts = f.path.split('/');
23
+ if (parts.length === 2)
24
+ foundCategories.add(parts[1]);
25
+ }
26
+ });
27
+ if (foundCategories.size > 0)
28
+ categories = Array.from(foundCategories);
29
+ const metaUrl = `https://raw.githubusercontent.com/${parsed.owner}/${parsed.repo}/${treeResult.branch}/skills/metadata.json`;
30
+ const metaRes = await (0, node_fetch_1.default)(metaUrl);
31
+ if (metaRes.ok) {
32
+ metadata = (await metaRes.json());
33
+ }
34
+ }
35
+ }
36
+ }
37
+ catch {
38
+ // Return defaults on error
39
+ }
40
+ return { categories, metadata };
41
+ }
42
+ }
43
+ exports.RegistryService = RegistryService;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-skills-standard",
3
- "version": "1.1.2",
4
- "description": "A CLI to manage and sync AI agent skills standard for Cursor, Claude, Copilot, and more.",
3
+ "version": "1.2.0",
4
+ "description": "A CLI to manage and sync AI agent skills standard for Cursor, Claude, Copilot, Windsurf, and more.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
7
  "agent-skills-standard": "dist/index.js",