@lyupro/skillforge-mcp 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +114 -0
- package/LICENSE +21 -0
- package/README.md +231 -0
- package/dist/cli/install.d.ts +41 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +223 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/config/config-schema.d.ts +175 -0
- package/dist/config/config-schema.d.ts.map +1 -0
- package/dist/config/config-schema.js +49 -0
- package/dist/config/config-schema.js.map +1 -0
- package/dist/config/config-store.d.ts +24 -0
- package/dist/config/config-store.d.ts.map +1 -0
- package/dist/config/config-store.js +67 -0
- package/dist/config/config-store.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +73 -0
- package/dist/config.js.map +1 -0
- package/dist/core/errors.d.ts +9 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +13 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/skill-content-cache.d.ts +18 -0
- package/dist/core/skill-content-cache.d.ts.map +1 -0
- package/dist/core/skill-content-cache.js +56 -0
- package/dist/core/skill-content-cache.js.map +1 -0
- package/dist/core/skill-metadata-cache.d.ts +15 -0
- package/dist/core/skill-metadata-cache.d.ts.map +1 -0
- package/dist/core/skill-metadata-cache.js +31 -0
- package/dist/core/skill-metadata-cache.js.map +1 -0
- package/dist/core/skill-registry.d.ts +12 -0
- package/dist/core/skill-registry.d.ts.map +1 -0
- package/dist/core/skill-registry.js +28 -0
- package/dist/core/skill-registry.js.map +1 -0
- package/dist/core/skill-resolver.d.ts +6 -0
- package/dist/core/skill-resolver.d.ts.map +1 -0
- package/dist/core/skill-resolver.js +32 -0
- package/dist/core/skill-resolver.js.map +1 -0
- package/dist/core/types.d.ts +80 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +1 -0
- package/dist/decorators/base-decorator.d.ts +10 -0
- package/dist/decorators/base-decorator.d.ts.map +1 -0
- package/dist/decorators/base-decorator.js +13 -0
- package/dist/decorators/base-decorator.js.map +1 -0
- package/dist/decorators/cache-decorator.d.ts +33 -0
- package/dist/decorators/cache-decorator.d.ts.map +1 -0
- package/dist/decorators/cache-decorator.js +89 -0
- package/dist/decorators/cache-decorator.js.map +1 -0
- package/dist/decorators/decorator-chain.d.ts +16 -0
- package/dist/decorators/decorator-chain.d.ts.map +1 -0
- package/dist/decorators/decorator-chain.js +31 -0
- package/dist/decorators/decorator-chain.js.map +1 -0
- package/dist/decorators/index.d.ts +10 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +6 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/logging-decorator.d.ts +15 -0
- package/dist/decorators/logging-decorator.d.ts.map +1 -0
- package/dist/decorators/logging-decorator.js +34 -0
- package/dist/decorators/logging-decorator.js.map +1 -0
- package/dist/decorators/timeout-decorator.d.ts +19 -0
- package/dist/decorators/timeout-decorator.d.ts.map +1 -0
- package/dist/decorators/timeout-decorator.js +59 -0
- package/dist/decorators/timeout-decorator.js.map +1 -0
- package/dist/factory/index.d.ts +2 -0
- package/dist/factory/index.d.ts.map +1 -0
- package/dist/factory/index.js +2 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/factory/strategy-factory.d.ts +10 -0
- package/dist/factory/strategy-factory.d.ts.map +1 -0
- package/dist/factory/strategy-factory.js +37 -0
- package/dist/factory/strategy-factory.js.map +1 -0
- package/dist/handlers/composite-resolver.d.ts +34 -0
- package/dist/handlers/composite-resolver.d.ts.map +1 -0
- package/dist/handlers/composite-resolver.js +94 -0
- package/dist/handlers/composite-resolver.js.map +1 -0
- package/dist/handlers/hybrid-strategy.d.ts +14 -0
- package/dist/handlers/hybrid-strategy.d.ts.map +1 -0
- package/dist/handlers/hybrid-strategy.js +42 -0
- package/dist/handlers/hybrid-strategy.js.map +1 -0
- package/dist/handlers/index.d.ts +3 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +2 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/invocation-strategy.d.ts +17 -0
- package/dist/handlers/invocation-strategy.d.ts.map +1 -0
- package/dist/handlers/invocation-strategy.js +2 -0
- package/dist/handlers/invocation-strategy.js.map +1 -0
- package/dist/handlers/prompt-strategy.d.ts +8 -0
- package/dist/handlers/prompt-strategy.d.ts.map +1 -0
- package/dist/handlers/prompt-strategy.js +31 -0
- package/dist/handlers/prompt-strategy.js.map +1 -0
- package/dist/handlers/script-strategy.d.ts +20 -0
- package/dist/handlers/script-strategy.d.ts.map +1 -0
- package/dist/handlers/script-strategy.js +87 -0
- package/dist/handlers/script-strategy.js.map +1 -0
- package/dist/installers/atomic-write.d.ts +13 -0
- package/dist/installers/atomic-write.d.ts.map +1 -0
- package/dist/installers/atomic-write.js +98 -0
- package/dist/installers/atomic-write.js.map +1 -0
- package/dist/installers/claude-installer.d.ts +26 -0
- package/dist/installers/claude-installer.d.ts.map +1 -0
- package/dist/installers/claude-installer.js +118 -0
- package/dist/installers/claude-installer.js.map +1 -0
- package/dist/installers/codex-installer.d.ts +30 -0
- package/dist/installers/codex-installer.d.ts.map +1 -0
- package/dist/installers/codex-installer.js +125 -0
- package/dist/installers/codex-installer.js.map +1 -0
- package/dist/installers/cursor-installer.d.ts +29 -0
- package/dist/installers/cursor-installer.d.ts.map +1 -0
- package/dist/installers/cursor-installer.js +126 -0
- package/dist/installers/cursor-installer.js.map +1 -0
- package/dist/installers/paths.d.ts +20 -0
- package/dist/installers/paths.d.ts.map +1 -0
- package/dist/installers/paths.js +50 -0
- package/dist/installers/paths.js.map +1 -0
- package/dist/installers/registry.d.ts +8 -0
- package/dist/installers/registry.d.ts.map +1 -0
- package/dist/installers/registry.js +18 -0
- package/dist/installers/registry.js.map +1 -0
- package/dist/installers/types.d.ts +45 -0
- package/dist/installers/types.d.ts.map +1 -0
- package/dist/installers/types.js +9 -0
- package/dist/installers/types.js.map +1 -0
- package/dist/parser/file-scanner.d.ts +10 -0
- package/dist/parser/file-scanner.d.ts.map +1 -0
- package/dist/parser/file-scanner.js +37 -0
- package/dist/parser/file-scanner.js.map +1 -0
- package/dist/parser/format-detector.d.ts +11 -0
- package/dist/parser/format-detector.d.ts.map +1 -0
- package/dist/parser/format-detector.js +13 -0
- package/dist/parser/format-detector.js.map +1 -0
- package/dist/parser/frontmatter-parser.d.ts +14 -0
- package/dist/parser/frontmatter-parser.d.ts.map +1 -0
- package/dist/parser/frontmatter-parser.js +98 -0
- package/dist/parser/frontmatter-parser.js.map +1 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +4 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/scripts-dir-detector.d.ts +7 -0
- package/dist/parser/scripts-dir-detector.d.ts.map +1 -0
- package/dist/parser/scripts-dir-detector.js +17 -0
- package/dist/parser/scripts-dir-detector.js.map +1 -0
- package/dist/security/blacklist-filter.d.ts +32 -0
- package/dist/security/blacklist-filter.d.ts.map +1 -0
- package/dist/security/blacklist-filter.js +35 -0
- package/dist/security/blacklist-filter.js.map +1 -0
- package/dist/security/index.d.ts +5 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +3 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/pattern-scanner.d.ts +27 -0
- package/dist/security/pattern-scanner.d.ts.map +1 -0
- package/dist/security/pattern-scanner.js +46 -0
- package/dist/security/pattern-scanner.js.map +1 -0
- package/dist/security/sandbox-runner.d.ts +48 -0
- package/dist/security/sandbox-runner.d.ts.map +1 -0
- package/dist/security/sandbox-runner.js +131 -0
- package/dist/security/sandbox-runner.js.map +1 -0
- package/dist/server-deps.d.ts +28 -0
- package/dist/server-deps.d.ts.map +1 -0
- package/dist/server-deps.js +2 -0
- package/dist/server-deps.js.map +1 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +174 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/configure.d.ts +22 -0
- package/dist/tools/configure.d.ts.map +1 -0
- package/dist/tools/configure.js +126 -0
- package/dist/tools/configure.js.map +1 -0
- package/dist/tools/get.d.ts +10 -0
- package/dist/tools/get.d.ts.map +1 -0
- package/dist/tools/get.js +20 -0
- package/dist/tools/get.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/invoke.d.ts +12 -0
- package/dist/tools/invoke.d.ts.map +1 -0
- package/dist/tools/invoke.js +36 -0
- package/dist/tools/invoke.js.map +1 -0
- package/dist/tools/list.d.ts +16 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +33 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/loader.d.ts +30 -0
- package/dist/tools/loader.d.ts.map +1 -0
- package/dist/tools/loader.js +92 -0
- package/dist/tools/loader.js.map +1 -0
- package/dist/tools/reload.d.ts +22 -0
- package/dist/tools/reload.d.ts.map +1 -0
- package/dist/tools/reload.js +39 -0
- package/dist/tools/reload.js.map +1 -0
- package/dist/watcher/chokidar-types.d.ts +20 -0
- package/dist/watcher/chokidar-types.d.ts.map +1 -0
- package/dist/watcher/chokidar-types.js +2 -0
- package/dist/watcher/chokidar-types.js.map +1 -0
- package/dist/watcher/folder-watcher.d.ts +27 -0
- package/dist/watcher/folder-watcher.d.ts.map +1 -0
- package/dist/watcher/folder-watcher.js +123 -0
- package/dist/watcher/folder-watcher.js.map +1 -0
- package/dist/watcher/index.d.ts +4 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js +2 -0
- package/dist/watcher/index.js.map +1 -0
- package/manifest.json +96 -0
- package/package.json +78 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS-specific config path helpers for host tools.
|
|
3
|
+
*
|
|
4
|
+
* Per repo convention, all SkillForge config paths use `os.homedir()`
|
|
5
|
+
* exclusively — no platform branching. Cursor is the exception: its
|
|
6
|
+
* `settings.json` location is third-party (Cursor app), out of our
|
|
7
|
+
* control, so the platform-specific dispatch here is rubric-exempt.
|
|
8
|
+
*/
|
|
9
|
+
import { join, resolve } from 'node:path';
|
|
10
|
+
import { homedir, platform } from 'node:os';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
export function claudeConfigPath() {
|
|
13
|
+
return join(homedir(), '.claude.json');
|
|
14
|
+
}
|
|
15
|
+
export function codexConfigPath() {
|
|
16
|
+
return join(homedir(), '.codex', 'config.toml');
|
|
17
|
+
}
|
|
18
|
+
// Cursor stores its global settings.json in a per-OS application data
|
|
19
|
+
// directory. We follow the location documented by the Cursor app itself.
|
|
20
|
+
// This is the only place in the codebase where a platform branch is
|
|
21
|
+
// permitted, because the third-party host owns the path.
|
|
22
|
+
export function cursorSettingsPath() {
|
|
23
|
+
const os = platform();
|
|
24
|
+
if (os === 'win32') {
|
|
25
|
+
const appData = process.env.APPDATA ?? join(homedir(), 'AppData', 'Roaming');
|
|
26
|
+
return join(appData, 'Cursor', 'User', 'settings.json');
|
|
27
|
+
}
|
|
28
|
+
if (os === 'darwin') {
|
|
29
|
+
return join(homedir(), 'Library', 'Application Support', 'Cursor', 'User', 'settings.json');
|
|
30
|
+
}
|
|
31
|
+
return join(homedir(), '.config', 'Cursor', 'User', 'settings.json');
|
|
32
|
+
}
|
|
33
|
+
// Fallback `--entry local` target when --binary-path is not supplied.
|
|
34
|
+
// Resolves to <package root>/dist/server.js via import.meta.url so the
|
|
35
|
+
// path works whether the file is executed from dist/ or src/ (tsx).
|
|
36
|
+
export function defaultBinaryPath() {
|
|
37
|
+
const here = fileURLToPath(import.meta.url);
|
|
38
|
+
// here = <root>/(dist|src)/installers/paths.(js|ts)
|
|
39
|
+
// Resolve up three segments to reach the package root, then dist/server.js.
|
|
40
|
+
return resolve(here, '..', '..', '..', 'dist', 'server.js');
|
|
41
|
+
}
|
|
42
|
+
export function defaultPaths() {
|
|
43
|
+
return {
|
|
44
|
+
claudeConfigPath: claudeConfigPath(),
|
|
45
|
+
codexConfigPath: codexConfigPath(),
|
|
46
|
+
cursorSettingsPath: cursorSettingsPath(),
|
|
47
|
+
defaultBinaryPath: defaultBinaryPath(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/installers/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASzC,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED,sEAAsE;AACtE,yEAAyE;AACzE,oEAAoE;AACpE,yDAAyD;AACzD,MAAM,UAAU,kBAAkB;IAChC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;AACvE,CAAC;AAED,sEAAsE;AACtE,uEAAuE;AACvE,oEAAoE;AACpE,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5C,oDAAoD;IACpD,4EAA4E;IAC5E,OAAO,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,gBAAgB,EAAE,gBAAgB,EAAE;QACpC,eAAe,EAAE,eAAe,EAAE;QAClC,kBAAkB,EAAE,kBAAkB,EAAE;QACxC,iBAAiB,EAAE,iBAAiB,EAAE;KACvC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installer registry — stable enumeration of the three host installers
|
|
3
|
+
* consumed by the `--all` dispatcher and by --claude / --codex / --cursor.
|
|
4
|
+
*/
|
|
5
|
+
import type { Installer } from './types.js';
|
|
6
|
+
export declare function getAllInstallers(): Installer[];
|
|
7
|
+
export declare function getInstallerByName(name: 'claude' | 'codex' | 'cursor'): Installer;
|
|
8
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/installers/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAE9C;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAIjF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installer registry — stable enumeration of the three host installers
|
|
3
|
+
* consumed by the `--all` dispatcher and by --claude / --codex / --cursor.
|
|
4
|
+
*/
|
|
5
|
+
import { ClaudeInstaller } from './claude-installer.js';
|
|
6
|
+
import { CodexInstaller } from './codex-installer.js';
|
|
7
|
+
import { CursorInstaller } from './cursor-installer.js';
|
|
8
|
+
export function getAllInstallers() {
|
|
9
|
+
return [new ClaudeInstaller(), new CodexInstaller(), new CursorInstaller()];
|
|
10
|
+
}
|
|
11
|
+
export function getInstallerByName(name) {
|
|
12
|
+
if (name === 'claude')
|
|
13
|
+
return new ClaudeInstaller();
|
|
14
|
+
if (name === 'codex')
|
|
15
|
+
return new CodexInstaller();
|
|
16
|
+
return new CursorInstaller();
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/installers/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,IAAI,eAAe,EAAE,EAAE,IAAI,cAAc,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAmC;IACpE,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,eAAe,EAAE,CAAC;IACpD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,cAAc,EAAE,CAAC;IAClD,OAAO,IAAI,eAAe,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the install CLI (v1.1).
|
|
3
|
+
*
|
|
4
|
+
* Each host tool (Claude Code / Codex CLI / Cursor) ships an Installer
|
|
5
|
+
* implementing this contract so the CLI dispatcher can iterate them
|
|
6
|
+
* uniformly under `--all`, `--dry-run`, and `--uninstall`.
|
|
7
|
+
*/
|
|
8
|
+
export type EntryKind = 'npx' | 'local';
|
|
9
|
+
export interface InstallOptions {
|
|
10
|
+
entry: EntryKind;
|
|
11
|
+
binaryPath?: string;
|
|
12
|
+
force?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export type InstallStatus = 'installed' | 'already-installed' | 'updated' | 'skipped';
|
|
15
|
+
export type UninstallStatus = 'uninstalled' | 'not-installed';
|
|
16
|
+
export interface InstallResult {
|
|
17
|
+
tool: string;
|
|
18
|
+
status: InstallStatus;
|
|
19
|
+
configPath: string;
|
|
20
|
+
message?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface UninstallResult {
|
|
23
|
+
tool: string;
|
|
24
|
+
status: UninstallStatus;
|
|
25
|
+
configPath: string;
|
|
26
|
+
message?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface PreviewResult {
|
|
29
|
+
tool: string;
|
|
30
|
+
configPath: string;
|
|
31
|
+
willCreate: boolean;
|
|
32
|
+
before: string | null;
|
|
33
|
+
after: string;
|
|
34
|
+
action: 'install' | 'uninstall';
|
|
35
|
+
}
|
|
36
|
+
export interface Installer {
|
|
37
|
+
readonly name: string;
|
|
38
|
+
detect(): Promise<boolean>;
|
|
39
|
+
install(opts: InstallOptions): Promise<InstallResult>;
|
|
40
|
+
uninstall(): Promise<UninstallResult>;
|
|
41
|
+
preview(opts: InstallOptions & {
|
|
42
|
+
action: 'install' | 'uninstall';
|
|
43
|
+
}): Promise<PreviewResult>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/installers/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,mBAAmB,GACnB,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,eAAe,CAAC;AAE9D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACtD,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG;QAAE,MAAM,EAAE,SAAS,GAAG,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC7F"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the install CLI (v1.1).
|
|
3
|
+
*
|
|
4
|
+
* Each host tool (Claude Code / Codex CLI / Cursor) ships an Installer
|
|
5
|
+
* implementing this contract so the CLI dispatcher can iterate them
|
|
6
|
+
* uniformly under `--all`, `--dry-run`, and `--uninstall`.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/installers/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface FileScannerOptions {
|
|
2
|
+
ignoreDirs?: string[];
|
|
3
|
+
}
|
|
4
|
+
export declare class FileScanner {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(options?: FileScannerOptions);
|
|
7
|
+
scan(folderAbsolutePath: string): Promise<string[]>;
|
|
8
|
+
}
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=file-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-scanner.d.ts","sourceRoot":"","sources":["../../src/parser/file-scanner.ts"],"names":[],"mappings":"AAKA,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,WAAW;;gBAGV,OAAO,GAAE,kBAAuB;IAItC,IAAI,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAmC1D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readdir, access } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const DEFAULT_IGNORE_DIRS = ['node_modules', '.git', 'dist', 'coverage'];
|
|
4
|
+
export class FileScanner {
|
|
5
|
+
#ignoreDirs;
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this.#ignoreDirs = new Set(options.ignoreDirs ?? DEFAULT_IGNORE_DIRS);
|
|
8
|
+
}
|
|
9
|
+
async scan(folderAbsolutePath) {
|
|
10
|
+
try {
|
|
11
|
+
await access(folderAbsolutePath);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error(`Folder not found: ${folderAbsolutePath}`);
|
|
15
|
+
}
|
|
16
|
+
const entries = await readdir(folderAbsolutePath, {
|
|
17
|
+
withFileTypes: true,
|
|
18
|
+
recursive: true,
|
|
19
|
+
});
|
|
20
|
+
const results = [];
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
if (!entry.isFile())
|
|
23
|
+
continue;
|
|
24
|
+
const entryPath = join(entry.parentPath ?? entry.path ?? folderAbsolutePath, entry.name);
|
|
25
|
+
const relativePath = entryPath.slice(folderAbsolutePath.length);
|
|
26
|
+
const segments = relativePath.split(/[\\/]/).filter(Boolean);
|
|
27
|
+
const inIgnored = segments.slice(0, -1).some((seg) => this.#ignoreDirs.has(seg));
|
|
28
|
+
if (inIgnored)
|
|
29
|
+
continue;
|
|
30
|
+
if (!entry.name.toLowerCase().endsWith('.md'))
|
|
31
|
+
continue;
|
|
32
|
+
results.push(entryPath);
|
|
33
|
+
}
|
|
34
|
+
return results.sort();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=file-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/parser/file-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,mBAAmB,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AAMzE,MAAM,OAAO,WAAW;IACb,WAAW,CAAsB;IAE1C,YAAY,UAA8B,EAAE;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,kBAA0B;QACnC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,qBAAqB,kBAAkB,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,kBAAkB,EAAE;YAChD,aAAa,EAAE,IAAI;YACnB,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBAAE,SAAS;YAE9B,MAAM,SAAS,GAAG,IAAI,CACpB,KAAK,CAAC,UAAU,IAAK,KAAqC,CAAC,IAAI,IAAI,kBAAkB,EACrF,KAAK,CAAC,IAAI,CACX,CAAC;YAEF,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAE7D,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACjF,IAAI,SAAS;gBAAE,SAAS;YAExB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YAExD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;QAED,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SkillFormat } from '../core/types.js';
|
|
2
|
+
interface DetectInput {
|
|
3
|
+
filePath?: string;
|
|
4
|
+
fileName: string;
|
|
5
|
+
frontmatter?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare class FormatDetector {
|
|
8
|
+
detect({ fileName, frontmatter }: DetectInput): SkillFormat;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=format-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-detector.d.ts","sourceRoot":"","sources":["../../src/parser/format-detector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,qBAAa,cAAc;IACzB,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,WAAW,GAAG,WAAW;CAO5D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class FormatDetector {
|
|
2
|
+
detect({ fileName, frontmatter }) {
|
|
3
|
+
if (fileName === 'SKILL.md')
|
|
4
|
+
return 'claude';
|
|
5
|
+
if (fileName === 'AGENTS.md')
|
|
6
|
+
return 'codex';
|
|
7
|
+
const persona = frontmatter?.['persona'];
|
|
8
|
+
if (typeof persona === 'string' && persona.trim().length > 0)
|
|
9
|
+
return 'persona';
|
|
10
|
+
return 'custom';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=format-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-detector.js","sourceRoot":"","sources":["../../src/parser/format-detector.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAe;QAC3C,IAAI,QAAQ,KAAK,UAAU;YAAE,OAAO,QAAQ,CAAC;QAC7C,IAAI,QAAQ,KAAK,WAAW;YAAE,OAAO,OAAO,CAAC;QAC7C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/E,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SkillContent } from '../core/types.js';
|
|
2
|
+
import { FormatDetector } from './format-detector.js';
|
|
3
|
+
import type { ScriptsDirDetector } from './scripts-dir-detector.js';
|
|
4
|
+
interface ParserOptions {
|
|
5
|
+
formatDetector?: FormatDetector;
|
|
6
|
+
scriptsDirDetector?: ScriptsDirDetector;
|
|
7
|
+
}
|
|
8
|
+
export declare class FrontmatterParser {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(options?: ParserOptions);
|
|
11
|
+
parseFile(absolutePath: string, configuredFolder: string): Promise<SkillContent>;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=frontmatter-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-parser.d.ts","sourceRoot":"","sources":["../../src/parser/frontmatter-parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAuBpE,UAAU,aAAa;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,qBAAa,iBAAiB;;gBAIhB,OAAO,GAAE,aAAkB;IAKjC,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAqFvF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { basename } from 'node:path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { FormatDetector } from './format-detector.js';
|
|
5
|
+
import { FsScriptsDirDetector } from './scripts-dir-detector.js';
|
|
6
|
+
const CONSUMED_KEYS = new Set([
|
|
7
|
+
'name', 'description', 'tags', 'format', 'strategy',
|
|
8
|
+
'allow_scripts', 'allowScripts', 'allow_network', 'allowNetwork',
|
|
9
|
+
'skills', 'timeout_ms', 'timeoutMs',
|
|
10
|
+
'scripts', 'cacheable', 'cache_ttl_ms', 'cacheTtlMs',
|
|
11
|
+
]);
|
|
12
|
+
const STRATEGY_KINDS = new Set(['prompt', 'script', 'hybrid']);
|
|
13
|
+
function normalizeTags(raw) {
|
|
14
|
+
if (Array.isArray(raw)) {
|
|
15
|
+
if (raw.every((t) => typeof t === 'string'))
|
|
16
|
+
return raw;
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (typeof raw === 'string') {
|
|
20
|
+
if (raw.includes(','))
|
|
21
|
+
return raw.split(',').map((t) => t.trim()).filter(Boolean);
|
|
22
|
+
return [raw];
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
export class FrontmatterParser {
|
|
27
|
+
#detector;
|
|
28
|
+
#scriptsDirDetector;
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.#detector = options.formatDetector ?? new FormatDetector();
|
|
31
|
+
this.#scriptsDirDetector = options.scriptsDirDetector ?? new FsScriptsDirDetector();
|
|
32
|
+
}
|
|
33
|
+
async parseFile(absolutePath, configuredFolder) {
|
|
34
|
+
const raw = await readFile(absolutePath, 'utf-8');
|
|
35
|
+
const parsed = matter(raw);
|
|
36
|
+
const data = parsed.data;
|
|
37
|
+
const name = typeof data['name'] === 'string' ? data['name'].trim() : '';
|
|
38
|
+
if (!name) {
|
|
39
|
+
throw new Error(`Skill at ${absolutePath}: missing required frontmatter field 'name'`);
|
|
40
|
+
}
|
|
41
|
+
const description = typeof data['description'] === 'string' ? data['description'].trim() : undefined;
|
|
42
|
+
const tags = normalizeTags(data['tags']);
|
|
43
|
+
const fileName = basename(absolutePath);
|
|
44
|
+
const format = this.#detector.detect({ fileName, frontmatter: data });
|
|
45
|
+
const strategyRaw = data['strategy'];
|
|
46
|
+
const strategy = typeof strategyRaw === 'string' && STRATEGY_KINDS.has(strategyRaw)
|
|
47
|
+
? strategyRaw
|
|
48
|
+
: undefined;
|
|
49
|
+
const allowScripts = Boolean(data['allow_scripts'] ?? data['allowScripts'] ?? false);
|
|
50
|
+
const allowNetwork = Boolean(data['allow_network'] ?? data['allowNetwork'] ?? false);
|
|
51
|
+
const skillsRaw = data['skills'];
|
|
52
|
+
const skills = Array.isArray(skillsRaw) && skillsRaw.every((s) => typeof s === 'string')
|
|
53
|
+
? skillsRaw
|
|
54
|
+
: undefined;
|
|
55
|
+
const timeoutRaw = data['timeout_ms'] ?? data['timeoutMs'];
|
|
56
|
+
const timeoutMs = typeof timeoutRaw === 'number' && Number.isFinite(timeoutRaw) && timeoutRaw > 0
|
|
57
|
+
? timeoutRaw
|
|
58
|
+
: undefined;
|
|
59
|
+
const scriptsRaw = data['scripts'];
|
|
60
|
+
const scripts = Array.isArray(scriptsRaw) && scriptsRaw.every((s) => typeof s === 'string')
|
|
61
|
+
? scriptsRaw
|
|
62
|
+
: undefined;
|
|
63
|
+
const cacheableRaw = data['cacheable'];
|
|
64
|
+
const cacheable = typeof cacheableRaw === 'boolean' ? cacheableRaw : undefined;
|
|
65
|
+
const cacheTtlRaw = data['cache_ttl_ms'] ?? data['cacheTtlMs'];
|
|
66
|
+
const cacheTtlMs = typeof cacheTtlRaw === 'number' && Number.isFinite(cacheTtlRaw) && cacheTtlRaw > 0
|
|
67
|
+
? cacheTtlRaw
|
|
68
|
+
: undefined;
|
|
69
|
+
const extra = {};
|
|
70
|
+
for (const [key, value] of Object.entries(data)) {
|
|
71
|
+
if (!CONSUMED_KEYS.has(key))
|
|
72
|
+
extra[key] = value;
|
|
73
|
+
}
|
|
74
|
+
const body = parsed.content.replace(/^\n+/, '');
|
|
75
|
+
const scriptsDir = await this.#scriptsDirDetector.detect(absolutePath);
|
|
76
|
+
return {
|
|
77
|
+
name,
|
|
78
|
+
description,
|
|
79
|
+
sourcePath: absolutePath,
|
|
80
|
+
folder: configuredFolder,
|
|
81
|
+
tags,
|
|
82
|
+
format,
|
|
83
|
+
strategy,
|
|
84
|
+
allowScripts,
|
|
85
|
+
allowNetwork,
|
|
86
|
+
skills,
|
|
87
|
+
timeoutMs,
|
|
88
|
+
scripts,
|
|
89
|
+
cacheable,
|
|
90
|
+
cacheTtlMs,
|
|
91
|
+
extra: Object.keys(extra).length > 0 ? extra : undefined,
|
|
92
|
+
body,
|
|
93
|
+
raw,
|
|
94
|
+
scriptsDir,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=frontmatter-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter-parser.js","sourceRoot":"","sources":["../../src/parser/frontmatter-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface ScriptsDirDetector {
|
|
2
|
+
detect(skillFilePath: string): Promise<string | undefined>;
|
|
3
|
+
}
|
|
4
|
+
export declare class FsScriptsDirDetector implements ScriptsDirDetector {
|
|
5
|
+
detect(skillFilePath: string): Promise<string | undefined>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=scripts-dir-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts-dir-detector.d.ts","sourceRoot":"","sources":["../../src/parser/scripts-dir-detector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC5D;AAED,qBAAa,oBAAqB,YAAW,kBAAkB;IACvD,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAUjE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
export class FsScriptsDirDetector {
|
|
4
|
+
async detect(skillFilePath) {
|
|
5
|
+
const candidate = join(dirname(skillFilePath), 'scripts');
|
|
6
|
+
try {
|
|
7
|
+
const s = await stat(candidate);
|
|
8
|
+
if (s.isDirectory())
|
|
9
|
+
return candidate;
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=scripts-dir-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts-dir-detector.js","sourceRoot":"","sources":["../../src/parser/scripts-dir-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAM1C,MAAM,OAAO,oBAAoB;IAC/B,KAAK,CAAC,MAAM,CAAC,aAAqB;QAChC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,SAAS,CAAC;YACtC,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PatternScanner } from './pattern-scanner.js';
|
|
2
|
+
import type { SkillContent } from '../core/types.js';
|
|
3
|
+
export interface BlacklistFilterOptions {
|
|
4
|
+
/** Skill names that are always rejected (case-sensitive exact match). */
|
|
5
|
+
manualBlacklist?: readonly string[];
|
|
6
|
+
/** Pattern scanner used for auto-audit. When null/undefined, auto-audit is off. */
|
|
7
|
+
patternScanner?: PatternScanner | null;
|
|
8
|
+
}
|
|
9
|
+
export type FilterVerdict = {
|
|
10
|
+
allowed: true;
|
|
11
|
+
} | {
|
|
12
|
+
allowed: false;
|
|
13
|
+
reason: 'manual';
|
|
14
|
+
pattern?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
allowed: false;
|
|
17
|
+
reason: 'audit';
|
|
18
|
+
pattern: string;
|
|
19
|
+
};
|
|
20
|
+
export declare class BlacklistFilter {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(opts?: BlacklistFilterOptions);
|
|
23
|
+
/** Replace the manual blacklist atomically. Normalizes input the same way
|
|
24
|
+
* the constructor does (trim, drop empties, dedupe). */
|
|
25
|
+
setManualBlacklist(names: readonly string[]): void;
|
|
26
|
+
/** Returns the verdict for a parsed skill.
|
|
27
|
+
* Manual blacklist checked first (cheap), then pattern audit (only if scanner present). */
|
|
28
|
+
evaluate(content: SkillContent): FilterVerdict;
|
|
29
|
+
/** True if neither layer is armed — useful for short-circuiting callers and tests. */
|
|
30
|
+
isNoop(): boolean;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=blacklist-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blacklist-filter.d.ts","sourceRoot":"","sources":["../../src/security/blacklist-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,mFAAmF;IACnF,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACzD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAMzD,qBAAa,eAAe;;gBAId,IAAI,CAAC,EAAE,sBAAsB;IAKzC;6DACyD;IACzD,kBAAkB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAIlD;gGAC4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,aAAa;IAe9C,sFAAsF;IACtF,MAAM,IAAI,OAAO;CAGlB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function normalizeNames(names) {
|
|
2
|
+
return new Set(names.map((s) => s.trim()).filter((s) => s.length > 0));
|
|
3
|
+
}
|
|
4
|
+
export class BlacklistFilter {
|
|
5
|
+
#blacklist;
|
|
6
|
+
#scanner;
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
this.#blacklist = normalizeNames(opts?.manualBlacklist ?? []);
|
|
9
|
+
this.#scanner = opts?.patternScanner ?? null;
|
|
10
|
+
}
|
|
11
|
+
/** Replace the manual blacklist atomically. Normalizes input the same way
|
|
12
|
+
* the constructor does (trim, drop empties, dedupe). */
|
|
13
|
+
setManualBlacklist(names) {
|
|
14
|
+
this.#blacklist = normalizeNames(names);
|
|
15
|
+
}
|
|
16
|
+
/** Returns the verdict for a parsed skill.
|
|
17
|
+
* Manual blacklist checked first (cheap), then pattern audit (only if scanner present). */
|
|
18
|
+
evaluate(content) {
|
|
19
|
+
if (this.#blacklist.has(content.name)) {
|
|
20
|
+
return { allowed: false, reason: 'manual' };
|
|
21
|
+
}
|
|
22
|
+
if (this.#scanner !== null) {
|
|
23
|
+
const result = this.#scanner.scan(content.body);
|
|
24
|
+
if (!result.safe) {
|
|
25
|
+
return { allowed: false, reason: 'audit', pattern: result.matches[0].pattern };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return { allowed: true };
|
|
29
|
+
}
|
|
30
|
+
/** True if neither layer is armed — useful for short-circuiting callers and tests. */
|
|
31
|
+
isNoop() {
|
|
32
|
+
return this.#blacklist.size === 0 && this.#scanner === null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=blacklist-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blacklist-filter.js","sourceRoot":"","sources":["../../src/security/blacklist-filter.ts"],"names":[],"mappings":"AAeA,SAAS,cAAc,CAAC,KAAwB;IAC9C,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,OAAO,eAAe;IAC1B,UAAU,CAAc;IACf,QAAQ,CAAwB;IAEzC,YAAY,IAA6B;QACvC,IAAI,CAAC,UAAU,GAAG,cAAc,CAAC,IAAI,EAAE,eAAe,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,cAAc,IAAI,IAAI,CAAC;IAC/C,CAAC;IAED;6DACyD;IACzD,kBAAkB,CAAC,KAAwB;QACzC,IAAI,CAAC,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;gGAC4F;IAC5F,QAAQ,CAAC,OAAqB;QAC5B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC9C,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,EAAE,CAAC;YAClF,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,sFAAsF;IACtF,MAAM;QACJ,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC;IAC9D,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { PatternScanner } from './pattern-scanner.js';
|
|
2
|
+
export type { ScanResult, PatternMatch, PatternScannerOptions } from './pattern-scanner.js';
|
|
3
|
+
export { BlacklistFilter } from './blacklist-filter.js';
|
|
4
|
+
export type { BlacklistFilterOptions, FilterVerdict } from './blacklist-filter.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/security/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface PatternMatch {
|
|
2
|
+
/** Regex source as supplied to the scanner (caller's original string). */
|
|
3
|
+
pattern: string;
|
|
4
|
+
/** Substring of input that matched. */
|
|
5
|
+
match: string;
|
|
6
|
+
/** Zero-based character offset of the match in the input. */
|
|
7
|
+
index: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ScanResult {
|
|
10
|
+
/** true when zero patterns matched. */
|
|
11
|
+
safe: boolean;
|
|
12
|
+
/** All matches across all patterns, ordered by `index` ascending. */
|
|
13
|
+
matches: PatternMatch[];
|
|
14
|
+
}
|
|
15
|
+
export interface PatternScannerOptions {
|
|
16
|
+
/** Regex source strings. Each will be compiled once with the `g` flag for full-input scan. */
|
|
17
|
+
patterns: string[];
|
|
18
|
+
/** Compile flags appended to the default `g`. Defaults to `''` (case-sensitive). Pass `'i'` for case-insensitive. */
|
|
19
|
+
flags?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare class PatternScanner {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(opts: PatternScannerOptions);
|
|
24
|
+
scan(input: string): ScanResult;
|
|
25
|
+
getPatterns(): string[];
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=pattern-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-scanner.d.ts","sourceRoot":"","sources":["../../src/security/pattern-scanner.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,qEAAqE;IACrE,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qHAAqH;IACrH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,qBAAa,cAAc;;gBAGb,IAAI,EAAE,qBAAqB;IAyBvC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAoB/B,WAAW,IAAI,MAAM,EAAE;CAGxB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export class PatternScanner {
|
|
2
|
+
#compiled;
|
|
3
|
+
constructor(opts) {
|
|
4
|
+
const extraFlags = opts.flags ?? '';
|
|
5
|
+
const seen = new Set();
|
|
6
|
+
this.#compiled = [];
|
|
7
|
+
for (const source of opts.patterns) {
|
|
8
|
+
if (source === '') {
|
|
9
|
+
process.stderr.write(`[skillforge:pattern-scanner] invalid pattern "": empty pattern discarded\n`);
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (seen.has(source)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
seen.add(source);
|
|
16
|
+
try {
|
|
17
|
+
const regex = new RegExp(source, 'g' + extraFlags);
|
|
18
|
+
this.#compiled.push({ source, regex });
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
22
|
+
process.stderr.write(`[skillforge:pattern-scanner] invalid pattern "${source}": ${msg}\n`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
scan(input) {
|
|
27
|
+
const matches = [];
|
|
28
|
+
for (const { source, regex } of this.#compiled) {
|
|
29
|
+
regex.lastIndex = 0;
|
|
30
|
+
let m;
|
|
31
|
+
while ((m = regex.exec(input)) !== null) {
|
|
32
|
+
if (m[0].length === 0) {
|
|
33
|
+
regex.lastIndex++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
matches.push({ pattern: source, match: m[0], index: m.index });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
matches.sort((a, b) => a.index - b.index);
|
|
40
|
+
return { safe: matches.length === 0, matches };
|
|
41
|
+
}
|
|
42
|
+
getPatterns() {
|
|
43
|
+
return this.#compiled.map((e) => e.source);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=pattern-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-scanner.js","sourceRoot":"","sources":["../../src/security/pattern-scanner.ts"],"names":[],"mappings":"AA4BA,MAAM,OAAO,cAAc;IAChB,SAAS,CAAkB;IAEpC,YAAY,IAA2B;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;gBAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;gBACnG,SAAS;YACX,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrB,SAAS;YACX,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAEjB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,UAAU,CAAC,CAAC;gBACnD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAa;QAChB,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;YACpB,IAAI,CAAyB,CAAC;YAC9B,OAAO,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtB,KAAK,CAAC,SAAS,EAAE,CAAC;oBAClB,SAAS;gBACX,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IACjD,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;CACF"}
|