agent-config-sync 0.1.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/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/catalog.d.ts +65 -0
- package/dist/catalog.js +328 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli-catalog.d.ts +70 -0
- package/dist/cli-catalog.js +433 -0
- package/dist/cli-catalog.js.map +1 -0
- package/dist/cli-diagnostics.d.ts +14 -0
- package/dist/cli-diagnostics.js +177 -0
- package/dist/cli-diagnostics.js.map +1 -0
- package/dist/cli-mcp.d.ts +38 -0
- package/dist/cli-mcp.js +179 -0
- package/dist/cli-mcp.js.map +1 -0
- package/dist/cli-skill.d.ts +51 -0
- package/dist/cli-skill.js +239 -0
- package/dist/cli-skill.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +733 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-adapters.d.ts +32 -0
- package/dist/config-adapters.js +409 -0
- package/dist/config-adapters.js.map +1 -0
- package/dist/fs.d.ts +2 -0
- package/dist/fs.js +20 -0
- package/dist/fs.js.map +1 -0
- package/dist/project-discovery.d.ts +24 -0
- package/dist/project-discovery.js +129 -0
- package/dist/project-discovery.js.map +1 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.js +121 -0
- package/dist/registry.js.map +1 -0
- package/dist/skill-adapters.d.ts +53 -0
- package/dist/skill-adapters.js +183 -0
- package/dist/skill-adapters.js.map +1 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Constants
|
|
5
|
+
// ============================================================================
|
|
6
|
+
/** Native config file paths for each target relative to project root */
|
|
7
|
+
const TARGET_CONFIG_PATHS = {
|
|
8
|
+
claude: '.mcp.json',
|
|
9
|
+
codex: path.join('.codex', 'config.toml'),
|
|
10
|
+
gemini: path.join('.gemini', 'settings.json'),
|
|
11
|
+
};
|
|
12
|
+
/** Skills directory paths for each target relative to project root */
|
|
13
|
+
const TARGET_SKILLS_PATHS = {
|
|
14
|
+
claude: path.join('.claude', 'skills'),
|
|
15
|
+
codex: path.join('.codex', 'skills'),
|
|
16
|
+
gemini: path.join('.gemini', 'antigravity', 'skills'),
|
|
17
|
+
};
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Project Discovery
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Discover the active project from the current working directory.
|
|
23
|
+
*
|
|
24
|
+
* Priority:
|
|
25
|
+
* 1. Nearest ancestor that is a Git repository root
|
|
26
|
+
* 2. Nearest ancestor containing any supported native config file
|
|
27
|
+
* 3. Fail with clear error
|
|
28
|
+
*/
|
|
29
|
+
export async function discoverProject(cwd = process.cwd()) {
|
|
30
|
+
const gitRoot = await findGitRoot(cwd);
|
|
31
|
+
const projectRoot = gitRoot ?? (await findNativeConfigRoot(cwd));
|
|
32
|
+
if (!projectRoot) {
|
|
33
|
+
throw new Error('Not inside a managed project. ' +
|
|
34
|
+
'Navigate to a Git repository or a directory with native agent config files.');
|
|
35
|
+
}
|
|
36
|
+
const targets = await resolveNativeConfigPaths(projectRoot);
|
|
37
|
+
return { root: projectRoot, targets };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Find the nearest Git repository root by traversing upwards.
|
|
41
|
+
*/
|
|
42
|
+
async function findGitRoot(cwd) {
|
|
43
|
+
let current = path.resolve(cwd);
|
|
44
|
+
while (true) {
|
|
45
|
+
const gitDir = path.join(current, '.git');
|
|
46
|
+
try {
|
|
47
|
+
const stat = await fs.stat(gitDir);
|
|
48
|
+
if (stat.isDirectory()) {
|
|
49
|
+
return current;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// .git doesn't exist, continue
|
|
54
|
+
}
|
|
55
|
+
const parent = path.dirname(current);
|
|
56
|
+
if (parent === current) {
|
|
57
|
+
// Reached root
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
current = parent;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Find the nearest ancestor containing any supported native config file.
|
|
65
|
+
*/
|
|
66
|
+
async function findNativeConfigRoot(cwd) {
|
|
67
|
+
let current = path.resolve(cwd);
|
|
68
|
+
while (true) {
|
|
69
|
+
for (const targetPath of Object.values(TARGET_CONFIG_PATHS)) {
|
|
70
|
+
const fullPath = path.join(current, targetPath);
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(fullPath);
|
|
73
|
+
return current;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// File doesn't exist, try next
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const parent = path.dirname(current);
|
|
80
|
+
if (parent === current) {
|
|
81
|
+
// Reached root
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
current = parent;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolve native config paths for all targets relative to the project root.
|
|
89
|
+
*/
|
|
90
|
+
async function resolveNativeConfigPaths(projectRoot) {
|
|
91
|
+
const targets = new Map();
|
|
92
|
+
for (const [target, relativePath] of Object.entries(TARGET_CONFIG_PATHS)) {
|
|
93
|
+
const fullPath = path.join(projectRoot, relativePath);
|
|
94
|
+
let exists = false;
|
|
95
|
+
try {
|
|
96
|
+
await fs.access(fullPath);
|
|
97
|
+
exists = true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// File doesn't exist
|
|
101
|
+
}
|
|
102
|
+
targets.set(target, {
|
|
103
|
+
target,
|
|
104
|
+
path: fullPath,
|
|
105
|
+
exists,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return targets;
|
|
109
|
+
}
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Utilities
|
|
112
|
+
// ============================================================================
|
|
113
|
+
/**
|
|
114
|
+
* Get the relative path from project root to a config file.
|
|
115
|
+
*/
|
|
116
|
+
export function getRelativeConfigPath(projectRoot, target) {
|
|
117
|
+
return TARGET_CONFIG_PATHS[target];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get the relative path from project root to the skills directory.
|
|
121
|
+
*/
|
|
122
|
+
export function getSkillsPath(projectRoot, target) {
|
|
123
|
+
return path.join(projectRoot, TARGET_SKILLS_PATHS[target]);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get the skills directory paths constant.
|
|
127
|
+
*/
|
|
128
|
+
export { TARGET_SKILLS_PATHS };
|
|
129
|
+
//# sourceMappingURL=project-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-discovery.js","sourceRoot":"","sources":["../src/project-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search the skills.directory registry for skills.
|
|
3
|
+
*/
|
|
4
|
+
export declare function searchSkills(query: string): Promise<RegistrySkill[]>;
|
|
5
|
+
/**
|
|
6
|
+
* Get detailed information about a skill from the registry.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getSkillInfo(skillName: string): Promise<RegistrySkillInfo | null>;
|
|
9
|
+
/**
|
|
10
|
+
* Download a skill's SKILL.md content from GitHub.
|
|
11
|
+
*/
|
|
12
|
+
export declare function downloadSkillContent(githubUrl: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Install a skill from GitHub URL.
|
|
15
|
+
*/
|
|
16
|
+
export declare function installFromGitHub(githubUrl: string, skillName?: string): Promise<{
|
|
17
|
+
name: string;
|
|
18
|
+
content: string;
|
|
19
|
+
}>;
|
|
20
|
+
export interface RegistrySkill {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
version: string;
|
|
24
|
+
author: string;
|
|
25
|
+
verticals: string[];
|
|
26
|
+
stars: number;
|
|
27
|
+
installs: number;
|
|
28
|
+
repo: string;
|
|
29
|
+
skill_md: string;
|
|
30
|
+
}
|
|
31
|
+
export interface RegistrySkillInfo {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
author: string;
|
|
35
|
+
verticals: string[];
|
|
36
|
+
updated: string;
|
|
37
|
+
stars: number;
|
|
38
|
+
installs: number;
|
|
39
|
+
repo: string;
|
|
40
|
+
skill_md: string;
|
|
41
|
+
installation: {
|
|
42
|
+
local: boolean;
|
|
43
|
+
global: string;
|
|
44
|
+
};
|
|
45
|
+
links: {
|
|
46
|
+
repo: string;
|
|
47
|
+
skill_md: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Skills Directory Registry Client
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/** Maximum size for skill content (1MB) */
|
|
5
|
+
const MAX_SKILL_SIZE = 1024 * 1024;
|
|
6
|
+
/**
|
|
7
|
+
* Validate that a URL is from GitHub.
|
|
8
|
+
*/
|
|
9
|
+
function validateGitHubUrl(inputUrl) {
|
|
10
|
+
try {
|
|
11
|
+
const url = new URL(inputUrl);
|
|
12
|
+
const allowedHosts = ['github.com', 'raw.githubusercontent.com', 'www.github.com'];
|
|
13
|
+
return allowedHosts.includes(url.hostname);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Search the skills.directory registry for skills.
|
|
21
|
+
*/
|
|
22
|
+
export async function searchSkills(query) {
|
|
23
|
+
const url = `https://api.skills-directory.com/v1/search?q=${encodeURIComponent(query)}`;
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(url);
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error('Registry search failed');
|
|
28
|
+
}
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
return data.skills || [];
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Failed to search registry. Please try again later.');
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get detailed information about a skill from the registry.
|
|
39
|
+
*/
|
|
40
|
+
export async function getSkillInfo(skillName) {
|
|
41
|
+
const url = `https://api.skills-directory.com/v1/skills/${encodeURIComponent(skillName)}`;
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch(url);
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
if (response.status === 404) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
throw new Error('Registry fetch failed');
|
|
49
|
+
}
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error('Failed to fetch skill info. Please try again later.');
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Download a skill's SKILL.md content from GitHub.
|
|
60
|
+
*/
|
|
61
|
+
export async function downloadSkillContent(githubUrl) {
|
|
62
|
+
// Validate URL is from GitHub
|
|
63
|
+
if (!validateGitHubUrl(githubUrl)) {
|
|
64
|
+
throw new Error('Only GitHub URLs are allowed');
|
|
65
|
+
}
|
|
66
|
+
// Parse GitHub URL to extract raw content URL
|
|
67
|
+
const rawUrl = githubUrl.replace('github.com', 'raw.githubusercontent.com')
|
|
68
|
+
.replace('/blob/', '/')
|
|
69
|
+
.replace('/tree/', '/');
|
|
70
|
+
// Ensure we point to SKILL.md
|
|
71
|
+
const skillUrl = rawUrl.endsWith('SKILL.md') ? rawUrl : `${rawUrl}/SKILL.md`;
|
|
72
|
+
// Validate final URL is still from GitHub
|
|
73
|
+
if (!validateGitHubUrl(skillUrl)) {
|
|
74
|
+
throw new Error('Invalid GitHub URL structure');
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const response = await fetch(skillUrl);
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(`Download failed: ${response.status}`);
|
|
80
|
+
}
|
|
81
|
+
// Check content length
|
|
82
|
+
const contentLength = response.headers.get('content-length');
|
|
83
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_SKILL_SIZE) {
|
|
84
|
+
throw new Error('Skill file too large');
|
|
85
|
+
}
|
|
86
|
+
const content = await response.text();
|
|
87
|
+
// Double-check actual content size
|
|
88
|
+
if (content.length > MAX_SKILL_SIZE) {
|
|
89
|
+
throw new Error('Skill file too large');
|
|
90
|
+
}
|
|
91
|
+
return content;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
95
|
+
if (message.includes('Only GitHub') || message.includes('Invalid GitHub')) {
|
|
96
|
+
throw new Error(message);
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`Failed to download skill. Check the URL and try again.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Install a skill from GitHub URL.
|
|
103
|
+
*/
|
|
104
|
+
export async function installFromGitHub(githubUrl, skillName) {
|
|
105
|
+
// Fetch the repository info to get the default branch if needed
|
|
106
|
+
const content = await downloadSkillContent(githubUrl);
|
|
107
|
+
// Parse the skill name from the content if not provided
|
|
108
|
+
if (!skillName) {
|
|
109
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
110
|
+
if (nameMatch) {
|
|
111
|
+
skillName = nameMatch[1].trim().replace(/^["']|["']$/g, '');
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Extract from GitHub URL
|
|
115
|
+
const urlMatch = githubUrl.match(/\/skills\/([^\/]+)/);
|
|
116
|
+
skillName = urlMatch ? urlMatch[1] : 'unknown-skill';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { name: skillName, content };
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { TargetName } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate a skill name to prevent path traversal and injection.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateSkillName(skillName: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Get the skills directory path for a target.
|
|
8
|
+
* - Claude: <project>/.claude/skills/
|
|
9
|
+
* - Codex: <project>/.codex/skills/
|
|
10
|
+
* - Gemini: <project>/.gemini/antigravity/skills/
|
|
11
|
+
*/
|
|
12
|
+
export declare function getSkillsDir(projectRoot: string, target: TargetName): string;
|
|
13
|
+
/**
|
|
14
|
+
* Get the skill directory path for a specific skill.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getSkillDir(projectRoot: string, target: TargetName, skillName: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get the SKILL.md file path for a specific skill.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getSkillFilePath(projectRoot: string, target: TargetName, skillName: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Read a skill file from disk.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readSkill(projectRoot: string, target: TargetName, skillName: string): Promise<{
|
|
25
|
+
exists: boolean;
|
|
26
|
+
content: string | null;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Write a skill file to disk atomically.
|
|
30
|
+
*/
|
|
31
|
+
export declare function writeSkill(projectRoot: string, target: TargetName, skillName: string, content: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Remove a skill directory.
|
|
34
|
+
*/
|
|
35
|
+
export declare function removeSkill(projectRoot: string, target: TargetName, skillName: string): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Add a skill to a project.
|
|
38
|
+
*/
|
|
39
|
+
export declare function addSkillToConfig(projectRoot: string, target: TargetName, skillId: string, content: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Remove a skill from a project.
|
|
42
|
+
*/
|
|
43
|
+
export declare function removeSkillFromConfig(projectRoot: string, target: TargetName, skillName: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Get all skills from a project's native config directories.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getSkills(projectRoot: string, target: TargetName): Promise<Record<string, {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
}>>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a skill is enabled for a target.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSkillEnabled(projectRoot: string, target: TargetName, skillName: string): Promise<boolean>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Constants
|
|
5
|
+
// ============================================================================
|
|
6
|
+
/** Maximum size for skill files (1MB) */
|
|
7
|
+
const MAX_SKILL_SIZE = 1024 * 1024;
|
|
8
|
+
/** Valid skill name pattern: alphanumeric, hyphens, underscores, dots */
|
|
9
|
+
const SKILL_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Validation
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Validate a skill name to prevent path traversal and injection.
|
|
15
|
+
*/
|
|
16
|
+
export function validateSkillName(skillName) {
|
|
17
|
+
if (!skillName || skillName.length === 0) {
|
|
18
|
+
throw new Error('Skill name cannot be empty');
|
|
19
|
+
}
|
|
20
|
+
if (skillName.length > 100) {
|
|
21
|
+
throw new Error('Skill name too long (max 100 characters)');
|
|
22
|
+
}
|
|
23
|
+
if (!SKILL_NAME_PATTERN.test(skillName)) {
|
|
24
|
+
throw new Error('Skill name must contain only alphanumeric characters, hyphens, underscores, and dots');
|
|
25
|
+
}
|
|
26
|
+
// Prevent path traversal
|
|
27
|
+
if (skillName.includes('..') || skillName.includes('/') || skillName.includes('\\')) {
|
|
28
|
+
throw new Error('Skill name cannot contain path traversal characters');
|
|
29
|
+
}
|
|
30
|
+
// Prevent leading/trailing dots and dashes (security issues)
|
|
31
|
+
if (skillName.startsWith('.') || skillName.startsWith('-') ||
|
|
32
|
+
skillName.endsWith('.') || skillName.endsWith('-')) {
|
|
33
|
+
throw new Error('Skill name cannot start or end with a dot or dash');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Skill Path Resolution
|
|
38
|
+
// ============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* Get the skills directory path for a target.
|
|
41
|
+
* - Claude: <project>/.claude/skills/
|
|
42
|
+
* - Codex: <project>/.codex/skills/
|
|
43
|
+
* - Gemini: <project>/.gemini/antigravity/skills/
|
|
44
|
+
*/
|
|
45
|
+
export function getSkillsDir(projectRoot, target) {
|
|
46
|
+
switch (target) {
|
|
47
|
+
case 'claude':
|
|
48
|
+
return path.join(projectRoot, '.claude', 'skills');
|
|
49
|
+
case 'codex':
|
|
50
|
+
return path.join(projectRoot, '.codex', 'skills');
|
|
51
|
+
case 'gemini':
|
|
52
|
+
return path.join(projectRoot, '.gemini', 'antigravity', 'skills');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the skill directory path for a specific skill.
|
|
57
|
+
*/
|
|
58
|
+
export function getSkillDir(projectRoot, target, skillName) {
|
|
59
|
+
const skillsDir = getSkillsDir(projectRoot, target);
|
|
60
|
+
return path.join(skillsDir, skillName);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the SKILL.md file path for a specific skill.
|
|
64
|
+
*/
|
|
65
|
+
export function getSkillFilePath(projectRoot, target, skillName) {
|
|
66
|
+
const skillDir = getSkillDir(projectRoot, target, skillName);
|
|
67
|
+
return path.join(skillDir, 'SKILL.md');
|
|
68
|
+
}
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Skill File Operations
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Read a skill file from disk.
|
|
74
|
+
*/
|
|
75
|
+
export async function readSkill(projectRoot, target, skillName) {
|
|
76
|
+
validateSkillName(skillName);
|
|
77
|
+
const skillPath = getSkillFilePath(projectRoot, target, skillName);
|
|
78
|
+
try {
|
|
79
|
+
await fs.access(skillPath);
|
|
80
|
+
const content = await fs.readFile(skillPath, 'utf8');
|
|
81
|
+
// Check content size
|
|
82
|
+
if (content.length > MAX_SKILL_SIZE) {
|
|
83
|
+
throw new Error('Skill file too large');
|
|
84
|
+
}
|
|
85
|
+
return { exists: true, content };
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { exists: false, content: null };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Write a skill file to disk atomically.
|
|
93
|
+
*/
|
|
94
|
+
export async function writeSkill(projectRoot, target, skillName, content) {
|
|
95
|
+
validateSkillName(skillName);
|
|
96
|
+
// Check content size before writing
|
|
97
|
+
if (content.length > MAX_SKILL_SIZE) {
|
|
98
|
+
throw new Error(`Skill content too large (${content.length} bytes, max ${MAX_SKILL_SIZE})`);
|
|
99
|
+
}
|
|
100
|
+
const skillDir = getSkillDir(projectRoot, target, skillName);
|
|
101
|
+
const skillPath = getSkillFilePath(projectRoot, target, skillName);
|
|
102
|
+
// Create skill directory if it doesn't exist
|
|
103
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
104
|
+
// Write atomically
|
|
105
|
+
const tempPath = `${skillPath}.tmp`;
|
|
106
|
+
await fs.writeFile(tempPath, content, 'utf8');
|
|
107
|
+
await fs.rename(tempPath, skillPath);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Remove a skill directory.
|
|
111
|
+
*/
|
|
112
|
+
export async function removeSkill(projectRoot, target, skillName) {
|
|
113
|
+
validateSkillName(skillName);
|
|
114
|
+
const skillDir = getSkillDir(projectRoot, target, skillName);
|
|
115
|
+
try {
|
|
116
|
+
await fs.access(skillDir);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false; // Doesn't exist
|
|
120
|
+
}
|
|
121
|
+
await fs.rm(skillDir, { recursive: true, force: true });
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Add a skill to a project.
|
|
126
|
+
*/
|
|
127
|
+
export async function addSkillToConfig(projectRoot, target, skillId, content) {
|
|
128
|
+
await writeSkill(projectRoot, target, skillId, content);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Remove a skill from a project.
|
|
132
|
+
*/
|
|
133
|
+
export async function removeSkillFromConfig(projectRoot, target, skillName) {
|
|
134
|
+
await removeSkill(projectRoot, target, skillName);
|
|
135
|
+
}
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Skill Status Queries
|
|
138
|
+
// ============================================================================
|
|
139
|
+
/**
|
|
140
|
+
* Get all skills from a project's native config directories.
|
|
141
|
+
*/
|
|
142
|
+
export async function getSkills(projectRoot, target) {
|
|
143
|
+
const skillsDir = getSkillsDir(projectRoot, target);
|
|
144
|
+
const skills = {};
|
|
145
|
+
try {
|
|
146
|
+
await fs.access(skillsDir);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return skills; // Directory doesn't exist
|
|
150
|
+
}
|
|
151
|
+
const entries = await fs.readdir(skillsDir, { withFileTypes: true });
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (!entry.isDirectory())
|
|
154
|
+
continue;
|
|
155
|
+
const skillName = entry.name;
|
|
156
|
+
// Validate skill name to skip invalid entries
|
|
157
|
+
try {
|
|
158
|
+
validateSkillName(skillName);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Skip invalid skill names
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const skillPath = path.join(skillsDir, skillName, 'SKILL.md');
|
|
165
|
+
try {
|
|
166
|
+
await fs.access(skillPath);
|
|
167
|
+
// All skills are considered "enabled" if the SKILL.md file exists
|
|
168
|
+
skills[skillName] = { enabled: true };
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// SKILL.md doesn't exist, skip
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return skills;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check if a skill is enabled for a target.
|
|
178
|
+
*/
|
|
179
|
+
export async function isSkillEnabled(projectRoot, target, skillName) {
|
|
180
|
+
const { exists } = await readSkill(projectRoot, target, skillName);
|
|
181
|
+
return exists;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=skill-adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-adapters.js","sourceRoot":"","sources":["../src/skill-adapters.ts"],"names":[],"mappings":"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"}
|