psadk 1.3.4 → 1.3.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/build/main/index.d.ts +3 -0
- package/build/main/index.js +4 -1
- package/build/main/lib/skills/constants.d.ts +1 -0
- package/build/main/lib/skills/constants.js +2 -1
- package/build/main/lib/skills/skillParser.d.ts +6 -1
- package/build/main/lib/skills/skillParser.js +25 -15
- package/build/main/lib/skills/types.d.ts +61 -0
- package/build/main/lib/skills/types.js +3 -0
- package/build/main/lib/skills/utils.d.ts +56 -0
- package/build/main/lib/skills/utils.js +342 -1
- package/build/main/lib/tools/PSSkillTool.d.ts +14 -0
- package/build/main/lib/tools/PSSkillTool.js +100 -0
- package/build/module/index.d.ts +3 -0
- package/build/module/index.js +4 -1
- package/build/module/lib/skills/constants.d.ts +1 -0
- package/build/module/lib/skills/constants.js +2 -1
- package/build/module/lib/skills/skillParser.d.ts +6 -1
- package/build/module/lib/skills/skillParser.js +25 -15
- package/build/module/lib/skills/types.d.ts +61 -0
- package/build/module/lib/skills/types.js +3 -0
- package/build/module/lib/skills/utils.d.ts +56 -0
- package/build/module/lib/skills/utils.js +340 -1
- package/build/module/lib/tools/PSSkillTool.d.ts +14 -0
- package/build/module/lib/tools/PSSkillTool.js +102 -0
- package/package.json +2 -1
package/build/main/index.d.ts
CHANGED
|
@@ -11,3 +11,6 @@ export * from './lib/tools/PSWriteFileTool';
|
|
|
11
11
|
export * from './lib/tools/PSSubAgentTool';
|
|
12
12
|
export * from './lib/tools/PSMemoryTool';
|
|
13
13
|
export * from './lib/tools/PSClarifyTool';
|
|
14
|
+
export * from './lib/tools/PSSkillTool';
|
|
15
|
+
export * from './lib/skills/types';
|
|
16
|
+
export * from './lib/skills/utils';
|
package/build/main/index.js
CHANGED
|
@@ -27,4 +27,7 @@ __exportStar(require("./lib/tools/PSWriteFileTool"), exports);
|
|
|
27
27
|
__exportStar(require("./lib/tools/PSSubAgentTool"), exports);
|
|
28
28
|
__exportStar(require("./lib/tools/PSMemoryTool"), exports);
|
|
29
29
|
__exportStar(require("./lib/tools/PSClarifyTool"), exports);
|
|
30
|
-
|
|
30
|
+
__exportStar(require("./lib/tools/PSSkillTool"), exports);
|
|
31
|
+
__exportStar(require("./lib/skills/types"), exports);
|
|
32
|
+
__exportStar(require("./lib/skills/utils"), exports);
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZDQUEyQjtBQUMzQixnREFBOEI7QUFDOUIsc0RBQW9DO0FBQ3BDLHNEQUFvQztBQUNwQyxvREFBa0M7QUFDbEMsb0RBQWtDO0FBQ2xDLHVEQUFxQztBQUNyQyxnRUFBOEM7QUFDOUMsNkRBQTJDO0FBQzNDLDhEQUE0QztBQUM1Qyw2REFBMkM7QUFDM0MsMkRBQXlDO0FBQ3pDLDREQUEwQztBQUMxQywwREFBd0M7QUFDeEMscURBQW1DO0FBQ25DLHFEQUFtQyJ9
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const STATIC_CONSTANTS = {
|
|
7
7
|
// Directory names
|
|
8
8
|
SLINGSHOT_DIR: '.slingshot',
|
|
9
|
+
AGENTS_DIR: '.agents', // Base directory for npx skills CLI
|
|
9
10
|
SKILLS_DIR: 'skills',
|
|
10
11
|
GLOBAL_SKILLS_DIR: 'skills', // For extension global path
|
|
11
12
|
// File names
|
|
@@ -21,4 +22,4 @@ const SKILL_CONSTANTS = Object.assign(Object.assign({}, STATIC_CONSTANTS), {
|
|
|
21
22
|
// Watch pattern for folder deletions - watch the entire skills directory
|
|
22
23
|
SKILLS_FOLDER_WATCH_PATTERN: `${STATIC_CONSTANTS.SLINGSHOT_DIR}/${STATIC_CONSTANTS.SKILLS_DIR}/**` });
|
|
23
24
|
exports.default = SKILL_CONSTANTS;
|
|
24
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9za2lsbHMvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7O0dBRUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHO0lBQ3ZCLGtCQUFrQjtJQUNsQixhQUFhLEVBQUUsWUFBWTtJQUMzQixVQUFVLEVBQUUsU0FBUyxFQUFFLG9DQUFvQztJQUMzRCxVQUFVLEVBQUUsUUFBUTtJQUNwQixpQkFBaUIsRUFBRSxRQUFRLEVBQUUsNEJBQTRCO0lBRXpELGFBQWE7SUFDYixxQkFBcUIsRUFBRSxVQUFVO0lBQ2pDLGFBQWEsRUFBRSxxQkFBcUI7SUFDcEMsVUFBVSxFQUFFLG1CQUFtQjtJQUUvQixTQUFTO0lBQ1QsY0FBYyxFQUFFLEdBQUcsRUFBRSxlQUFlO0NBQ3JDLENBQUM7QUFFRixNQUFNLGVBQWUsbUNBQ2hCLGdCQUFnQjtJQUNuQix3Q0FBd0M7SUFDeEMsbUJBQW1CLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxhQUFhLElBQUksZ0JBQWdCLENBQUMsVUFBVSxPQUFPLGdCQUFnQixDQUFDLHFCQUFxQixFQUFFO0lBQ3BJLHlFQUF5RTtJQUN6RSwyQkFBMkIsRUFBRSxHQUFHLGdCQUFnQixDQUFDLGFBQWEsSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLEtBQUssR0FDbkcsQ0FBQztBQUVGLGtCQUFlLGVBQWUsQ0FBQyJ9
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { SkillMetadata } from './types';
|
|
1
2
|
/**
|
|
2
|
-
* Parses a SKILL.md file to extract metadata
|
|
3
|
+
* Parses a SKILL.md file content to extract all metadata using gray-matter
|
|
4
|
+
*/
|
|
5
|
+
export declare function parseSkillMetadataFromContent(content: string, skillPath: string): SkillMetadata;
|
|
6
|
+
/**
|
|
7
|
+
* Parses a SKILL.md file to extract metadata for the registry (legacy format)
|
|
3
8
|
* @param {string} filePath - The absolute path to the SKILL.md file.
|
|
4
9
|
* @returns {Object|null} - Returns { name, description, folderPath } or null if invalid.
|
|
5
10
|
*/
|
|
@@ -3,12 +3,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseSkillMetadataFromContent = parseSkillMetadataFromContent;
|
|
6
7
|
exports.default = parseSkillMetadata;
|
|
7
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const
|
|
10
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
10
11
|
/**
|
|
11
|
-
* Parses a SKILL.md file to extract metadata
|
|
12
|
+
* Parses a SKILL.md file content to extract all metadata using gray-matter
|
|
13
|
+
*/
|
|
14
|
+
function parseSkillMetadataFromContent(content, skillPath) {
|
|
15
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
16
|
+
return {
|
|
17
|
+
name: parsed.data.name || 'unknown',
|
|
18
|
+
description: parsed.data.description || 'No description available',
|
|
19
|
+
version: parsed.data.version,
|
|
20
|
+
author: parsed.data.author,
|
|
21
|
+
license: parsed.data.license,
|
|
22
|
+
path: skillPath,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parses a SKILL.md file to extract metadata for the registry (legacy format)
|
|
12
27
|
* @param {string} filePath - The absolute path to the SKILL.md file.
|
|
13
28
|
* @returns {Object|null} - Returns { name, description, folderPath } or null if invalid.
|
|
14
29
|
*/
|
|
@@ -18,23 +33,18 @@ function parseSkillMetadata(filePath) {
|
|
|
18
33
|
return null;
|
|
19
34
|
}
|
|
20
35
|
const fileContent = node_fs_1.default.readFileSync(filePath, 'utf8');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
const trimmedName = data.name.trim();
|
|
28
|
-
const trimmedDescription = data.description ? data.description.trim() : '';
|
|
36
|
+
const skillPath = node_path_1.default.dirname(filePath);
|
|
37
|
+
// Parse using the unified function
|
|
38
|
+
const fullMetadata = parseSkillMetadataFromContent(fileContent, skillPath);
|
|
39
|
+
// Return legacy format for backward compatibility
|
|
29
40
|
return {
|
|
30
|
-
name:
|
|
31
|
-
description:
|
|
32
|
-
|
|
33
|
-
folderPath: node_path_1.default.dirname(filePath),
|
|
41
|
+
name: fullMetadata.name,
|
|
42
|
+
description: fullMetadata.description,
|
|
43
|
+
folderPath: fullMetadata.path,
|
|
34
44
|
};
|
|
35
45
|
}
|
|
36
46
|
catch (_a) {
|
|
37
47
|
return null;
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tpbGxQYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NraWxscy9za2lsbFBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVVBLHNFQWNDO0FBT0QscUNBdUJDO0FBdERELHNEQUF5QjtBQUN6QiwwREFBNkI7QUFFN0IsOERBQWlDO0FBSWpDOztHQUVHO0FBQ0gsU0FBZ0IsNkJBQTZCLENBQzNDLE9BQWUsRUFDZixTQUFpQjtJQUVqQixNQUFNLE1BQU0sR0FBRyxJQUFBLHFCQUFNLEVBQUMsT0FBTyxDQUFDLENBQUM7SUFFL0IsT0FBTztRQUNMLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxTQUFTO1FBQ25DLFdBQVcsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSwwQkFBMEI7UUFDbEUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTztRQUM1QixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNO1FBQzFCLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU87UUFDNUIsSUFBSSxFQUFFLFNBQVM7S0FDaEIsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBd0Isa0JBQWtCLENBQ3hDLFFBQWdCO0lBRWhCLElBQUksQ0FBQztRQUNILElBQUksQ0FBQyxpQkFBRSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQzdCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLGlCQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUN0RCxNQUFNLFNBQVMsR0FBRyxtQkFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV6QyxtQ0FBbUM7UUFDbkMsTUFBTSxZQUFZLEdBQUcsNkJBQTZCLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRTNFLGtEQUFrRDtRQUNsRCxPQUFPO1lBQ0wsSUFBSSxFQUFFLFlBQVksQ0FBQyxJQUFJO1lBQ3ZCLFdBQVcsRUFBRSxZQUFZLENBQUMsV0FBVztZQUNyQyxVQUFVLEVBQUUsWUFBWSxDQUFDLElBQUk7U0FDOUIsQ0FBQztJQUNKLENBQUM7SUFBQyxXQUFNLENBQUM7UUFDUCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDIn0=
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface SkillContent {
|
|
2
|
+
metadata: SkillFrontmatter;
|
|
3
|
+
content: string;
|
|
4
|
+
rawContent: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SkillFrontmatter {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
version: string;
|
|
10
|
+
author: string;
|
|
11
|
+
dependencies?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface SkillSourceConfig {
|
|
14
|
+
source: string;
|
|
15
|
+
sourceType?: 'git' | 'npm' | 'local';
|
|
16
|
+
version?: string;
|
|
17
|
+
branch?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SkillSourcesObject {
|
|
20
|
+
[skillName: string]: SkillSourceConfig;
|
|
21
|
+
}
|
|
22
|
+
export interface PSSkillToolConfig {
|
|
23
|
+
skillsPath: string;
|
|
24
|
+
allowedSkills?: string[];
|
|
25
|
+
skillSources?: SkillSourcesObject;
|
|
26
|
+
autoInstall?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface PSSkillToolExecutionConfig {
|
|
29
|
+
skillsPath: string;
|
|
30
|
+
allowedSkills?: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface SkillInstallationOptions {
|
|
33
|
+
source: string;
|
|
34
|
+
skillsPath: string;
|
|
35
|
+
timeout?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface SkillInvocation {
|
|
38
|
+
skill_name: string;
|
|
39
|
+
arguments?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface SkillMetadata {
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
path: string;
|
|
45
|
+
version?: string;
|
|
46
|
+
author?: string;
|
|
47
|
+
license?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface SkillExecutionResult {
|
|
50
|
+
status: 'success' | 'error';
|
|
51
|
+
skill_name: string;
|
|
52
|
+
content?: string;
|
|
53
|
+
metadata?: {
|
|
54
|
+
name: string;
|
|
55
|
+
description: string;
|
|
56
|
+
version: string;
|
|
57
|
+
author: string;
|
|
58
|
+
};
|
|
59
|
+
message: string;
|
|
60
|
+
error?: string;
|
|
61
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NraWxscy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { IStreamLogger } from '../PSAgentLogger';
|
|
2
|
+
import { SkillContent, SkillInstallationOptions, SkillMetadata, SkillSourcesObject } from './types';
|
|
1
3
|
/**
|
|
2
4
|
* Gets the slingshot directories for both workspace and user levels.
|
|
3
5
|
* Creates the directories if they don't exist.
|
|
@@ -8,3 +10,57 @@ export default function getSlingshotDirectories(repoRoot: string): {
|
|
|
8
10
|
workspaceLevelSlingshotDir: string | null;
|
|
9
11
|
userLevelSlingshotDir: string | null;
|
|
10
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Validates skill name for security (prevents path traversal)
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateSkillName(skillName: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Validates skill source URL for security (prevents command injection)
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateSkillSource(source: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Ensures skills directory exists
|
|
23
|
+
*/
|
|
24
|
+
export declare function ensureSkillsDirectory(skillsPath: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Gets the path to a skill's SKILL.md file
|
|
27
|
+
* Skills are stored in the .agents/skills subdirectory as created by npx skills CLI
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSkillFilePath(skillsPath: string, skillName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Checks if a skill exists locally
|
|
32
|
+
*/
|
|
33
|
+
export declare function skillExists(skillsPath: string, skillName: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Reads skill content and parses frontmatter using skillParser
|
|
36
|
+
*/
|
|
37
|
+
export declare function readSkillContent(skillsPath: string, skillName: string): Promise<SkillContent>;
|
|
38
|
+
/**
|
|
39
|
+
* Scans a directory for installed skills and returns metadata
|
|
40
|
+
*/
|
|
41
|
+
export declare function scanInstalledSkills(skillsPath: string): Promise<Map<string, SkillMetadata>>;
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes skill source URLs to handle common formatting issues
|
|
44
|
+
*/
|
|
45
|
+
export declare function normalizeSkillSource(source: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Extract skill name from source URL
|
|
48
|
+
*/
|
|
49
|
+
export declare function extractSkillName(source: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Install a skill using npx skills command (simplified)
|
|
52
|
+
*/
|
|
53
|
+
export declare function installSkill(options: SkillInstallationOptions): Promise<SkillMetadata>;
|
|
54
|
+
/**
|
|
55
|
+
* Converts skill metadata to XML format for system prompts
|
|
56
|
+
*/
|
|
57
|
+
export declare function convertSkillsToSystemPromptXml(skills: SkillMetadata[]): string;
|
|
58
|
+
/**
|
|
59
|
+
* Get skills XML from a skills directory scan
|
|
60
|
+
*/
|
|
61
|
+
export declare function getSkillsSystemPromptFromDirectory(skillsPath: string): Promise<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Setup skills directory and get system prompt
|
|
64
|
+
* Accepts skill sources as an object mapping skill names to source configurations
|
|
65
|
+
*/
|
|
66
|
+
export declare function setupSkillsAndGetPrompt(skillsPath: string, sources?: SkillSourcesObject, log?: IStreamLogger): Promise<string>;
|
|
@@ -4,10 +4,28 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.default = getSlingshotDirectories;
|
|
7
|
+
exports.validateSkillName = validateSkillName;
|
|
8
|
+
exports.validateSkillSource = validateSkillSource;
|
|
9
|
+
exports.ensureSkillsDirectory = ensureSkillsDirectory;
|
|
10
|
+
exports.getSkillFilePath = getSkillFilePath;
|
|
11
|
+
exports.skillExists = skillExists;
|
|
12
|
+
exports.readSkillContent = readSkillContent;
|
|
13
|
+
exports.scanInstalledSkills = scanInstalledSkills;
|
|
14
|
+
exports.normalizeSkillSource = normalizeSkillSource;
|
|
15
|
+
exports.extractSkillName = extractSkillName;
|
|
16
|
+
exports.installSkill = installSkill;
|
|
17
|
+
exports.convertSkillsToSystemPromptXml = convertSkillsToSystemPromptXml;
|
|
18
|
+
exports.getSkillsSystemPromptFromDirectory = getSkillsSystemPromptFromDirectory;
|
|
19
|
+
exports.setupSkillsAndGetPrompt = setupSkillsAndGetPrompt;
|
|
20
|
+
const fs_1 = require("fs");
|
|
7
21
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
22
|
const node_os_1 = __importDefault(require("node:os"));
|
|
9
23
|
const node_path_1 = __importDefault(require("node:path"));
|
|
24
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
25
|
+
const debuglogger_1 = __importDefault(require("../utils/debuglogger"));
|
|
10
26
|
const constants_1 = __importDefault(require("./constants"));
|
|
27
|
+
const skillParser_1 = require("./skillParser");
|
|
28
|
+
const skillsXMLMetaDataGenerator_1 = __importDefault(require("./skillsXMLMetaDataGenerator"));
|
|
11
29
|
/**
|
|
12
30
|
* Gets the slingshot directories for both workspace and user levels.
|
|
13
31
|
* Creates the directories if they don't exist.
|
|
@@ -45,4 +63,327 @@ function getSlingshotDirectories(repoRoot) {
|
|
|
45
63
|
return result;
|
|
46
64
|
}
|
|
47
65
|
}
|
|
48
|
-
|
|
66
|
+
const dlog = (0, debuglogger_1.default)('PSAI:SkillUtils:');
|
|
67
|
+
// Extract skill-related constants from centralized constants
|
|
68
|
+
const { AGENTS_DIR, SKILLS_DIR, SKILL_DEFINITION_FILE } = constants_1.default;
|
|
69
|
+
// Map to track ongoing installations to prevent race conditions
|
|
70
|
+
const ongoingInstallations = new Map();
|
|
71
|
+
/**
|
|
72
|
+
* Validates skill name for security (prevents path traversal)
|
|
73
|
+
*/
|
|
74
|
+
function validateSkillName(skillName) {
|
|
75
|
+
// Skill name should not contain path separators or special characters
|
|
76
|
+
const validPattern = /^[a-zA-Z0-9_-]+$/;
|
|
77
|
+
return validPattern.test(skillName) && !skillName.includes('..');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validates skill source URL for security (prevents command injection)
|
|
81
|
+
*/
|
|
82
|
+
function validateSkillSource(source) {
|
|
83
|
+
if (!source || typeof source !== 'string') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const trimmed = source.trim();
|
|
87
|
+
// Check for common malicious patterns
|
|
88
|
+
const dangerousPatterns = [
|
|
89
|
+
/[;&|`$(){}[\]\\]/, // Shell metacharacters
|
|
90
|
+
/\.\./, // Path traversal
|
|
91
|
+
/^-/, // Starting with dash (could be interpreted as flag)
|
|
92
|
+
/\s/, // Whitespace (could break command parsing)
|
|
93
|
+
// eslint-disable-next-line no-control-regex
|
|
94
|
+
/[\x00-\x1f\x7f]/, // Control characters
|
|
95
|
+
];
|
|
96
|
+
for (const pattern of dangerousPatterns) {
|
|
97
|
+
if (pattern.test(trimmed)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Only allow specific URL patterns
|
|
102
|
+
const allowedPatterns = [
|
|
103
|
+
/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+(@[a-zA-Z0-9_-]+)?$/, // owner/repo@skill
|
|
104
|
+
/^github\.com\/[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+(@[a-zA-Z0-9_-]+)?$/, // github.com/owner/repo@skill
|
|
105
|
+
/^https:\/\/github\.com\/[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+(@[a-zA-Z0-9_-]+)?$/, // Full GitHub URL
|
|
106
|
+
];
|
|
107
|
+
return allowedPatterns.some((pattern) => pattern.test(trimmed));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Ensures skills directory exists
|
|
111
|
+
*/
|
|
112
|
+
async function ensureSkillsDirectory(skillsPath) {
|
|
113
|
+
await fs_1.promises.mkdir(skillsPath, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Gets the path to a skill's SKILL.md file
|
|
117
|
+
* Skills are stored in the .agents/skills subdirectory as created by npx skills CLI
|
|
118
|
+
*/
|
|
119
|
+
function getSkillFilePath(skillsPath, skillName) {
|
|
120
|
+
if (!validateSkillName(skillName)) {
|
|
121
|
+
throw new Error(`Invalid skill name: ${skillName}`);
|
|
122
|
+
}
|
|
123
|
+
return node_path_1.default.join(skillsPath, AGENTS_DIR, SKILLS_DIR, skillName, SKILL_DEFINITION_FILE);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Checks if a skill exists locally
|
|
127
|
+
*/
|
|
128
|
+
function skillExists(skillsPath, skillName) {
|
|
129
|
+
const skillFilePath = getSkillFilePath(skillsPath, skillName);
|
|
130
|
+
return node_fs_1.default.existsSync(skillFilePath);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Reads skill content and parses frontmatter using skillParser
|
|
134
|
+
*/
|
|
135
|
+
async function readSkillContent(skillsPath, skillName) {
|
|
136
|
+
const skillFilePath = getSkillFilePath(skillsPath, skillName);
|
|
137
|
+
const rawContent = await fs_1.promises.readFile(skillFilePath, 'utf-8');
|
|
138
|
+
const parsed = (0, gray_matter_1.default)(rawContent);
|
|
139
|
+
// Create SkillFrontmatter with user-friendly defaults (different from SkillMetadata)
|
|
140
|
+
const metadata = {
|
|
141
|
+
name: parsed.data.name || skillName,
|
|
142
|
+
description: parsed.data.description || 'No description provided',
|
|
143
|
+
version: parsed.data.version || '1.0.0',
|
|
144
|
+
author: parsed.data.author || 'Unknown',
|
|
145
|
+
dependencies: parsed.data.dependencies || [],
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
metadata,
|
|
149
|
+
content: parsed.content,
|
|
150
|
+
rawContent,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Scans a directory for installed skills and returns metadata
|
|
155
|
+
*/
|
|
156
|
+
async function scanInstalledSkills(skillsPath) {
|
|
157
|
+
const installedSkills = new Map();
|
|
158
|
+
try {
|
|
159
|
+
await fs_1.promises.access(skillsPath);
|
|
160
|
+
}
|
|
161
|
+
catch (_a) {
|
|
162
|
+
return installedSkills;
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
// Skills are located in .agents/skills directory (created by npx skills CLI)
|
|
166
|
+
const skillsDir = node_path_1.default.join(skillsPath, AGENTS_DIR, SKILLS_DIR);
|
|
167
|
+
dlog.info(`Scanning skills directory: ${skillsDir}`);
|
|
168
|
+
try {
|
|
169
|
+
await fs_1.promises.access(skillsDir);
|
|
170
|
+
}
|
|
171
|
+
catch (_b) {
|
|
172
|
+
dlog.info(`Skills directory does not exist: ${skillsDir}`);
|
|
173
|
+
return installedSkills;
|
|
174
|
+
}
|
|
175
|
+
const entries = await fs_1.promises.readdir(skillsDir, {
|
|
176
|
+
withFileTypes: true,
|
|
177
|
+
});
|
|
178
|
+
dlog.info(`Found entries:`, entries.map((e) => `${e.name} (${e.isDirectory() ? 'dir' : 'file'})`));
|
|
179
|
+
for (const entry of entries) {
|
|
180
|
+
if (entry.isDirectory()) {
|
|
181
|
+
const skillDir = node_path_1.default.join(skillsDir, entry.name);
|
|
182
|
+
dlog.info(`Checking skill directory: ${skillDir}`);
|
|
183
|
+
const metadata = await loadSkillMetadata(skillDir);
|
|
184
|
+
dlog.info(`Metadata loaded:`, metadata ? 'success' : 'failed');
|
|
185
|
+
if (metadata) {
|
|
186
|
+
metadata.path = skillDir;
|
|
187
|
+
installedSkills.set(entry.name, metadata);
|
|
188
|
+
dlog.info(`Added skill: ${entry.name}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
dlog.info(`Total skills found: ${installedSkills.size}`);
|
|
193
|
+
dlog.info(`Skill names:`, Array.from(installedSkills.keys()));
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
dlog.error(`Error scanning skills:`, error);
|
|
197
|
+
}
|
|
198
|
+
return installedSkills;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Load skill metadata from SKILL.md file using skillParser
|
|
202
|
+
*/
|
|
203
|
+
async function loadSkillMetadata(skillDir) {
|
|
204
|
+
const skillMdPath = node_path_1.default.join(skillDir, SKILL_DEFINITION_FILE);
|
|
205
|
+
try {
|
|
206
|
+
const fileContent = await fs_1.promises.readFile(skillMdPath, 'utf-8');
|
|
207
|
+
return (0, skillParser_1.parseSkillMetadataFromContent)(fileContent, skillDir);
|
|
208
|
+
}
|
|
209
|
+
catch (_a) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Normalizes skill source URLs to handle common formatting issues
|
|
215
|
+
*/
|
|
216
|
+
function normalizeSkillSource(source) {
|
|
217
|
+
// Validate input first for security
|
|
218
|
+
if (!validateSkillSource(source)) {
|
|
219
|
+
throw new Error(`Invalid or potentially unsafe skill source: ${source}`);
|
|
220
|
+
}
|
|
221
|
+
let normalized = source.trim();
|
|
222
|
+
// Remove .git suffix if present (common mistake)
|
|
223
|
+
normalized = normalized.replace(/\.git$/, '');
|
|
224
|
+
// Remove https:// prefix if present (npx skills prefers short format)
|
|
225
|
+
normalized = normalized.replace(/^https:\/\//, '');
|
|
226
|
+
// Remove github.com/ prefix (npx skills prefers owner/repo format)
|
|
227
|
+
normalized = normalized.replace(/^github\.com\//, '');
|
|
228
|
+
return normalized;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Extract skill name from source URL
|
|
232
|
+
*/
|
|
233
|
+
function extractSkillName(source) {
|
|
234
|
+
// Handle formats like:
|
|
235
|
+
// - github.com/owner/repo@skill
|
|
236
|
+
// - owner/repo@skill
|
|
237
|
+
// - github.com/owner/repo (use repo name)
|
|
238
|
+
const normalized = source.replace(/^github\.com\//, '');
|
|
239
|
+
let skillName;
|
|
240
|
+
if (normalized.includes('@')) {
|
|
241
|
+
skillName = normalized.split('@')[1];
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
// Use repo name if no skill specified
|
|
245
|
+
skillName = normalized.split('/')[1] || 'unknown-skill';
|
|
246
|
+
}
|
|
247
|
+
// Validate the extracted skill name for security
|
|
248
|
+
if (!validateSkillName(skillName)) {
|
|
249
|
+
throw new Error(`Invalid skill name extracted from source: ${skillName}`);
|
|
250
|
+
}
|
|
251
|
+
return skillName;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Install a skill using npx skills command (simplified)
|
|
255
|
+
*/
|
|
256
|
+
async function installSkill(options) {
|
|
257
|
+
const { source, skillsPath, timeout = 60000 } = options;
|
|
258
|
+
if (!source || typeof source !== 'string') {
|
|
259
|
+
throw new Error('Invalid skill source provided');
|
|
260
|
+
}
|
|
261
|
+
const normalizedSource = normalizeSkillSource(source);
|
|
262
|
+
const skillName = extractSkillName(normalizedSource);
|
|
263
|
+
if (!validateSkillName(skillName)) {
|
|
264
|
+
throw new Error(`Invalid skill name derived from source: ${skillName}`);
|
|
265
|
+
}
|
|
266
|
+
// Check if there's already an ongoing installation for this skill
|
|
267
|
+
if (ongoingInstallations.has(skillName)) {
|
|
268
|
+
dlog.info(`Installation for ${skillName} already in progress, waiting...`);
|
|
269
|
+
return ongoingInstallations.get(skillName);
|
|
270
|
+
}
|
|
271
|
+
// Check if already installed
|
|
272
|
+
if (skillExists(skillsPath, skillName)) {
|
|
273
|
+
const skillDir = node_path_1.default.join(skillsPath, AGENTS_DIR, SKILLS_DIR, skillName);
|
|
274
|
+
const metadata = await loadSkillMetadata(skillDir);
|
|
275
|
+
if (metadata) {
|
|
276
|
+
dlog.info(`Skill ${skillName} already installed`);
|
|
277
|
+
return metadata;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Create installation promise and track it
|
|
281
|
+
const installationPromise = performSimpleInstallation(normalizedSource, skillName, skillsPath, timeout);
|
|
282
|
+
ongoingInstallations.set(skillName, installationPromise);
|
|
283
|
+
try {
|
|
284
|
+
return await installationPromise;
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
ongoingInstallations.delete(skillName);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Simple skill installation - just run npx skills add and check result
|
|
292
|
+
*/
|
|
293
|
+
async function performSimpleInstallation(normalizedSource, skillName, skillsPath, timeout) {
|
|
294
|
+
await ensureSkillsDirectory(skillsPath);
|
|
295
|
+
try {
|
|
296
|
+
// Run the installation command safely with spawn to prevent command injection
|
|
297
|
+
const command = 'npx';
|
|
298
|
+
const args = ['skills', 'add', normalizedSource, '--yes'];
|
|
299
|
+
dlog.info(`Installing skill: ${command} ${args.join(' ')}`);
|
|
300
|
+
const { spawnSync } = await import('child_process');
|
|
301
|
+
const result = spawnSync(command, args, {
|
|
302
|
+
cwd: skillsPath,
|
|
303
|
+
timeout,
|
|
304
|
+
stdio: 'inherit', // Show output directly
|
|
305
|
+
encoding: 'utf8',
|
|
306
|
+
});
|
|
307
|
+
// Check if the command failed
|
|
308
|
+
if (result.error) {
|
|
309
|
+
throw result.error;
|
|
310
|
+
}
|
|
311
|
+
if (result.status !== 0) {
|
|
312
|
+
throw new Error(`Installation process exited with code ${result.status}`);
|
|
313
|
+
}
|
|
314
|
+
// Check if installation succeeded by looking for the skill
|
|
315
|
+
const skillDir = node_path_1.default.join(skillsPath, AGENTS_DIR, SKILLS_DIR, skillName);
|
|
316
|
+
const metadata = await loadSkillMetadata(skillDir);
|
|
317
|
+
if (metadata) {
|
|
318
|
+
dlog.info(`Successfully installed skill: ${skillName}`);
|
|
319
|
+
return metadata;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
throw new Error(`Skill installation completed but no SKILL.md found at ${skillDir}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
throw new Error(`Failed to install skill ${skillName}: ${error}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Converts skill metadata to XML format for system prompts
|
|
331
|
+
*/
|
|
332
|
+
function convertSkillsToSystemPromptXml(skills) {
|
|
333
|
+
const skillsList = skills.map((skill) => ({
|
|
334
|
+
name: skill.name,
|
|
335
|
+
description: skill.description,
|
|
336
|
+
}));
|
|
337
|
+
return (0, skillsXMLMetaDataGenerator_1.default)(skillsList);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Get skills XML from a skills directory scan
|
|
341
|
+
*/
|
|
342
|
+
async function getSkillsSystemPromptFromDirectory(skillsPath) {
|
|
343
|
+
const installedSkills = await scanInstalledSkills(skillsPath);
|
|
344
|
+
const skillsArray = Array.from(installedSkills.values());
|
|
345
|
+
return convertSkillsToSystemPromptXml(skillsArray);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Setup skills directory and get system prompt
|
|
349
|
+
* Accepts skill sources as an object mapping skill names to source configurations
|
|
350
|
+
*/
|
|
351
|
+
async function setupSkillsAndGetPrompt(skillsPath, sources, log) {
|
|
352
|
+
var _a;
|
|
353
|
+
await ensureSkillsDirectory(skillsPath);
|
|
354
|
+
if (sources) {
|
|
355
|
+
const skillEntries = Object.entries(sources);
|
|
356
|
+
if (skillEntries.length > 0) {
|
|
357
|
+
(_a = log === null || log === void 0 ? void 0 : log.info) === null || _a === void 0 ? void 0 : _a.call(log, `🚀 Installing ${skillEntries.length} skills from configuration...`);
|
|
358
|
+
await Promise.all(skillEntries.map(async ([skillName, config]) => {
|
|
359
|
+
var _a, _b, _c;
|
|
360
|
+
try {
|
|
361
|
+
// Validate the source
|
|
362
|
+
if (!config.source || !validateSkillSource(config.source)) {
|
|
363
|
+
throw new Error(`Invalid source URL: ${config.source}`);
|
|
364
|
+
}
|
|
365
|
+
const normalizedSource = normalizeSkillSource(config.source);
|
|
366
|
+
// For object format, we use the key as the skill name
|
|
367
|
+
// Append it to the source if not already present
|
|
368
|
+
let sourceWithSkill = normalizedSource;
|
|
369
|
+
if (!normalizedSource.includes('@')) {
|
|
370
|
+
sourceWithSkill = `${normalizedSource}@${skillName}`;
|
|
371
|
+
}
|
|
372
|
+
(_a = log === null || log === void 0 ? void 0 : log.info) === null || _a === void 0 ? void 0 : _a.call(log, `⬇️ Installing skill "${skillName}" from ${config.source} (${config.sourceType || 'git'})`);
|
|
373
|
+
await installSkill({
|
|
374
|
+
source: sourceWithSkill,
|
|
375
|
+
skillsPath,
|
|
376
|
+
timeout: 60000,
|
|
377
|
+
});
|
|
378
|
+
(_b = log === null || log === void 0 ? void 0 : log.info) === null || _b === void 0 ? void 0 : _b.call(log, `✅ Successfully installed skill: ${skillName}`);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
(_c = log === null || log === void 0 ? void 0 : log.error) === null || _c === void 0 ? void 0 : _c.call(log, `❌ Failed to install skill "${skillName}":`, error);
|
|
382
|
+
// Continue with other skills even if one fails
|
|
383
|
+
}
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return await getSkillsSystemPromptFromDirectory(skillsPath);
|
|
388
|
+
}
|
|
389
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NraWxscy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQTJCQSwwQ0E4Q0M7QUFhRCw4Q0FJQztBQUtELGtEQStCQztBQUtELHNEQUVDO0FBTUQsNENBZUM7QUFLRCxrQ0FHQztBQUtELDRDQXVCQztBQUtELGtEQXNEQztBQXFCRCxvREFrQkM7QUFLRCw0Q0FzQkM7QUFLRCxvQ0E4Q0M7QUF3REQsd0VBU0M7QUFLRCxnRkFNQztBQU1ELDBEQW9EQztBQXBmRCwyQkFBNEM7QUFDNUMsc0RBQXlCO0FBQ3pCLHNEQUF5QjtBQUN6QiwwREFBNkI7QUFFN0IsOERBQWlDO0FBR2pDLHVFQUErQztBQUUvQyw0REFBMEM7QUFDMUMsK0NBQThEO0FBQzlELDhGQUFxRTtBQVNyRTs7Ozs7R0FLRztBQUNILFNBQXdCLHVCQUF1QixDQUFDLFFBQWdCO0lBQzlELE1BQU0sTUFBTSxHQUdSO1FBQ0YsMEJBQTBCLEVBQUUsSUFBSTtRQUNoQyxxQkFBcUIsRUFBRSxJQUFJO0tBQzVCLENBQUM7SUFFRixJQUFJLENBQUM7UUFDSCwyQ0FBMkM7UUFDM0MsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE1BQU0scUJBQXFCLEdBQUcsbUJBQUksQ0FBQyxJQUFJLENBQ3JDLFFBQVEsRUFDUixtQkFBZSxDQUFDLGFBQWEsQ0FDOUIsQ0FBQztZQUVGLHVEQUF1RDtZQUN2RCxJQUFJLENBQUMsaUJBQUUsQ0FBQyxVQUFVLENBQUMscUJBQXFCLENBQUMsRUFBRSxDQUFDO2dCQUMxQyxpQkFBRSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzNELENBQUM7WUFFRCxNQUFNLENBQUMsMEJBQTBCLEdBQUcscUJBQXFCLENBQUM7UUFDNUQsQ0FBQztRQUVELHFFQUFxRTtRQUNyRSxNQUFNLFdBQVcsR0FB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
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PSAgentLogger } from '../PSAgentLogger';
|
|
2
|
+
import { PSAgentTool } from '../PSAgentTool';
|
|
3
|
+
import { PSSkillToolExecutionConfig, SkillExecutionResult } from '../skills/types';
|
|
4
|
+
export declare class PSSkillTool extends PSAgentTool {
|
|
5
|
+
static readonly toolName = "skill";
|
|
6
|
+
private skillsPath;
|
|
7
|
+
private allowedSkills?;
|
|
8
|
+
constructor(config: PSSkillToolExecutionConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Validates if a skill is allowed to be executed
|
|
11
|
+
*/
|
|
12
|
+
private isSkillAllowed;
|
|
13
|
+
run(input: Record<string, any>, log?: PSAgentLogger): Promise<SkillExecutionResult>;
|
|
14
|
+
}
|