@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,59 @@
|
|
|
1
|
+
import { BaseDecorator } from './base-decorator.js';
|
|
2
|
+
export class TimeoutDecorator extends BaseDecorator {
|
|
3
|
+
#defaultMs;
|
|
4
|
+
#setTimeout;
|
|
5
|
+
#clearTimeout;
|
|
6
|
+
#clock;
|
|
7
|
+
constructor(inner, deps) {
|
|
8
|
+
super(inner);
|
|
9
|
+
this.#defaultMs = deps.defaultMs;
|
|
10
|
+
this.#setTimeout = deps.setTimeoutFn ?? setTimeout;
|
|
11
|
+
this.#clearTimeout = deps.clearTimeoutFn ?? clearTimeout;
|
|
12
|
+
this.#clock = deps.clock ?? (() => performance.now());
|
|
13
|
+
}
|
|
14
|
+
async invoke(skill, context) {
|
|
15
|
+
const timeoutMs = skill.timeoutMs ?? this.#defaultMs;
|
|
16
|
+
if (timeoutMs <= 0) {
|
|
17
|
+
// 0 / negative = disabled; pass through without timeout
|
|
18
|
+
return await this.inner.invoke(skill, context);
|
|
19
|
+
}
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const start = this.#clock();
|
|
22
|
+
let timer;
|
|
23
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
24
|
+
timer = this.#setTimeout(() => {
|
|
25
|
+
controller.abort();
|
|
26
|
+
resolve({
|
|
27
|
+
ok: false,
|
|
28
|
+
output: '',
|
|
29
|
+
error: 'timeout',
|
|
30
|
+
durationMs: Math.round(this.#clock() - start),
|
|
31
|
+
});
|
|
32
|
+
}, timeoutMs);
|
|
33
|
+
// Allow Node.js process to exit even if timer is pending
|
|
34
|
+
if (typeof timer.unref === 'function') {
|
|
35
|
+
timer.unref();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
// If caller passed a parent signal, link it: parent abort → child abort
|
|
39
|
+
if (context.signal) {
|
|
40
|
+
if (context.signal.aborted) {
|
|
41
|
+
controller.abort();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
context.signal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const innerPromise = this.inner.invoke(skill, { ...context, signal: controller.signal });
|
|
48
|
+
try {
|
|
49
|
+
const result = await Promise.race([innerPromise, timeoutPromise]);
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
if (timer !== undefined) {
|
|
54
|
+
this.#clearTimeout(timer);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=timeout-decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-decorator.js","sourceRoot":"","sources":["../../src/decorators/timeout-decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAepD,MAAM,OAAO,gBAAiB,SAAQ,aAAa;IACxC,UAAU,CAAS;IACnB,WAAW,CAAoB;IAC/B,aAAa,CAAsB;IACnC,MAAM,CAAe;IAE9B,YAAY,KAAyB,EAAE,IAA0B;QAC/D,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC;QACnD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,YAAY,CAAC;QACzD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAmB,EAAE,OAA0B;QAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC;QACrD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,wDAAwD;YACxD,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,KAAgD,CAAC;QAErD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;YAC/D,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE;gBAC5B,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnB,OAAO,CAAC;oBACN,EAAE,EAAE,KAAK;oBACT,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE,SAAS;oBAChB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC;iBAC9C,CAAC,CAAC;YACL,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,yDAAyD;YACzD,IAAI,OAAQ,KAA2C,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBAC5E,KAA0C,CAAC,KAAK,EAAE,CAAC;YACtD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,wEAAwE;QACxE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;YAClE,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SkillContent, StrategyKind } from '../core/types.js';
|
|
2
|
+
import type { InvocationStrategy } from '../handlers/invocation-strategy.js';
|
|
3
|
+
export declare class StrategyFactory {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(strategies?: InvocationStrategy[]);
|
|
6
|
+
register(strategy: InvocationStrategy): void;
|
|
7
|
+
create(skill: SkillContent): InvocationStrategy;
|
|
8
|
+
get registeredKinds(): StrategyKind[];
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=strategy-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy-factory.d.ts","sourceRoot":"","sources":["../../src/factory/strategy-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAE7E,qBAAa,eAAe;;gBAGd,UAAU,CAAC,EAAE,kBAAkB,EAAE;IAS7C,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAK5C,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,kBAAkB;IAsB/C,IAAI,eAAe,IAAI,YAAY,EAAE,CAEpC;CACF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class StrategyFactory {
|
|
2
|
+
#store;
|
|
3
|
+
constructor(strategies) {
|
|
4
|
+
this.#store = new Map();
|
|
5
|
+
if (strategies !== undefined) {
|
|
6
|
+
for (const strategy of strategies) {
|
|
7
|
+
this.register(strategy);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
register(strategy) {
|
|
12
|
+
// Set in place so existing keys keep their insertion position for auto-detect order.
|
|
13
|
+
this.#store.set(strategy.kind, strategy);
|
|
14
|
+
}
|
|
15
|
+
create(skill) {
|
|
16
|
+
if (this.#store.size === 0) {
|
|
17
|
+
throw new Error('StrategyFactory: no strategies registered');
|
|
18
|
+
}
|
|
19
|
+
if (skill.strategy !== undefined) {
|
|
20
|
+
const found = this.#store.get(skill.strategy);
|
|
21
|
+
if (found === undefined) {
|
|
22
|
+
throw new Error(`Strategy not registered: ${skill.strategy}`);
|
|
23
|
+
}
|
|
24
|
+
return found;
|
|
25
|
+
}
|
|
26
|
+
for (const strategy of this.#store.values()) {
|
|
27
|
+
if (strategy.canHandle(skill)) {
|
|
28
|
+
return strategy;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`No strategy can handle skill: ${skill.name}`);
|
|
32
|
+
}
|
|
33
|
+
get registeredKinds() {
|
|
34
|
+
return Array.from(this.#store.keys());
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=strategy-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy-factory.js","sourceRoot":"","sources":["../../src/factory/strategy-factory.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,eAAe;IACjB,MAAM,CAAwC;IAEvD,YAAY,UAAiC;QAC3C,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACxB,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;gBAClC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,QAA4B;QACnC,qFAAqF;QACrF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,KAAmB;QACxB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { InvocationContext, InvocationResult, SkillContent } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Function provided by caller to load SkillContent by name. Returns undefined
|
|
4
|
+
* if skill not registered. Composite resolver uses this in collectChain phase.
|
|
5
|
+
*/
|
|
6
|
+
export type SkillLoader = (name: string) => Promise<SkillContent | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* Function provided by caller to actually invoke a non-composite skill,
|
|
9
|
+
* including decorator chain wrapping + strategy factory dispatch. Composite
|
|
10
|
+
* resolver delegates leaf execution to this.
|
|
11
|
+
*/
|
|
12
|
+
export type SkillInvoker = (skill: SkillContent, context: InvocationContext) => Promise<InvocationResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Walk the composite chain depth-first, loading each referenced skill.
|
|
15
|
+
* Returns Map<name, SkillContent> for all reachable nodes plus the root.
|
|
16
|
+
* Throws CyclicSkillDependencyError if a cycle is found during traversal.
|
|
17
|
+
* Throws Error('unknown skill referenced from composite: <name>') if a
|
|
18
|
+
* reference cannot be resolved.
|
|
19
|
+
*/
|
|
20
|
+
export declare function collectChain(root: SkillContent, loadSkill: SkillLoader): Promise<Map<string, SkillContent>>;
|
|
21
|
+
/**
|
|
22
|
+
* Resolves a composite skill: cycle-check via collectChain → sequential invoke
|
|
23
|
+
* nested skills → concatenate outputs with separator.
|
|
24
|
+
*
|
|
25
|
+
* Parent body (root.body) is prepended as a leading section if non-empty.
|
|
26
|
+
* Sections are joined with '\n\n---\n\n'.
|
|
27
|
+
* Each nested skill section is prefixed with '## Skill: <name>\n\n'.
|
|
28
|
+
*
|
|
29
|
+
* Failure short-circuits: first failed nested invoke returns its result
|
|
30
|
+
* wrapped in a composite envelope; subsequent skills are NOT invoked.
|
|
31
|
+
* On cycle or unknown-skill errors, returns ok:false immediately.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveComposite(root: SkillContent, context: InvocationContext, loadSkill: SkillLoader, invokeSkill: SkillInvoker, clock?: () => number): Promise<InvocationResult>;
|
|
34
|
+
//# sourceMappingURL=composite-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite-resolver.d.ts","sourceRoot":"","sources":["../../src/handlers/composite-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG1F;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE1G;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,WAAW,GACrB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CA0BpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,WAAW,EACtB,WAAW,EAAE,YAAY,EACzB,KAAK,GAAE,MAAM,MAAgC,GAC5C,OAAO,CAAC,gBAAgB,CAAC,CAgD3B"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { CyclicSkillDependencyError } from '../core/errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walk the composite chain depth-first, loading each referenced skill.
|
|
4
|
+
* Returns Map<name, SkillContent> for all reachable nodes plus the root.
|
|
5
|
+
* Throws CyclicSkillDependencyError if a cycle is found during traversal.
|
|
6
|
+
* Throws Error('unknown skill referenced from composite: <name>') if a
|
|
7
|
+
* reference cannot be resolved.
|
|
8
|
+
*/
|
|
9
|
+
export async function collectChain(root, loadSkill) {
|
|
10
|
+
const collected = new Map();
|
|
11
|
+
collected.set(root.name, root);
|
|
12
|
+
const visit = async (current, stack) => {
|
|
13
|
+
const nested = current.skills ?? [];
|
|
14
|
+
for (const nestedName of nested) {
|
|
15
|
+
if (stack.includes(nestedName)) {
|
|
16
|
+
throw new CyclicSkillDependencyError([...stack, nestedName]);
|
|
17
|
+
}
|
|
18
|
+
if (!collected.has(nestedName)) {
|
|
19
|
+
const loaded = await loadSkill(nestedName);
|
|
20
|
+
if (!loaded) {
|
|
21
|
+
throw new Error(`unknown skill referenced from composite: ${nestedName}`);
|
|
22
|
+
}
|
|
23
|
+
collected.set(nestedName, loaded);
|
|
24
|
+
await visit(loaded, [...stack, nestedName]);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Already collected — still traverse to detect cycles through this subtree.
|
|
28
|
+
await visit(collected.get(nestedName), [...stack, nestedName]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
await visit(root, [root.name]);
|
|
33
|
+
return collected;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolves a composite skill: cycle-check via collectChain → sequential invoke
|
|
37
|
+
* nested skills → concatenate outputs with separator.
|
|
38
|
+
*
|
|
39
|
+
* Parent body (root.body) is prepended as a leading section if non-empty.
|
|
40
|
+
* Sections are joined with '\n\n---\n\n'.
|
|
41
|
+
* Each nested skill section is prefixed with '## Skill: <name>\n\n'.
|
|
42
|
+
*
|
|
43
|
+
* Failure short-circuits: first failed nested invoke returns its result
|
|
44
|
+
* wrapped in a composite envelope; subsequent skills are NOT invoked.
|
|
45
|
+
* On cycle or unknown-skill errors, returns ok:false immediately.
|
|
46
|
+
*/
|
|
47
|
+
export async function resolveComposite(root, context, loadSkill, invokeSkill, clock = () => performance.now()) {
|
|
48
|
+
const start = clock();
|
|
49
|
+
let chain;
|
|
50
|
+
try {
|
|
51
|
+
chain = await collectChain(root, loadSkill);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
output: '',
|
|
58
|
+
error: msg,
|
|
59
|
+
durationMs: Math.round(clock() - start),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const nestedNames = root.skills ?? [];
|
|
63
|
+
const sections = [];
|
|
64
|
+
const rootBody = (root.body ?? '').trim();
|
|
65
|
+
if (rootBody.length > 0)
|
|
66
|
+
sections.push(rootBody);
|
|
67
|
+
for (const name of nestedNames) {
|
|
68
|
+
const skill = chain.get(name);
|
|
69
|
+
if (!skill) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
output: '',
|
|
73
|
+
error: `unknown skill referenced from composite: ${name}`,
|
|
74
|
+
durationMs: Math.round(clock() - start),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const childResult = await invokeSkill(skill, context);
|
|
78
|
+
if (!childResult.ok) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
output: childResult.output,
|
|
82
|
+
error: `nested skill ${name} failed: ${childResult.error ?? 'unknown error'}`,
|
|
83
|
+
durationMs: Math.round(clock() - start),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
sections.push(`## Skill: ${name}\n\n${childResult.output.trim()}`);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
output: sections.join('\n\n---\n\n'),
|
|
91
|
+
durationMs: Math.round(clock() - start),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=composite-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite-resolver.js","sourceRoot":"","sources":["../../src/handlers/composite-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InvocationStrategy } from './invocation-strategy.js';
|
|
2
|
+
import type { InvocationContext, InvocationResult, SkillContent, StrategyKind } from '../core/types.js';
|
|
3
|
+
export interface HybridStrategyDeps {
|
|
4
|
+
scriptStrategy: InvocationStrategy;
|
|
5
|
+
clock?: () => number;
|
|
6
|
+
}
|
|
7
|
+
export declare class HybridStrategy implements InvocationStrategy {
|
|
8
|
+
#private;
|
|
9
|
+
readonly kind: StrategyKind;
|
|
10
|
+
constructor(deps: HybridStrategyDeps);
|
|
11
|
+
canHandle(skill: SkillContent): boolean;
|
|
12
|
+
invoke(skill: SkillContent, context: InvocationContext): Promise<InvocationResult>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=hybrid-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-strategy.d.ts","sourceRoot":"","sources":["../../src/handlers/hybrid-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACb,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,kBAAkB,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAkBD,qBAAa,cAAe,YAAW,kBAAkB;;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAY;gBAI3B,IAAI,EAAE,kBAAkB;IAKpC,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAIjC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAkBzF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const SECTION_SEP = '\n\n';
|
|
2
|
+
function assembleHybridPrompt(body, scriptOutput, userInput) {
|
|
3
|
+
const trimmedBody = body.trim();
|
|
4
|
+
const trimmedScript = scriptOutput.trim();
|
|
5
|
+
const trimmedInput = userInput.trim();
|
|
6
|
+
const sections = [];
|
|
7
|
+
if (trimmedBody.length > 0)
|
|
8
|
+
sections.push(trimmedBody);
|
|
9
|
+
sections.push(`## Script output${SECTION_SEP}${trimmedScript}`);
|
|
10
|
+
if (trimmedInput.length > 0) {
|
|
11
|
+
sections.push(`## User input${SECTION_SEP}${trimmedInput}`);
|
|
12
|
+
}
|
|
13
|
+
return sections.join(SECTION_SEP);
|
|
14
|
+
}
|
|
15
|
+
export class HybridStrategy {
|
|
16
|
+
kind = 'hybrid';
|
|
17
|
+
#script;
|
|
18
|
+
#clock;
|
|
19
|
+
constructor(deps) {
|
|
20
|
+
this.#script = deps.scriptStrategy;
|
|
21
|
+
this.#clock = deps.clock ?? (() => performance.now());
|
|
22
|
+
}
|
|
23
|
+
canHandle(skill) {
|
|
24
|
+
return skill.strategy === 'hybrid';
|
|
25
|
+
}
|
|
26
|
+
async invoke(skill, context) {
|
|
27
|
+
const start = this.#clock();
|
|
28
|
+
const scriptResult = await this.#script.invoke(skill, context);
|
|
29
|
+
// Failure short-circuits — no prompt blend on failure.
|
|
30
|
+
if (!scriptResult.ok) {
|
|
31
|
+
return scriptResult;
|
|
32
|
+
}
|
|
33
|
+
const promptBlob = assembleHybridPrompt(skill.body ?? '', scriptResult.output, context.input);
|
|
34
|
+
const durationMs = Math.round(this.#clock() - start);
|
|
35
|
+
return {
|
|
36
|
+
ok: true,
|
|
37
|
+
output: promptBlob,
|
|
38
|
+
durationMs,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=hybrid-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-strategy.js","sourceRoot":"","sources":["../../src/handlers/hybrid-strategy.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,GAAG,MAAM,CAAC;AAE3B,SAAS,oBAAoB,CAAC,IAAY,EAAE,YAAoB,EAAE,SAAiB;IACjF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,QAAQ,CAAC,IAAI,CAAC,mBAAmB,WAAW,GAAG,aAAa,EAAE,CAAC,CAAC;IAChE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,gBAAgB,WAAW,GAAG,YAAY,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,OAAO,cAAc;IAChB,IAAI,GAAiB,QAAQ,CAAC;IAC9B,OAAO,CAAqB;IAC5B,MAAM,CAAe;IAE9B,YAAY,IAAwB;QAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,SAAS,CAAC,KAAmB;QAC3B,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAmB,EAAE,OAA0B;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAE/D,uDAAuD;QACvD,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;YACrB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9F,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC;QAErD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,UAAU;YAClB,UAAU;SACX,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InvocationContext, InvocationResult, SkillContent, StrategyKind } from '../core/types.js';
|
|
2
|
+
export interface InvocationStrategy {
|
|
3
|
+
/** Identifier — matches StrategyKind so StrategyFactory can index by kind. */
|
|
4
|
+
readonly kind: StrategyKind;
|
|
5
|
+
/**
|
|
6
|
+
* Returns true if this strategy is capable of executing the given skill.
|
|
7
|
+
* PromptStrategy returns true for any skill (default fallback).
|
|
8
|
+
* ScriptStrategy will require allowScripts + a scripts/ dir.
|
|
9
|
+
*/
|
|
10
|
+
canHandle(skill: SkillContent): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Execute the skill. Implementations MUST catch their own errors and
|
|
13
|
+
* surface them via `InvocationResult { ok: false, error }` — never throw.
|
|
14
|
+
*/
|
|
15
|
+
invoke(skill: SkillContent, context: InvocationContext): Promise<InvocationResult>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=invocation-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invocation-strategy.d.ts","sourceRoot":"","sources":["../../src/handlers/invocation-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACb,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAE5B;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;IAExC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACpF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invocation-strategy.js","sourceRoot":"","sources":["../../src/handlers/invocation-strategy.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InvocationContext, InvocationResult, SkillContent, StrategyKind } from '../core/types.js';
|
|
2
|
+
import type { InvocationStrategy } from './invocation-strategy.js';
|
|
3
|
+
export declare class PromptStrategy implements InvocationStrategy {
|
|
4
|
+
readonly kind: StrategyKind;
|
|
5
|
+
canHandle(_skill: SkillContent): boolean;
|
|
6
|
+
invoke(skill: SkillContent, context: InvocationContext): Promise<InvocationResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=prompt-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-strategy.d.ts","sourceRoot":"","sources":["../../src/handlers/prompt-strategy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,qBAAa,cAAe,YAAW,kBAAkB;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAY;IAEvC,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAIlC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAuBzF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { performance } from 'node:perf_hooks';
|
|
2
|
+
export class PromptStrategy {
|
|
3
|
+
kind = 'prompt';
|
|
4
|
+
canHandle(_skill) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
async invoke(skill, context) {
|
|
8
|
+
const start = performance.now();
|
|
9
|
+
try {
|
|
10
|
+
const parts = [];
|
|
11
|
+
parts.push(`# Skill: ${skill.name}`);
|
|
12
|
+
if (skill.description !== undefined && skill.description !== '') {
|
|
13
|
+
parts.push(skill.description);
|
|
14
|
+
}
|
|
15
|
+
parts.push('');
|
|
16
|
+
parts.push(skill.body);
|
|
17
|
+
parts.push('');
|
|
18
|
+
parts.push('## Input');
|
|
19
|
+
parts.push(context.input);
|
|
20
|
+
const output = parts.join('\n');
|
|
21
|
+
const durationMs = Math.max(0, Math.round(performance.now() - start));
|
|
22
|
+
return { ok: true, output, durationMs };
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const durationMs = Math.max(0, Math.round(performance.now() - start));
|
|
26
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
27
|
+
return { ok: false, output: '', error, durationMs };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=prompt-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-strategy.js","sourceRoot":"","sources":["../../src/handlers/prompt-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAS9C,MAAM,OAAO,cAAc;IAChB,IAAI,GAAiB,QAAQ,CAAC;IAEvC,SAAS,CAAC,MAAoB;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAmB,EAAE,OAA0B;QAC1D,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC;YACH,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACrC,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,EAAE,EAAE,CAAC;gBAChE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAChC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE1B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;YACtE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;YACtE,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { InvocationContext, InvocationResult, SkillContent, StrategyKind } from '../core/types.js';
|
|
2
|
+
import type { InvocationStrategy } from './invocation-strategy.js';
|
|
3
|
+
import type { SandboxRunner } from '../security/sandbox-runner.js';
|
|
4
|
+
import type { Logger } from '../decorators/logging-decorator.js';
|
|
5
|
+
export interface ScriptStrategyDeps {
|
|
6
|
+
sandboxRunner: SandboxRunner;
|
|
7
|
+
/** Reads global `config.security.allowScripts` at invoke-time (not boot-time)
|
|
8
|
+
* so config changes via `mcp__skills__configure` reflect without restart. */
|
|
9
|
+
isGloballyAllowed: () => boolean;
|
|
10
|
+
logger?: Logger;
|
|
11
|
+
clock?: () => number;
|
|
12
|
+
}
|
|
13
|
+
export declare class ScriptStrategy implements InvocationStrategy {
|
|
14
|
+
#private;
|
|
15
|
+
readonly kind: StrategyKind;
|
|
16
|
+
constructor(deps: ScriptStrategyDeps);
|
|
17
|
+
canHandle(skill: SkillContent): boolean;
|
|
18
|
+
invoke(skill: SkillContent, context: InvocationContext): Promise<InvocationResult>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=script-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-strategy.d.ts","sourceRoot":"","sources":["../../src/handlers/script-strategy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAEjE,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B;kFAC8E;IAC9E,iBAAiB,EAAE,MAAM,OAAO,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAkBD,qBAAa,cAAe,YAAW,kBAAkB;;IACvD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAY;gBAM3B,IAAI,EAAE,kBAAkB;IAOpC,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAOjC,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA0DzF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
const INTERPRETER_BY_EXT = {
|
|
3
|
+
'.py': { cmd: 'python3', needsScriptPath: true },
|
|
4
|
+
'.sh': { cmd: 'bash', needsScriptPath: true },
|
|
5
|
+
'.js': { cmd: 'node', needsScriptPath: true },
|
|
6
|
+
'.mjs': { cmd: 'node', needsScriptPath: true },
|
|
7
|
+
};
|
|
8
|
+
function lowerExt(name) {
|
|
9
|
+
const dot = name.lastIndexOf('.');
|
|
10
|
+
return dot < 0 ? '' : name.slice(dot).toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
function fail(error, durationMs = 0) {
|
|
13
|
+
return { ok: false, output: '', error, durationMs };
|
|
14
|
+
}
|
|
15
|
+
export class ScriptStrategy {
|
|
16
|
+
kind = 'script';
|
|
17
|
+
#sandbox;
|
|
18
|
+
#isGlobalAllowed;
|
|
19
|
+
#logger;
|
|
20
|
+
#clock;
|
|
21
|
+
constructor(deps) {
|
|
22
|
+
this.#sandbox = deps.sandboxRunner;
|
|
23
|
+
this.#isGlobalAllowed = deps.isGloballyAllowed;
|
|
24
|
+
this.#logger = deps.logger;
|
|
25
|
+
this.#clock = deps.clock ?? (() => performance.now());
|
|
26
|
+
}
|
|
27
|
+
canHandle(skill) {
|
|
28
|
+
if (skill.strategy === 'script')
|
|
29
|
+
return true;
|
|
30
|
+
if (skill.strategy !== undefined)
|
|
31
|
+
return false;
|
|
32
|
+
// Auto-detect: scripts[] non-empty.
|
|
33
|
+
return Array.isArray(skill.scripts) && skill.scripts.length > 0;
|
|
34
|
+
}
|
|
35
|
+
async invoke(skill, context) {
|
|
36
|
+
const start = this.#clock();
|
|
37
|
+
// Gate 1: global config flag.
|
|
38
|
+
if (!this.#isGlobalAllowed()) {
|
|
39
|
+
return fail('scripts disabled globally (config.security.allowScripts=false)', Math.round(this.#clock() - start));
|
|
40
|
+
}
|
|
41
|
+
// Gate 2: per-skill opt-in.
|
|
42
|
+
if (skill.allowScripts !== true) {
|
|
43
|
+
return fail('scripts disabled for this skill (metadata.allowScripts must be true)', Math.round(this.#clock() - start));
|
|
44
|
+
}
|
|
45
|
+
// Resolve script path: single-entry only.
|
|
46
|
+
const entries = skill.scripts ?? [];
|
|
47
|
+
if (entries.length === 0) {
|
|
48
|
+
return fail('no script entries declared (metadata.scripts is empty)', Math.round(this.#clock() - start));
|
|
49
|
+
}
|
|
50
|
+
if (!skill.scriptsDir) {
|
|
51
|
+
return fail('no scripts/ directory found next to skill file', Math.round(this.#clock() - start));
|
|
52
|
+
}
|
|
53
|
+
const scriptName = entries[0];
|
|
54
|
+
const ext = lowerExt(scriptName);
|
|
55
|
+
const interp = INTERPRETER_BY_EXT[ext];
|
|
56
|
+
if (!interp) {
|
|
57
|
+
return fail(`unsupported script extension: ${ext || '(none)'} — allowed: .py, .sh, .js, .mjs`, Math.round(this.#clock() - start));
|
|
58
|
+
}
|
|
59
|
+
const scriptPath = join(skill.scriptsDir, scriptName);
|
|
60
|
+
try {
|
|
61
|
+
const sandboxResult = await this.#sandbox.run(interp.cmd, [scriptPath], {
|
|
62
|
+
env: { SKILLFORGE_INPUT: context.input },
|
|
63
|
+
signal: context.signal,
|
|
64
|
+
allowNetwork: skill.allowNetwork === true,
|
|
65
|
+
});
|
|
66
|
+
const durationMs = sandboxResult.durationMs;
|
|
67
|
+
if (sandboxResult.timedOut) {
|
|
68
|
+
return { ok: false, output: sandboxResult.stdout, error: 'timeout', durationMs };
|
|
69
|
+
}
|
|
70
|
+
if (sandboxResult.exitCode === 0) {
|
|
71
|
+
return { ok: true, output: sandboxResult.stdout, durationMs };
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
output: sandboxResult.stdout,
|
|
76
|
+
error: sandboxResult.stderr || `exit code ${sandboxResult.exitCode}`,
|
|
77
|
+
durationMs,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
82
|
+
this.#logger?.error(`[skillforge] script-strategy error skill=${skill.name} err=${errMsg}`);
|
|
83
|
+
return fail(`sandbox error: ${errMsg}`, Math.round(this.#clock() - start));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=script-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-strategy.js","sourceRoot":"","sources":["../../src/handlers/script-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic JSON / TOML helpers with .backup snapshots.
|
|
3
|
+
*
|
|
4
|
+
* Read helpers return null on missing file, throw on corrupt content.
|
|
5
|
+
* Write helpers go via <path>.tmp + fs.rename and snapshot the previous
|
|
6
|
+
* content into <path>.backup before overwriting. On rename failure the
|
|
7
|
+
* backup is restored.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readJsonSafe(path: string): Promise<unknown | null>;
|
|
10
|
+
export declare function readTomlSafe(path: string): Promise<Record<string, unknown> | null>;
|
|
11
|
+
export declare function writeJsonAtomic(path: string, data: unknown): Promise<void>;
|
|
12
|
+
export declare function writeTomlAtomic(path: string, data: Record<string, unknown>): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=atomic-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic-write.d.ts","sourceRoot":"","sources":["../../src/installers/atomic-write.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAeH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAaxE;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAaxF;AA6BD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhG"}
|