@skill-toolbox/core 0.0.1
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/factory.d.mts +88 -0
- package/dist/factory.d.ts +88 -0
- package/dist/factory.js +50 -0
- package/dist/factory.js.map +1 -0
- package/dist/factory.mjs +25 -0
- package/dist/factory.mjs.map +1 -0
- package/dist/index.d.mts +126 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +249 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +218 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SourceCategory, SkillSource } from '@skill-toolbox/utils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Filesystem source configuration
|
|
5
|
+
*/
|
|
6
|
+
interface FilesystemSourceConfig {
|
|
7
|
+
type: 'filesystem';
|
|
8
|
+
/** Path to the skills directory or file */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Display name for this source */
|
|
11
|
+
name?: string;
|
|
12
|
+
/** Category override */
|
|
13
|
+
category?: SourceCategory;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Git source configuration
|
|
17
|
+
*/
|
|
18
|
+
interface GitSourceConfig {
|
|
19
|
+
type: 'git';
|
|
20
|
+
/** Git repository source (e.g., 'user/repo') */
|
|
21
|
+
source: string;
|
|
22
|
+
/** Skill path within repository ('' for root - default is root) */
|
|
23
|
+
skillPath?: string;
|
|
24
|
+
/** Display name for this source */
|
|
25
|
+
name?: string;
|
|
26
|
+
/** Category override */
|
|
27
|
+
category?: SourceCategory;
|
|
28
|
+
/** Cache directory */
|
|
29
|
+
cacheDir?: string;
|
|
30
|
+
/** Use shallow clone */
|
|
31
|
+
shallow?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Source configuration union type
|
|
35
|
+
*/
|
|
36
|
+
type SourceConfig = FilesystemSourceConfig | GitSourceConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Constructor interface for source classes
|
|
39
|
+
*/
|
|
40
|
+
interface SourceConstructor<Options> {
|
|
41
|
+
new (options: Options): SkillSource;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Filesystem source options (subset for factory)
|
|
45
|
+
*/
|
|
46
|
+
interface FilesystemSourceOptions {
|
|
47
|
+
path: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
category?: SourceCategory;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Git source options (subset for factory)
|
|
53
|
+
*/
|
|
54
|
+
interface GitSourceOptions {
|
|
55
|
+
source: string;
|
|
56
|
+
skillPath?: string;
|
|
57
|
+
name?: string;
|
|
58
|
+
category?: SourceCategory;
|
|
59
|
+
cacheDir?: string;
|
|
60
|
+
shallow?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper to create sources from configurations.
|
|
64
|
+
* Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* import { FilesystemSource } from '@skill-toolbox/filesystem-source';
|
|
69
|
+
* import { GitSource } from '@skill-toolbox/git-source';
|
|
70
|
+
* import { createSources, SkillLoader } from '@skill-toolbox/core';
|
|
71
|
+
*
|
|
72
|
+
* const sources = createSources(
|
|
73
|
+
* [
|
|
74
|
+
* { type: 'filesystem', path: './skills' },
|
|
75
|
+
* { type: 'git', source: 'user/repo' },
|
|
76
|
+
* ],
|
|
77
|
+
* { FilesystemSource, GitSource }
|
|
78
|
+
* );
|
|
79
|
+
*
|
|
80
|
+
* const loader = new SkillLoader({ sources });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function createSources(configs: SourceConfig[], imports: {
|
|
84
|
+
FilesystemSource: SourceConstructor<FilesystemSourceOptions>;
|
|
85
|
+
GitSource: SourceConstructor<GitSourceOptions>;
|
|
86
|
+
}): SkillSource[];
|
|
87
|
+
|
|
88
|
+
export { type FilesystemSourceConfig, type GitSourceConfig, type SourceConfig, createSources };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SourceCategory, SkillSource } from '@skill-toolbox/utils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Filesystem source configuration
|
|
5
|
+
*/
|
|
6
|
+
interface FilesystemSourceConfig {
|
|
7
|
+
type: 'filesystem';
|
|
8
|
+
/** Path to the skills directory or file */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Display name for this source */
|
|
11
|
+
name?: string;
|
|
12
|
+
/** Category override */
|
|
13
|
+
category?: SourceCategory;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Git source configuration
|
|
17
|
+
*/
|
|
18
|
+
interface GitSourceConfig {
|
|
19
|
+
type: 'git';
|
|
20
|
+
/** Git repository source (e.g., 'user/repo') */
|
|
21
|
+
source: string;
|
|
22
|
+
/** Skill path within repository ('' for root - default is root) */
|
|
23
|
+
skillPath?: string;
|
|
24
|
+
/** Display name for this source */
|
|
25
|
+
name?: string;
|
|
26
|
+
/** Category override */
|
|
27
|
+
category?: SourceCategory;
|
|
28
|
+
/** Cache directory */
|
|
29
|
+
cacheDir?: string;
|
|
30
|
+
/** Use shallow clone */
|
|
31
|
+
shallow?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Source configuration union type
|
|
35
|
+
*/
|
|
36
|
+
type SourceConfig = FilesystemSourceConfig | GitSourceConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Constructor interface for source classes
|
|
39
|
+
*/
|
|
40
|
+
interface SourceConstructor<Options> {
|
|
41
|
+
new (options: Options): SkillSource;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Filesystem source options (subset for factory)
|
|
45
|
+
*/
|
|
46
|
+
interface FilesystemSourceOptions {
|
|
47
|
+
path: string;
|
|
48
|
+
name?: string;
|
|
49
|
+
category?: SourceCategory;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Git source options (subset for factory)
|
|
53
|
+
*/
|
|
54
|
+
interface GitSourceOptions {
|
|
55
|
+
source: string;
|
|
56
|
+
skillPath?: string;
|
|
57
|
+
name?: string;
|
|
58
|
+
category?: SourceCategory;
|
|
59
|
+
cacheDir?: string;
|
|
60
|
+
shallow?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper to create sources from configurations.
|
|
64
|
+
* Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* import { FilesystemSource } from '@skill-toolbox/filesystem-source';
|
|
69
|
+
* import { GitSource } from '@skill-toolbox/git-source';
|
|
70
|
+
* import { createSources, SkillLoader } from '@skill-toolbox/core';
|
|
71
|
+
*
|
|
72
|
+
* const sources = createSources(
|
|
73
|
+
* [
|
|
74
|
+
* { type: 'filesystem', path: './skills' },
|
|
75
|
+
* { type: 'git', source: 'user/repo' },
|
|
76
|
+
* ],
|
|
77
|
+
* { FilesystemSource, GitSource }
|
|
78
|
+
* );
|
|
79
|
+
*
|
|
80
|
+
* const loader = new SkillLoader({ sources });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare function createSources(configs: SourceConfig[], imports: {
|
|
84
|
+
FilesystemSource: SourceConstructor<FilesystemSourceOptions>;
|
|
85
|
+
GitSource: SourceConstructor<GitSourceOptions>;
|
|
86
|
+
}): SkillSource[];
|
|
87
|
+
|
|
88
|
+
export { type FilesystemSourceConfig, type GitSourceConfig, type SourceConfig, createSources };
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/factory.ts
|
|
21
|
+
var factory_exports = {};
|
|
22
|
+
__export(factory_exports, {
|
|
23
|
+
createSources: () => createSources
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(factory_exports);
|
|
26
|
+
function createSources(configs, imports) {
|
|
27
|
+
return configs.map((config) => {
|
|
28
|
+
if (config.type === "filesystem") {
|
|
29
|
+
return new imports.FilesystemSource({
|
|
30
|
+
path: config.path,
|
|
31
|
+
name: config.name,
|
|
32
|
+
category: config.category
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
return new imports.GitSource({
|
|
36
|
+
source: config.source,
|
|
37
|
+
skillPath: config.skillPath,
|
|
38
|
+
name: config.name,
|
|
39
|
+
category: config.category,
|
|
40
|
+
cacheDir: config.cacheDir,
|
|
41
|
+
shallow: config.shallow
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
createSources
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/factory.ts"],"sourcesContent":["import type { SkillSource, SourceCategory } from '@skill-toolbox/utils';\n\n/**\n * Filesystem source configuration\n */\nexport interface FilesystemSourceConfig {\n type: 'filesystem';\n /** Path to the skills directory or file */\n path: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n}\n\n/**\n * Git source configuration\n */\nexport interface GitSourceConfig {\n type: 'git';\n /** Git repository source (e.g., 'user/repo') */\n source: string;\n /** Skill path within repository ('' for root - default is root) */\n skillPath?: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n /** Cache directory */\n cacheDir?: string;\n /** Use shallow clone */\n shallow?: boolean;\n}\n\n/**\n * Source configuration union type\n */\nexport type SourceConfig = FilesystemSourceConfig | GitSourceConfig;\n\n/**\n * Constructor interface for source classes\n */\ninterface SourceConstructor<Options> {\n new (options: Options): SkillSource;\n}\n\n/**\n * Filesystem source options (subset for factory)\n */\ninterface FilesystemSourceOptions {\n path: string;\n name?: string;\n category?: SourceCategory;\n}\n\n/**\n * Git source options (subset for factory)\n */\ninterface GitSourceOptions {\n source: string;\n skillPath?: string;\n name?: string;\n category?: SourceCategory;\n cacheDir?: string;\n shallow?: boolean;\n}\n\n/**\n * Helper to create sources from configurations.\n * Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.\n *\n * @example\n * ```typescript\n * import { FilesystemSource } from '@skill-toolbox/filesystem-source';\n * import { GitSource } from '@skill-toolbox/git-source';\n * import { createSources, SkillLoader } from '@skill-toolbox/core';\n *\n * const sources = createSources(\n * [\n * { type: 'filesystem', path: './skills' },\n * { type: 'git', source: 'user/repo' },\n * ],\n * { FilesystemSource, GitSource }\n * );\n *\n * const loader = new SkillLoader({ sources });\n * ```\n */\nexport function createSources(\n configs: SourceConfig[],\n imports: {\n FilesystemSource: SourceConstructor<FilesystemSourceOptions>;\n GitSource: SourceConstructor<GitSourceOptions>;\n }\n): SkillSource[] {\n return configs.map((config) => {\n if (config.type === 'filesystem') {\n return new imports.FilesystemSource({\n path: config.path,\n name: config.name,\n category: config.category,\n });\n } else {\n return new imports.GitSource({\n source: config.source,\n skillPath: config.skillPath,\n name: config.name,\n category: config.category,\n cacheDir: config.cacheDir,\n shallow: config.shallow,\n });\n }\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwFO,SAAS,cACd,SACA,SAIe;AACf,SAAO,QAAQ,IAAI,CAAC,WAAW;AAC7B,QAAI,OAAO,SAAS,cAAc;AAChC,aAAO,IAAI,QAAQ,iBAAiB;AAAA,QAClC,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH,OAAO;AACL,aAAO,IAAI,QAAQ,UAAU;AAAA,QAC3B,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;","names":[]}
|
package/dist/factory.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/factory.ts
|
|
2
|
+
function createSources(configs, imports) {
|
|
3
|
+
return configs.map((config) => {
|
|
4
|
+
if (config.type === "filesystem") {
|
|
5
|
+
return new imports.FilesystemSource({
|
|
6
|
+
path: config.path,
|
|
7
|
+
name: config.name,
|
|
8
|
+
category: config.category
|
|
9
|
+
});
|
|
10
|
+
} else {
|
|
11
|
+
return new imports.GitSource({
|
|
12
|
+
source: config.source,
|
|
13
|
+
skillPath: config.skillPath,
|
|
14
|
+
name: config.name,
|
|
15
|
+
category: config.category,
|
|
16
|
+
cacheDir: config.cacheDir,
|
|
17
|
+
shallow: config.shallow
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
createSources
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=factory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/factory.ts"],"sourcesContent":["import type { SkillSource, SourceCategory } from '@skill-toolbox/utils';\n\n/**\n * Filesystem source configuration\n */\nexport interface FilesystemSourceConfig {\n type: 'filesystem';\n /** Path to the skills directory or file */\n path: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n}\n\n/**\n * Git source configuration\n */\nexport interface GitSourceConfig {\n type: 'git';\n /** Git repository source (e.g., 'user/repo') */\n source: string;\n /** Skill path within repository ('' for root - default is root) */\n skillPath?: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n /** Cache directory */\n cacheDir?: string;\n /** Use shallow clone */\n shallow?: boolean;\n}\n\n/**\n * Source configuration union type\n */\nexport type SourceConfig = FilesystemSourceConfig | GitSourceConfig;\n\n/**\n * Constructor interface for source classes\n */\ninterface SourceConstructor<Options> {\n new (options: Options): SkillSource;\n}\n\n/**\n * Filesystem source options (subset for factory)\n */\ninterface FilesystemSourceOptions {\n path: string;\n name?: string;\n category?: SourceCategory;\n}\n\n/**\n * Git source options (subset for factory)\n */\ninterface GitSourceOptions {\n source: string;\n skillPath?: string;\n name?: string;\n category?: SourceCategory;\n cacheDir?: string;\n shallow?: boolean;\n}\n\n/**\n * Helper to create sources from configurations.\n * Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.\n *\n * @example\n * ```typescript\n * import { FilesystemSource } from '@skill-toolbox/filesystem-source';\n * import { GitSource } from '@skill-toolbox/git-source';\n * import { createSources, SkillLoader } from '@skill-toolbox/core';\n *\n * const sources = createSources(\n * [\n * { type: 'filesystem', path: './skills' },\n * { type: 'git', source: 'user/repo' },\n * ],\n * { FilesystemSource, GitSource }\n * );\n *\n * const loader = new SkillLoader({ sources });\n * ```\n */\nexport function createSources(\n configs: SourceConfig[],\n imports: {\n FilesystemSource: SourceConstructor<FilesystemSourceOptions>;\n GitSource: SourceConstructor<GitSourceOptions>;\n }\n): SkillSource[] {\n return configs.map((config) => {\n if (config.type === 'filesystem') {\n return new imports.FilesystemSource({\n path: config.path,\n name: config.name,\n category: config.category,\n });\n } else {\n return new imports.GitSource({\n source: config.source,\n skillPath: config.skillPath,\n name: config.name,\n category: config.category,\n cacheDir: config.cacheDir,\n shallow: config.shallow,\n });\n }\n });\n}\n"],"mappings":";AAwFO,SAAS,cACd,SACA,SAIe;AACf,SAAO,QAAQ,IAAI,CAAC,WAAW;AAC7B,QAAI,OAAO,SAAS,cAAc;AAChC,aAAO,IAAI,QAAQ,iBAAiB;AAAA,QAClC,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH,OAAO;AACL,aAAO,IAAI,QAAQ,UAAU;AAAA,QAC3B,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,SAAS,OAAO;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { SkillPlugin, SkillIR, Skill, SkillSource } from '@skill-toolbox/utils';
|
|
2
|
+
export { FilesystemSourceConfig, GitSourceConfig, SourceConfig, createSources } from './factory.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Core skill parser
|
|
6
|
+
*/
|
|
7
|
+
declare class SkillParser {
|
|
8
|
+
private pluginManager;
|
|
9
|
+
constructor(plugins?: SkillPlugin[]);
|
|
10
|
+
/**
|
|
11
|
+
* Parse markdown to IR (exposed for testing)
|
|
12
|
+
*/
|
|
13
|
+
parseToIR(markdown: string): Promise<SkillIR>;
|
|
14
|
+
/**
|
|
15
|
+
* Parse markdown to Skill object
|
|
16
|
+
*/
|
|
17
|
+
parse(markdown: string): Promise<Skill>;
|
|
18
|
+
/**
|
|
19
|
+
* Add a plugin
|
|
20
|
+
*/
|
|
21
|
+
use(plugin: SkillPlugin): this;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a plugin is registered
|
|
24
|
+
*/
|
|
25
|
+
hasPlugin(name: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Convert IR to Skill object
|
|
28
|
+
*/
|
|
29
|
+
private irToSkill;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Plugin manager for registering and executing plugins
|
|
34
|
+
*/
|
|
35
|
+
declare class PluginManager {
|
|
36
|
+
private plugins;
|
|
37
|
+
/**
|
|
38
|
+
* Register a plugin
|
|
39
|
+
*/
|
|
40
|
+
register(plugin: SkillPlugin): void;
|
|
41
|
+
/**
|
|
42
|
+
* Register multiple plugins
|
|
43
|
+
*/
|
|
44
|
+
registerAll(plugins: SkillPlugin[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Get a plugin by name
|
|
47
|
+
*/
|
|
48
|
+
get(name: string): SkillPlugin | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Process IR through all registered plugins
|
|
51
|
+
*/
|
|
52
|
+
process(ir: SkillIR): Promise<SkillIR>;
|
|
53
|
+
/**
|
|
54
|
+
* Check if a plugin is registered
|
|
55
|
+
*/
|
|
56
|
+
has(name: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Remove a plugin
|
|
59
|
+
*/
|
|
60
|
+
remove(name: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Clear all plugins
|
|
63
|
+
*/
|
|
64
|
+
clear(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get all plugin names
|
|
67
|
+
*/
|
|
68
|
+
getPluginNames(): string[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Options for SkillLoader
|
|
73
|
+
*/
|
|
74
|
+
interface SkillLoaderOptions {
|
|
75
|
+
/** Sources to load skills from (each bound to a specific repo/path) */
|
|
76
|
+
sources: SkillSource[];
|
|
77
|
+
/** Custom parser (optional) */
|
|
78
|
+
parser?: SkillParser;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result of loading all skills
|
|
82
|
+
*/
|
|
83
|
+
interface LoadAllResult {
|
|
84
|
+
/** Successfully loaded skills (key: full name like 'user/repo/skill-name') */
|
|
85
|
+
skills: Map<string, Skill>;
|
|
86
|
+
/** Errors encountered (key: path or source identifier) */
|
|
87
|
+
errors: Map<string, Error>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Unified skill loader that works with bound SkillSource instances
|
|
91
|
+
*
|
|
92
|
+
* Usage:
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const loader = new SkillLoader({
|
|
95
|
+
* sources: [
|
|
96
|
+
* new GitSource({ source: 'user/repo', skillPath: 'skills' }),
|
|
97
|
+
* new FilesystemSource({ path: './local-skills' }),
|
|
98
|
+
* ],
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* const { skills, errors } = await loader.loadAll();
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare class SkillLoader {
|
|
105
|
+
private sources;
|
|
106
|
+
private parser;
|
|
107
|
+
constructor(options: SkillLoaderOptions);
|
|
108
|
+
/**
|
|
109
|
+
* Load skills from all configured sources
|
|
110
|
+
*
|
|
111
|
+
* - Skills are named with source prefix: 'source-id/skill-name'
|
|
112
|
+
* - Failed sources are skipped (doesn't stop loading other sources)
|
|
113
|
+
* - All sources are cleaned up automatically
|
|
114
|
+
*
|
|
115
|
+
* @returns Loaded skills and errors
|
|
116
|
+
*/
|
|
117
|
+
loadAll(): Promise<LoadAllResult>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @skill-toolbox/core
|
|
122
|
+
* Core parsing engine and plugin system
|
|
123
|
+
*/
|
|
124
|
+
declare const VERSION = "1.0.0";
|
|
125
|
+
|
|
126
|
+
export { type LoadAllResult, PluginManager, SkillLoader, type SkillLoaderOptions, SkillParser, VERSION };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { SkillPlugin, SkillIR, Skill, SkillSource } from '@skill-toolbox/utils';
|
|
2
|
+
export { FilesystemSourceConfig, GitSourceConfig, SourceConfig, createSources } from './factory.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Core skill parser
|
|
6
|
+
*/
|
|
7
|
+
declare class SkillParser {
|
|
8
|
+
private pluginManager;
|
|
9
|
+
constructor(plugins?: SkillPlugin[]);
|
|
10
|
+
/**
|
|
11
|
+
* Parse markdown to IR (exposed for testing)
|
|
12
|
+
*/
|
|
13
|
+
parseToIR(markdown: string): Promise<SkillIR>;
|
|
14
|
+
/**
|
|
15
|
+
* Parse markdown to Skill object
|
|
16
|
+
*/
|
|
17
|
+
parse(markdown: string): Promise<Skill>;
|
|
18
|
+
/**
|
|
19
|
+
* Add a plugin
|
|
20
|
+
*/
|
|
21
|
+
use(plugin: SkillPlugin): this;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a plugin is registered
|
|
24
|
+
*/
|
|
25
|
+
hasPlugin(name: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Convert IR to Skill object
|
|
28
|
+
*/
|
|
29
|
+
private irToSkill;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Plugin manager for registering and executing plugins
|
|
34
|
+
*/
|
|
35
|
+
declare class PluginManager {
|
|
36
|
+
private plugins;
|
|
37
|
+
/**
|
|
38
|
+
* Register a plugin
|
|
39
|
+
*/
|
|
40
|
+
register(plugin: SkillPlugin): void;
|
|
41
|
+
/**
|
|
42
|
+
* Register multiple plugins
|
|
43
|
+
*/
|
|
44
|
+
registerAll(plugins: SkillPlugin[]): void;
|
|
45
|
+
/**
|
|
46
|
+
* Get a plugin by name
|
|
47
|
+
*/
|
|
48
|
+
get(name: string): SkillPlugin | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Process IR through all registered plugins
|
|
51
|
+
*/
|
|
52
|
+
process(ir: SkillIR): Promise<SkillIR>;
|
|
53
|
+
/**
|
|
54
|
+
* Check if a plugin is registered
|
|
55
|
+
*/
|
|
56
|
+
has(name: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Remove a plugin
|
|
59
|
+
*/
|
|
60
|
+
remove(name: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Clear all plugins
|
|
63
|
+
*/
|
|
64
|
+
clear(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Get all plugin names
|
|
67
|
+
*/
|
|
68
|
+
getPluginNames(): string[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Options for SkillLoader
|
|
73
|
+
*/
|
|
74
|
+
interface SkillLoaderOptions {
|
|
75
|
+
/** Sources to load skills from (each bound to a specific repo/path) */
|
|
76
|
+
sources: SkillSource[];
|
|
77
|
+
/** Custom parser (optional) */
|
|
78
|
+
parser?: SkillParser;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result of loading all skills
|
|
82
|
+
*/
|
|
83
|
+
interface LoadAllResult {
|
|
84
|
+
/** Successfully loaded skills (key: full name like 'user/repo/skill-name') */
|
|
85
|
+
skills: Map<string, Skill>;
|
|
86
|
+
/** Errors encountered (key: path or source identifier) */
|
|
87
|
+
errors: Map<string, Error>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Unified skill loader that works with bound SkillSource instances
|
|
91
|
+
*
|
|
92
|
+
* Usage:
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const loader = new SkillLoader({
|
|
95
|
+
* sources: [
|
|
96
|
+
* new GitSource({ source: 'user/repo', skillPath: 'skills' }),
|
|
97
|
+
* new FilesystemSource({ path: './local-skills' }),
|
|
98
|
+
* ],
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* const { skills, errors } = await loader.loadAll();
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare class SkillLoader {
|
|
105
|
+
private sources;
|
|
106
|
+
private parser;
|
|
107
|
+
constructor(options: SkillLoaderOptions);
|
|
108
|
+
/**
|
|
109
|
+
* Load skills from all configured sources
|
|
110
|
+
*
|
|
111
|
+
* - Skills are named with source prefix: 'source-id/skill-name'
|
|
112
|
+
* - Failed sources are skipped (doesn't stop loading other sources)
|
|
113
|
+
* - All sources are cleaned up automatically
|
|
114
|
+
*
|
|
115
|
+
* @returns Loaded skills and errors
|
|
116
|
+
*/
|
|
117
|
+
loadAll(): Promise<LoadAllResult>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @skill-toolbox/core
|
|
122
|
+
* Core parsing engine and plugin system
|
|
123
|
+
*/
|
|
124
|
+
declare const VERSION = "1.0.0";
|
|
125
|
+
|
|
126
|
+
export { type LoadAllResult, PluginManager, SkillLoader, type SkillLoaderOptions, SkillParser, VERSION };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PluginManager: () => PluginManager,
|
|
24
|
+
SkillLoader: () => SkillLoader,
|
|
25
|
+
SkillParser: () => SkillParser,
|
|
26
|
+
VERSION: () => VERSION,
|
|
27
|
+
createSources: () => createSources
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/parser/SkillParser.ts
|
|
32
|
+
var import_marked = require("marked");
|
|
33
|
+
|
|
34
|
+
// src/plugin/PluginManager.ts
|
|
35
|
+
var import_utils = require("@skill-toolbox/utils");
|
|
36
|
+
var PluginManager = class {
|
|
37
|
+
plugins = /* @__PURE__ */ new Map();
|
|
38
|
+
/**
|
|
39
|
+
* Register a plugin
|
|
40
|
+
*/
|
|
41
|
+
register(plugin) {
|
|
42
|
+
if (this.plugins.has(plugin.name)) {
|
|
43
|
+
throw new import_utils.PluginError(plugin.name, "Plugin already registered");
|
|
44
|
+
}
|
|
45
|
+
this.plugins.set(plugin.name, plugin);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Register multiple plugins
|
|
49
|
+
*/
|
|
50
|
+
registerAll(plugins) {
|
|
51
|
+
plugins.forEach((plugin) => this.register(plugin));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get a plugin by name
|
|
55
|
+
*/
|
|
56
|
+
get(name) {
|
|
57
|
+
return this.plugins.get(name);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Process IR through all registered plugins
|
|
61
|
+
*/
|
|
62
|
+
async process(ir) {
|
|
63
|
+
let result = ir;
|
|
64
|
+
for (const plugin of this.plugins.values()) {
|
|
65
|
+
try {
|
|
66
|
+
result = await plugin.parse(result);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw new import_utils.PluginError(
|
|
69
|
+
plugin.name,
|
|
70
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
71
|
+
error instanceof Error ? error : void 0
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if a plugin is registered
|
|
79
|
+
*/
|
|
80
|
+
has(name) {
|
|
81
|
+
return this.plugins.has(name);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Remove a plugin
|
|
85
|
+
*/
|
|
86
|
+
remove(name) {
|
|
87
|
+
return this.plugins.delete(name);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Clear all plugins
|
|
91
|
+
*/
|
|
92
|
+
clear() {
|
|
93
|
+
this.plugins.clear();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get all plugin names
|
|
97
|
+
*/
|
|
98
|
+
getPluginNames() {
|
|
99
|
+
return Array.from(this.plugins.keys());
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/parser/SkillParser.ts
|
|
104
|
+
var SkillParser = class {
|
|
105
|
+
pluginManager;
|
|
106
|
+
constructor(plugins) {
|
|
107
|
+
this.pluginManager = new PluginManager();
|
|
108
|
+
if (plugins) {
|
|
109
|
+
this.pluginManager.registerAll(plugins);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Parse markdown to IR (exposed for testing)
|
|
114
|
+
*/
|
|
115
|
+
async parseToIR(markdown) {
|
|
116
|
+
const frontmatterMatch = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
117
|
+
const frontmatter = frontmatterMatch?.[1];
|
|
118
|
+
const tokens = import_marked.marked.lexer(markdown);
|
|
119
|
+
return {
|
|
120
|
+
frontmatter,
|
|
121
|
+
tokens,
|
|
122
|
+
raw: markdown
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parse markdown to Skill object
|
|
127
|
+
*/
|
|
128
|
+
async parse(markdown) {
|
|
129
|
+
const ir = await this.parseToIR(markdown);
|
|
130
|
+
const processedIR = await this.pluginManager.process(ir);
|
|
131
|
+
return this.irToSkill(processedIR);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Add a plugin
|
|
135
|
+
*/
|
|
136
|
+
use(plugin) {
|
|
137
|
+
this.pluginManager.register(plugin);
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if a plugin is registered
|
|
142
|
+
*/
|
|
143
|
+
hasPlugin(name) {
|
|
144
|
+
return this.pluginManager.has(name);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Convert IR to Skill object
|
|
148
|
+
*/
|
|
149
|
+
irToSkill(ir) {
|
|
150
|
+
return {
|
|
151
|
+
metadata: ir.metadata || { name: "", version: "" },
|
|
152
|
+
sections: ir.sections || [],
|
|
153
|
+
codeBlocks: ir.codeBlocks || [],
|
|
154
|
+
dependencies: ir.dependencies || [],
|
|
155
|
+
references: ir.references || [],
|
|
156
|
+
raw: {
|
|
157
|
+
markdown: ir.raw
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/SkillLoader.ts
|
|
164
|
+
var SkillLoader = class {
|
|
165
|
+
sources;
|
|
166
|
+
parser;
|
|
167
|
+
constructor(options) {
|
|
168
|
+
this.sources = options.sources;
|
|
169
|
+
this.parser = options.parser || new SkillParser();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Load skills from all configured sources
|
|
173
|
+
*
|
|
174
|
+
* - Skills are named with source prefix: 'source-id/skill-name'
|
|
175
|
+
* - Failed sources are skipped (doesn't stop loading other sources)
|
|
176
|
+
* - All sources are cleaned up automatically
|
|
177
|
+
*
|
|
178
|
+
* @returns Loaded skills and errors
|
|
179
|
+
*/
|
|
180
|
+
async loadAll() {
|
|
181
|
+
const skills = /* @__PURE__ */ new Map();
|
|
182
|
+
const errors = /* @__PURE__ */ new Map();
|
|
183
|
+
for (const source of this.sources) {
|
|
184
|
+
try {
|
|
185
|
+
const result = await source.load();
|
|
186
|
+
for (const skillData of result.skills) {
|
|
187
|
+
try {
|
|
188
|
+
const skill = await this.parser.parse(skillData.content);
|
|
189
|
+
skills.set(skillData.name, skill);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
errors.set(
|
|
192
|
+
skillData.path,
|
|
193
|
+
error instanceof Error ? error : new Error(String(error))
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (const err of result.errors) {
|
|
198
|
+
errors.set(err.path, err.error);
|
|
199
|
+
}
|
|
200
|
+
} catch (error) {
|
|
201
|
+
const info = source.getSourceInfo();
|
|
202
|
+
errors.set(
|
|
203
|
+
info.identifier,
|
|
204
|
+
error instanceof Error ? error : new Error(String(error))
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
await Promise.all(
|
|
209
|
+
this.sources.map(
|
|
210
|
+
(s) => s.cleanup().catch((e) => console.warn("Cleanup failed:", e))
|
|
211
|
+
)
|
|
212
|
+
);
|
|
213
|
+
return { skills, errors };
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// src/factory.ts
|
|
218
|
+
function createSources(configs, imports) {
|
|
219
|
+
return configs.map((config) => {
|
|
220
|
+
if (config.type === "filesystem") {
|
|
221
|
+
return new imports.FilesystemSource({
|
|
222
|
+
path: config.path,
|
|
223
|
+
name: config.name,
|
|
224
|
+
category: config.category
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
return new imports.GitSource({
|
|
228
|
+
source: config.source,
|
|
229
|
+
skillPath: config.skillPath,
|
|
230
|
+
name: config.name,
|
|
231
|
+
category: config.category,
|
|
232
|
+
cacheDir: config.cacheDir,
|
|
233
|
+
shallow: config.shallow
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/index.ts
|
|
240
|
+
var VERSION = "1.0.0";
|
|
241
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
242
|
+
0 && (module.exports = {
|
|
243
|
+
PluginManager,
|
|
244
|
+
SkillLoader,
|
|
245
|
+
SkillParser,
|
|
246
|
+
VERSION,
|
|
247
|
+
createSources
|
|
248
|
+
});
|
|
249
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/parser/SkillParser.ts","../src/plugin/PluginManager.ts","../src/SkillLoader.ts","../src/factory.ts"],"sourcesContent":["/**\n * @skill-toolbox/core\n * Core parsing engine and plugin system\n */\n\nexport const VERSION = '1.0.0';\n\nexport { SkillParser } from './parser';\nexport { PluginManager } from './plugin';\nexport { SkillLoader } from './SkillLoader';\nexport type { SkillLoaderOptions, LoadAllResult } from './SkillLoader';\nexport { createSources } from './factory';\nexport type { SourceConfig, FilesystemSourceConfig, GitSourceConfig } from './factory';\n","import { marked } from 'marked';\nimport type { Skill, SkillIR, SkillPlugin } from '@skill-toolbox/utils';\nimport { PluginManager } from '../plugin';\n\n/**\n * Core skill parser\n */\nexport class SkillParser {\n private pluginManager: PluginManager;\n\n constructor(plugins?: SkillPlugin[]) {\n this.pluginManager = new PluginManager();\n if (plugins) {\n this.pluginManager.registerAll(plugins);\n }\n }\n\n /**\n * Parse markdown to IR (exposed for testing)\n */\n async parseToIR(markdown: string): Promise<SkillIR> {\n // Extract frontmatter (support both \\n and \\r\\n line endings)\n const frontmatterMatch = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/);\n const frontmatter = frontmatterMatch?.[1];\n\n // Parse markdown to tokens\n const tokens = marked.lexer(markdown);\n\n return {\n frontmatter,\n tokens,\n raw: markdown\n };\n }\n\n /**\n * Parse markdown to Skill object\n */\n async parse(markdown: string): Promise<Skill> {\n // 1. Parse to IR\n const ir = await this.parseToIR(markdown);\n\n // 2. Process through plugins\n const processedIR = await this.pluginManager.process(ir);\n\n // 3. Convert to Skill object\n return this.irToSkill(processedIR);\n }\n\n /**\n * Add a plugin\n */\n use(plugin: SkillPlugin): this {\n this.pluginManager.register(plugin);\n return this;\n }\n\n /**\n * Check if a plugin is registered\n */\n hasPlugin(name: string): boolean {\n return this.pluginManager.has(name);\n }\n\n /**\n * Convert IR to Skill object\n */\n private irToSkill(ir: SkillIR): Skill {\n return {\n metadata: (ir.metadata as any) || { name: '', version: '' },\n sections: (ir.sections as any) || [],\n codeBlocks: (ir.codeBlocks as any) || [],\n dependencies: (ir.dependencies as any) || [],\n references: (ir.references as any) || [],\n raw: {\n markdown: ir.raw\n }\n };\n }\n}\n","import type { SkillPlugin, SkillIR } from '@skill-toolbox/utils';\nimport { PluginError } from '@skill-toolbox/utils';\n\n/**\n * Plugin manager for registering and executing plugins\n */\nexport class PluginManager {\n private plugins: Map<string, SkillPlugin> = new Map();\n\n /**\n * Register a plugin\n */\n register(plugin: SkillPlugin): void {\n if (this.plugins.has(plugin.name)) {\n throw new PluginError(plugin.name, 'Plugin already registered');\n }\n this.plugins.set(plugin.name, plugin);\n }\n\n /**\n * Register multiple plugins\n */\n registerAll(plugins: SkillPlugin[]): void {\n plugins.forEach(plugin => this.register(plugin));\n }\n\n /**\n * Get a plugin by name\n */\n get(name: string): SkillPlugin | undefined {\n return this.plugins.get(name);\n }\n\n /**\n * Process IR through all registered plugins\n */\n async process(ir: SkillIR): Promise<SkillIR> {\n let result = ir;\n\n for (const plugin of this.plugins.values()) {\n try {\n result = await plugin.parse(result);\n } catch (error) {\n throw new PluginError(\n plugin.name,\n error instanceof Error ? error.message : 'Unknown error',\n error instanceof Error ? error : undefined\n );\n }\n }\n\n return result;\n }\n\n /**\n * Check if a plugin is registered\n */\n has(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /**\n * Remove a plugin\n */\n remove(name: string): boolean {\n return this.plugins.delete(name);\n }\n\n /**\n * Clear all plugins\n */\n clear(): void {\n this.plugins.clear();\n }\n\n /**\n * Get all plugin names\n */\n getPluginNames(): string[] {\n return Array.from(this.plugins.keys());\n }\n}\n","import type { Skill, SkillSource } from '@skill-toolbox/utils';\nimport { SkillParser } from './parser';\n\n/**\n * Options for SkillLoader\n */\nexport interface SkillLoaderOptions {\n /** Sources to load skills from (each bound to a specific repo/path) */\n sources: SkillSource[];\n /** Custom parser (optional) */\n parser?: SkillParser;\n}\n\n/**\n * Result of loading all skills\n */\nexport interface LoadAllResult {\n /** Successfully loaded skills (key: full name like 'user/repo/skill-name') */\n skills: Map<string, Skill>;\n /** Errors encountered (key: path or source identifier) */\n errors: Map<string, Error>;\n}\n\n/**\n * Unified skill loader that works with bound SkillSource instances\n *\n * Usage:\n * ```typescript\n * const loader = new SkillLoader({\n * sources: [\n * new GitSource({ source: 'user/repo', skillPath: 'skills' }),\n * new FilesystemSource({ path: './local-skills' }),\n * ],\n * });\n *\n * const { skills, errors } = await loader.loadAll();\n * ```\n */\nexport class SkillLoader {\n private sources: SkillSource[];\n private parser: SkillParser;\n\n constructor(options: SkillLoaderOptions) {\n this.sources = options.sources;\n this.parser = options.parser || new SkillParser();\n }\n\n /**\n * Load skills from all configured sources\n *\n * - Skills are named with source prefix: 'source-id/skill-name'\n * - Failed sources are skipped (doesn't stop loading other sources)\n * - All sources are cleaned up automatically\n *\n * @returns Loaded skills and errors\n */\n async loadAll(): Promise<LoadAllResult> {\n const skills = new Map<string, Skill>();\n const errors = new Map<string, Error>();\n\n // Load from each source\n for (const source of this.sources) {\n try {\n const result = await source.load();\n\n // Parse each skill\n for (const skillData of result.skills) {\n try {\n const skill = await this.parser.parse(skillData.content);\n skills.set(skillData.name, skill);\n } catch (error) {\n errors.set(\n skillData.path,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Collect file-level errors\n for (const err of result.errors) {\n errors.set(err.path, err.error);\n }\n } catch (error) {\n // Source-level error\n const info = source.getSourceInfo();\n errors.set(\n info.identifier,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Cleanup all sources\n await Promise.all(\n this.sources.map((s) =>\n s.cleanup().catch((e) => console.warn('Cleanup failed:', e))\n )\n );\n\n return { skills, errors };\n }\n}\n","import type { SkillSource, SourceCategory } from '@skill-toolbox/utils';\n\n/**\n * Filesystem source configuration\n */\nexport interface FilesystemSourceConfig {\n type: 'filesystem';\n /** Path to the skills directory or file */\n path: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n}\n\n/**\n * Git source configuration\n */\nexport interface GitSourceConfig {\n type: 'git';\n /** Git repository source (e.g., 'user/repo') */\n source: string;\n /** Skill path within repository ('' for root - default is root) */\n skillPath?: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n /** Cache directory */\n cacheDir?: string;\n /** Use shallow clone */\n shallow?: boolean;\n}\n\n/**\n * Source configuration union type\n */\nexport type SourceConfig = FilesystemSourceConfig | GitSourceConfig;\n\n/**\n * Constructor interface for source classes\n */\ninterface SourceConstructor<Options> {\n new (options: Options): SkillSource;\n}\n\n/**\n * Filesystem source options (subset for factory)\n */\ninterface FilesystemSourceOptions {\n path: string;\n name?: string;\n category?: SourceCategory;\n}\n\n/**\n * Git source options (subset for factory)\n */\ninterface GitSourceOptions {\n source: string;\n skillPath?: string;\n name?: string;\n category?: SourceCategory;\n cacheDir?: string;\n shallow?: boolean;\n}\n\n/**\n * Helper to create sources from configurations.\n * Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.\n *\n * @example\n * ```typescript\n * import { FilesystemSource } from '@skill-toolbox/filesystem-source';\n * import { GitSource } from '@skill-toolbox/git-source';\n * import { createSources, SkillLoader } from '@skill-toolbox/core';\n *\n * const sources = createSources(\n * [\n * { type: 'filesystem', path: './skills' },\n * { type: 'git', source: 'user/repo' },\n * ],\n * { FilesystemSource, GitSource }\n * );\n *\n * const loader = new SkillLoader({ sources });\n * ```\n */\nexport function createSources(\n configs: SourceConfig[],\n imports: {\n FilesystemSource: SourceConstructor<FilesystemSourceOptions>;\n GitSource: SourceConstructor<GitSourceOptions>;\n }\n): SkillSource[] {\n return configs.map((config) => {\n if (config.type === 'filesystem') {\n return new imports.FilesystemSource({\n path: config.path,\n name: config.name,\n category: config.category,\n });\n } else {\n return new imports.GitSource({\n source: config.source,\n skillPath: config.skillPath,\n name: config.name,\n category: config.category,\n cacheDir: config.cacheDir,\n shallow: config.shallow,\n });\n }\n });\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// src/parser/SkillParser.ts
|
|
2
|
+
import { marked } from "marked";
|
|
3
|
+
|
|
4
|
+
// src/plugin/PluginManager.ts
|
|
5
|
+
import { PluginError } from "@skill-toolbox/utils";
|
|
6
|
+
var PluginManager = class {
|
|
7
|
+
plugins = /* @__PURE__ */ new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Register a plugin
|
|
10
|
+
*/
|
|
11
|
+
register(plugin) {
|
|
12
|
+
if (this.plugins.has(plugin.name)) {
|
|
13
|
+
throw new PluginError(plugin.name, "Plugin already registered");
|
|
14
|
+
}
|
|
15
|
+
this.plugins.set(plugin.name, plugin);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register multiple plugins
|
|
19
|
+
*/
|
|
20
|
+
registerAll(plugins) {
|
|
21
|
+
plugins.forEach((plugin) => this.register(plugin));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get a plugin by name
|
|
25
|
+
*/
|
|
26
|
+
get(name) {
|
|
27
|
+
return this.plugins.get(name);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Process IR through all registered plugins
|
|
31
|
+
*/
|
|
32
|
+
async process(ir) {
|
|
33
|
+
let result = ir;
|
|
34
|
+
for (const plugin of this.plugins.values()) {
|
|
35
|
+
try {
|
|
36
|
+
result = await plugin.parse(result);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
throw new PluginError(
|
|
39
|
+
plugin.name,
|
|
40
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
41
|
+
error instanceof Error ? error : void 0
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if a plugin is registered
|
|
49
|
+
*/
|
|
50
|
+
has(name) {
|
|
51
|
+
return this.plugins.has(name);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Remove a plugin
|
|
55
|
+
*/
|
|
56
|
+
remove(name) {
|
|
57
|
+
return this.plugins.delete(name);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Clear all plugins
|
|
61
|
+
*/
|
|
62
|
+
clear() {
|
|
63
|
+
this.plugins.clear();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all plugin names
|
|
67
|
+
*/
|
|
68
|
+
getPluginNames() {
|
|
69
|
+
return Array.from(this.plugins.keys());
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// src/parser/SkillParser.ts
|
|
74
|
+
var SkillParser = class {
|
|
75
|
+
pluginManager;
|
|
76
|
+
constructor(plugins) {
|
|
77
|
+
this.pluginManager = new PluginManager();
|
|
78
|
+
if (plugins) {
|
|
79
|
+
this.pluginManager.registerAll(plugins);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parse markdown to IR (exposed for testing)
|
|
84
|
+
*/
|
|
85
|
+
async parseToIR(markdown) {
|
|
86
|
+
const frontmatterMatch = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
87
|
+
const frontmatter = frontmatterMatch?.[1];
|
|
88
|
+
const tokens = marked.lexer(markdown);
|
|
89
|
+
return {
|
|
90
|
+
frontmatter,
|
|
91
|
+
tokens,
|
|
92
|
+
raw: markdown
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Parse markdown to Skill object
|
|
97
|
+
*/
|
|
98
|
+
async parse(markdown) {
|
|
99
|
+
const ir = await this.parseToIR(markdown);
|
|
100
|
+
const processedIR = await this.pluginManager.process(ir);
|
|
101
|
+
return this.irToSkill(processedIR);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Add a plugin
|
|
105
|
+
*/
|
|
106
|
+
use(plugin) {
|
|
107
|
+
this.pluginManager.register(plugin);
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if a plugin is registered
|
|
112
|
+
*/
|
|
113
|
+
hasPlugin(name) {
|
|
114
|
+
return this.pluginManager.has(name);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Convert IR to Skill object
|
|
118
|
+
*/
|
|
119
|
+
irToSkill(ir) {
|
|
120
|
+
return {
|
|
121
|
+
metadata: ir.metadata || { name: "", version: "" },
|
|
122
|
+
sections: ir.sections || [],
|
|
123
|
+
codeBlocks: ir.codeBlocks || [],
|
|
124
|
+
dependencies: ir.dependencies || [],
|
|
125
|
+
references: ir.references || [],
|
|
126
|
+
raw: {
|
|
127
|
+
markdown: ir.raw
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/SkillLoader.ts
|
|
134
|
+
var SkillLoader = class {
|
|
135
|
+
sources;
|
|
136
|
+
parser;
|
|
137
|
+
constructor(options) {
|
|
138
|
+
this.sources = options.sources;
|
|
139
|
+
this.parser = options.parser || new SkillParser();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Load skills from all configured sources
|
|
143
|
+
*
|
|
144
|
+
* - Skills are named with source prefix: 'source-id/skill-name'
|
|
145
|
+
* - Failed sources are skipped (doesn't stop loading other sources)
|
|
146
|
+
* - All sources are cleaned up automatically
|
|
147
|
+
*
|
|
148
|
+
* @returns Loaded skills and errors
|
|
149
|
+
*/
|
|
150
|
+
async loadAll() {
|
|
151
|
+
const skills = /* @__PURE__ */ new Map();
|
|
152
|
+
const errors = /* @__PURE__ */ new Map();
|
|
153
|
+
for (const source of this.sources) {
|
|
154
|
+
try {
|
|
155
|
+
const result = await source.load();
|
|
156
|
+
for (const skillData of result.skills) {
|
|
157
|
+
try {
|
|
158
|
+
const skill = await this.parser.parse(skillData.content);
|
|
159
|
+
skills.set(skillData.name, skill);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
errors.set(
|
|
162
|
+
skillData.path,
|
|
163
|
+
error instanceof Error ? error : new Error(String(error))
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const err of result.errors) {
|
|
168
|
+
errors.set(err.path, err.error);
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
const info = source.getSourceInfo();
|
|
172
|
+
errors.set(
|
|
173
|
+
info.identifier,
|
|
174
|
+
error instanceof Error ? error : new Error(String(error))
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await Promise.all(
|
|
179
|
+
this.sources.map(
|
|
180
|
+
(s) => s.cleanup().catch((e) => console.warn("Cleanup failed:", e))
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
return { skills, errors };
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/factory.ts
|
|
188
|
+
function createSources(configs, imports) {
|
|
189
|
+
return configs.map((config) => {
|
|
190
|
+
if (config.type === "filesystem") {
|
|
191
|
+
return new imports.FilesystemSource({
|
|
192
|
+
path: config.path,
|
|
193
|
+
name: config.name,
|
|
194
|
+
category: config.category
|
|
195
|
+
});
|
|
196
|
+
} else {
|
|
197
|
+
return new imports.GitSource({
|
|
198
|
+
source: config.source,
|
|
199
|
+
skillPath: config.skillPath,
|
|
200
|
+
name: config.name,
|
|
201
|
+
category: config.category,
|
|
202
|
+
cacheDir: config.cacheDir,
|
|
203
|
+
shallow: config.shallow
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/index.ts
|
|
210
|
+
var VERSION = "1.0.0";
|
|
211
|
+
export {
|
|
212
|
+
PluginManager,
|
|
213
|
+
SkillLoader,
|
|
214
|
+
SkillParser,
|
|
215
|
+
VERSION,
|
|
216
|
+
createSources
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parser/SkillParser.ts","../src/plugin/PluginManager.ts","../src/SkillLoader.ts","../src/factory.ts","../src/index.ts"],"sourcesContent":["import { marked } from 'marked';\nimport type { Skill, SkillIR, SkillPlugin } from '@skill-toolbox/utils';\nimport { PluginManager } from '../plugin';\n\n/**\n * Core skill parser\n */\nexport class SkillParser {\n private pluginManager: PluginManager;\n\n constructor(plugins?: SkillPlugin[]) {\n this.pluginManager = new PluginManager();\n if (plugins) {\n this.pluginManager.registerAll(plugins);\n }\n }\n\n /**\n * Parse markdown to IR (exposed for testing)\n */\n async parseToIR(markdown: string): Promise<SkillIR> {\n // Extract frontmatter (support both \\n and \\r\\n line endings)\n const frontmatterMatch = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/);\n const frontmatter = frontmatterMatch?.[1];\n\n // Parse markdown to tokens\n const tokens = marked.lexer(markdown);\n\n return {\n frontmatter,\n tokens,\n raw: markdown\n };\n }\n\n /**\n * Parse markdown to Skill object\n */\n async parse(markdown: string): Promise<Skill> {\n // 1. Parse to IR\n const ir = await this.parseToIR(markdown);\n\n // 2. Process through plugins\n const processedIR = await this.pluginManager.process(ir);\n\n // 3. Convert to Skill object\n return this.irToSkill(processedIR);\n }\n\n /**\n * Add a plugin\n */\n use(plugin: SkillPlugin): this {\n this.pluginManager.register(plugin);\n return this;\n }\n\n /**\n * Check if a plugin is registered\n */\n hasPlugin(name: string): boolean {\n return this.pluginManager.has(name);\n }\n\n /**\n * Convert IR to Skill object\n */\n private irToSkill(ir: SkillIR): Skill {\n return {\n metadata: (ir.metadata as any) || { name: '', version: '' },\n sections: (ir.sections as any) || [],\n codeBlocks: (ir.codeBlocks as any) || [],\n dependencies: (ir.dependencies as any) || [],\n references: (ir.references as any) || [],\n raw: {\n markdown: ir.raw\n }\n };\n }\n}\n","import type { SkillPlugin, SkillIR } from '@skill-toolbox/utils';\nimport { PluginError } from '@skill-toolbox/utils';\n\n/**\n * Plugin manager for registering and executing plugins\n */\nexport class PluginManager {\n private plugins: Map<string, SkillPlugin> = new Map();\n\n /**\n * Register a plugin\n */\n register(plugin: SkillPlugin): void {\n if (this.plugins.has(plugin.name)) {\n throw new PluginError(plugin.name, 'Plugin already registered');\n }\n this.plugins.set(plugin.name, plugin);\n }\n\n /**\n * Register multiple plugins\n */\n registerAll(plugins: SkillPlugin[]): void {\n plugins.forEach(plugin => this.register(plugin));\n }\n\n /**\n * Get a plugin by name\n */\n get(name: string): SkillPlugin | undefined {\n return this.plugins.get(name);\n }\n\n /**\n * Process IR through all registered plugins\n */\n async process(ir: SkillIR): Promise<SkillIR> {\n let result = ir;\n\n for (const plugin of this.plugins.values()) {\n try {\n result = await plugin.parse(result);\n } catch (error) {\n throw new PluginError(\n plugin.name,\n error instanceof Error ? error.message : 'Unknown error',\n error instanceof Error ? error : undefined\n );\n }\n }\n\n return result;\n }\n\n /**\n * Check if a plugin is registered\n */\n has(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /**\n * Remove a plugin\n */\n remove(name: string): boolean {\n return this.plugins.delete(name);\n }\n\n /**\n * Clear all plugins\n */\n clear(): void {\n this.plugins.clear();\n }\n\n /**\n * Get all plugin names\n */\n getPluginNames(): string[] {\n return Array.from(this.plugins.keys());\n }\n}\n","import type { Skill, SkillSource } from '@skill-toolbox/utils';\nimport { SkillParser } from './parser';\n\n/**\n * Options for SkillLoader\n */\nexport interface SkillLoaderOptions {\n /** Sources to load skills from (each bound to a specific repo/path) */\n sources: SkillSource[];\n /** Custom parser (optional) */\n parser?: SkillParser;\n}\n\n/**\n * Result of loading all skills\n */\nexport interface LoadAllResult {\n /** Successfully loaded skills (key: full name like 'user/repo/skill-name') */\n skills: Map<string, Skill>;\n /** Errors encountered (key: path or source identifier) */\n errors: Map<string, Error>;\n}\n\n/**\n * Unified skill loader that works with bound SkillSource instances\n *\n * Usage:\n * ```typescript\n * const loader = new SkillLoader({\n * sources: [\n * new GitSource({ source: 'user/repo', skillPath: 'skills' }),\n * new FilesystemSource({ path: './local-skills' }),\n * ],\n * });\n *\n * const { skills, errors } = await loader.loadAll();\n * ```\n */\nexport class SkillLoader {\n private sources: SkillSource[];\n private parser: SkillParser;\n\n constructor(options: SkillLoaderOptions) {\n this.sources = options.sources;\n this.parser = options.parser || new SkillParser();\n }\n\n /**\n * Load skills from all configured sources\n *\n * - Skills are named with source prefix: 'source-id/skill-name'\n * - Failed sources are skipped (doesn't stop loading other sources)\n * - All sources are cleaned up automatically\n *\n * @returns Loaded skills and errors\n */\n async loadAll(): Promise<LoadAllResult> {\n const skills = new Map<string, Skill>();\n const errors = new Map<string, Error>();\n\n // Load from each source\n for (const source of this.sources) {\n try {\n const result = await source.load();\n\n // Parse each skill\n for (const skillData of result.skills) {\n try {\n const skill = await this.parser.parse(skillData.content);\n skills.set(skillData.name, skill);\n } catch (error) {\n errors.set(\n skillData.path,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Collect file-level errors\n for (const err of result.errors) {\n errors.set(err.path, err.error);\n }\n } catch (error) {\n // Source-level error\n const info = source.getSourceInfo();\n errors.set(\n info.identifier,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Cleanup all sources\n await Promise.all(\n this.sources.map((s) =>\n s.cleanup().catch((e) => console.warn('Cleanup failed:', e))\n )\n );\n\n return { skills, errors };\n }\n}\n","import type { SkillSource, SourceCategory } from '@skill-toolbox/utils';\n\n/**\n * Filesystem source configuration\n */\nexport interface FilesystemSourceConfig {\n type: 'filesystem';\n /** Path to the skills directory or file */\n path: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n}\n\n/**\n * Git source configuration\n */\nexport interface GitSourceConfig {\n type: 'git';\n /** Git repository source (e.g., 'user/repo') */\n source: string;\n /** Skill path within repository ('' for root - default is root) */\n skillPath?: string;\n /** Display name for this source */\n name?: string;\n /** Category override */\n category?: SourceCategory;\n /** Cache directory */\n cacheDir?: string;\n /** Use shallow clone */\n shallow?: boolean;\n}\n\n/**\n * Source configuration union type\n */\nexport type SourceConfig = FilesystemSourceConfig | GitSourceConfig;\n\n/**\n * Constructor interface for source classes\n */\ninterface SourceConstructor<Options> {\n new (options: Options): SkillSource;\n}\n\n/**\n * Filesystem source options (subset for factory)\n */\ninterface FilesystemSourceOptions {\n path: string;\n name?: string;\n category?: SourceCategory;\n}\n\n/**\n * Git source options (subset for factory)\n */\ninterface GitSourceOptions {\n source: string;\n skillPath?: string;\n name?: string;\n category?: SourceCategory;\n cacheDir?: string;\n shallow?: boolean;\n}\n\n/**\n * Helper to create sources from configurations.\n * Requires FilesystemSource and GitSource to be passed in to avoid circular dependencies.\n *\n * @example\n * ```typescript\n * import { FilesystemSource } from '@skill-toolbox/filesystem-source';\n * import { GitSource } from '@skill-toolbox/git-source';\n * import { createSources, SkillLoader } from '@skill-toolbox/core';\n *\n * const sources = createSources(\n * [\n * { type: 'filesystem', path: './skills' },\n * { type: 'git', source: 'user/repo' },\n * ],\n * { FilesystemSource, GitSource }\n * );\n *\n * const loader = new SkillLoader({ sources });\n * ```\n */\nexport function createSources(\n configs: SourceConfig[],\n imports: {\n FilesystemSource: SourceConstructor<FilesystemSourceOptions>;\n GitSource: SourceConstructor<GitSourceOptions>;\n }\n): SkillSource[] {\n return configs.map((config) => {\n if (config.type === 'filesystem') {\n return new imports.FilesystemSource({\n path: config.path,\n name: config.name,\n category: config.category,\n });\n } else {\n return new imports.GitSource({\n source: config.source,\n skillPath: config.skillPath,\n name: config.name,\n category: config.category,\n cacheDir: config.cacheDir,\n shallow: config.shallow,\n });\n }\n });\n}\n","/**\n * @skill-toolbox/core\n * Core parsing engine and plugin system\n */\n\nexport const VERSION = '1.0.0';\n\nexport { SkillParser } from './parser';\nexport { PluginManager } from './plugin';\nexport { SkillLoader } from './SkillLoader';\nexport type { SkillLoaderOptions, LoadAllResult } from './SkillLoader';\nexport { createSources } from './factory';\nexport type { SourceConfig, FilesystemSourceConfig, GitSourceConfig } from './factory';\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skill-toolbox/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Core parsing engine and plugin system for skill-toolbox",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./factory": {
|
|
15
|
+
"types": "./dist/factory.d.ts",
|
|
16
|
+
"import": "./dist/factory.mjs",
|
|
17
|
+
"require": "./dist/factory.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "tsup src/index.ts src/factory.ts --format cjs,esm --dts --watch",
|
|
25
|
+
"build": "tsup src/index.ts src/factory.ts --format cjs,esm --dts",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@skill-toolbox/utils": "workspace:*",
|
|
32
|
+
"marked": "^12.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"tsup": "^8.0.0",
|
|
36
|
+
"vitest": "^1.2.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"registry": "https://registry.npmjs.org/"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/Link-Reverie/skill-toolbox.git",
|
|
45
|
+
"directory": "packages/core"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/Link-Reverie/skill-toolbox/issues"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/Link-Reverie/skill-toolbox#readme",
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"keywords": [
|
|
53
|
+
"skill",
|
|
54
|
+
"ai-agent",
|
|
55
|
+
"claude",
|
|
56
|
+
"llm",
|
|
57
|
+
"typescript",
|
|
58
|
+
"parser",
|
|
59
|
+
"plugin"
|
|
60
|
+
]
|
|
61
|
+
}
|