@botbotgo/kit 1.0.104
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/README.md +65 -0
- package/config/build/build.sh +182 -0
- package/config/build/tsconfig.dts.json +34 -0
- package/config/build/tsup.config.ts +19 -0
- package/config/build/vitest.config.ts +29 -0
- package/config/tool.yaml +11 -0
- package/dist/agent-context.d.ts +3 -0
- package/dist/agent-context.d.ts.map +1 -0
- package/dist/api/adapters/LangChainToolsHub.d.ts +35 -0
- package/dist/api/adapters/LangChainToolsHub.d.ts.map +1 -0
- package/dist/api/createAgentTools.d.ts +52 -0
- package/dist/api/createAgentTools.d.ts.map +1 -0
- package/dist/api/expose/extension-init/index.d.ts +3 -0
- package/dist/api/expose/extension-init/index.d.ts.map +1 -0
- package/dist/api/expose/extension-init/initExtension.d.ts +21 -0
- package/dist/api/expose/extension-init/initExtension.d.ts.map +1 -0
- package/dist/api/expose/index.d.ts +16 -0
- package/dist/api/expose/index.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/build.d.ts +21 -0
- package/dist/api/expose/mcp-build/build.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/generator.d.ts +15 -0
- package/dist/api/expose/mcp-build/generator.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/index.d.ts +8 -0
- package/dist/api/expose/mcp-build/index.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/init.d.ts +17 -0
- package/dist/api/expose/mcp-build/init.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/run.d.ts +17 -0
- package/dist/api/expose/mcp-build/run.d.ts.map +1 -0
- package/dist/api/expose/mcp-build/types.d.ts +25 -0
- package/dist/api/expose/mcp-build/types.d.ts.map +1 -0
- package/dist/api/expose/mcpServer.d.ts +74 -0
- package/dist/api/expose/mcpServer.d.ts.map +1 -0
- package/dist/api/expose/openapi.d.ts +23 -0
- package/dist/api/expose/openapi.d.ts.map +1 -0
- package/dist/api/expose/openapiHttp.d.ts +51 -0
- package/dist/api/expose/openapiHttp.d.ts.map +1 -0
- package/dist/api/extension/contextRunner.d.ts +10 -0
- package/dist/api/extension/contextRunner.d.ts.map +1 -0
- package/dist/api/extension/createExtension.d.ts +38 -0
- package/dist/api/extension/createExtension.d.ts.map +1 -0
- package/dist/api/extension/dynamicImportAdapter.d.ts +25 -0
- package/dist/api/extension/dynamicImportAdapter.d.ts.map +1 -0
- package/dist/api/extension/generateExtensionManifest.d.ts +29 -0
- package/dist/api/extension/generateExtensionManifest.d.ts.map +1 -0
- package/dist/api/extension/index.d.ts +23 -0
- package/dist/api/extension/index.d.ts.map +1 -0
- package/dist/api/extension/loadToolYaml.d.ts +7 -0
- package/dist/api/extension/loadToolYaml.d.ts.map +1 -0
- package/dist/api/extension/overrideWithConfig.d.ts +2 -0
- package/dist/api/extension/overrideWithConfig.d.ts.map +1 -0
- package/dist/api/extension/registerExtension.d.ts +32 -0
- package/dist/api/extension/registerExtension.d.ts.map +1 -0
- package/dist/api/extension/registerFromManifest.d.ts +43 -0
- package/dist/api/extension/registerFromManifest.d.ts.map +1 -0
- package/dist/api/extension/resolvePackageRoot.d.ts +2 -0
- package/dist/api/extension/resolvePackageRoot.d.ts.map +1 -0
- package/dist/api/extension/support/groupPrefix.d.ts +21 -0
- package/dist/api/extension/support/groupPrefix.d.ts.map +1 -0
- package/dist/api/extension/support/types.d.ts +15 -0
- package/dist/api/extension/support/types.d.ts.map +1 -0
- package/dist/api/register-tools.d.ts +17 -0
- package/dist/api/register-tools.d.ts.map +1 -0
- package/dist/api/resolveAgentSkillRoots.d.ts +7 -0
- package/dist/api/resolveAgentSkillRoots.d.ts.map +1 -0
- package/dist/api/runtimeFromConfig.d.ts +20 -0
- package/dist/api/runtimeFromConfig.d.ts.map +1 -0
- package/dist/api/runtimeFromConfig.helpers.d.ts +12 -0
- package/dist/api/runtimeFromConfig.helpers.d.ts.map +1 -0
- package/dist/api/runtimeFromConfig.types.d.ts +37 -0
- package/dist/api/runtimeFromConfig.types.d.ts.map +1 -0
- package/dist/build.cjs +30 -0
- package/dist/build.cjs.map +1 -0
- package/dist/build.d.ts +13 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +5 -0
- package/dist/build.js.map +1 -0
- package/dist/canonicalCoreSchemas-PHGTNPN5.js +3 -0
- package/dist/canonicalCoreSchemas-PHGTNPN5.js.map +1 -0
- package/dist/canonicalCoreSchemas-TY7NCWCC.cjs +16 -0
- package/dist/canonicalCoreSchemas-TY7NCWCC.cjs.map +1 -0
- package/dist/chunk-4OOTCNR7.js +324 -0
- package/dist/chunk-4OOTCNR7.js.map +1 -0
- package/dist/chunk-AGLGFQUW.cjs +259 -0
- package/dist/chunk-AGLGFQUW.cjs.map +1 -0
- package/dist/chunk-AZUXVVGV.cjs +1073 -0
- package/dist/chunk-AZUXVVGV.cjs.map +1 -0
- package/dist/chunk-BDUSB6GT.js +520 -0
- package/dist/chunk-BDUSB6GT.js.map +1 -0
- package/dist/chunk-BNIE2IKZ.cjs +100 -0
- package/dist/chunk-BNIE2IKZ.cjs.map +1 -0
- package/dist/chunk-BTHDNP3C.cjs +350 -0
- package/dist/chunk-BTHDNP3C.cjs.map +1 -0
- package/dist/chunk-GGFAGLDC.js +1049 -0
- package/dist/chunk-GGFAGLDC.js.map +1 -0
- package/dist/chunk-ITX6A2BT.js +92 -0
- package/dist/chunk-ITX6A2BT.js.map +1 -0
- package/dist/chunk-IVL4TBFB.js +248 -0
- package/dist/chunk-IVL4TBFB.js.map +1 -0
- package/dist/chunk-JW4EMVTE.cjs +553 -0
- package/dist/chunk-JW4EMVTE.cjs.map +1 -0
- package/dist/chunk-LNVK4GO7.cjs +3043 -0
- package/dist/chunk-LNVK4GO7.cjs.map +1 -0
- package/dist/chunk-NTWOVFEY.js +16 -0
- package/dist/chunk-NTWOVFEY.js.map +1 -0
- package/dist/chunk-P5XFA3MW.js +3013 -0
- package/dist/chunk-P5XFA3MW.js.map +1 -0
- package/dist/chunk-UUNG3GL3.cjs +19 -0
- package/dist/chunk-UUNG3GL3.cjs.map +1 -0
- package/dist/core/registry/ToolRegistry.d.ts +68 -0
- package/dist/core/registry/ToolRegistry.d.ts.map +1 -0
- package/dist/core/runtime/Budget.d.ts +63 -0
- package/dist/core/runtime/Budget.d.ts.map +1 -0
- package/dist/core/runtime/Evidence.d.ts +19 -0
- package/dist/core/runtime/Evidence.d.ts.map +1 -0
- package/dist/core/runtime/PTCRuntime.d.ts +124 -0
- package/dist/core/runtime/PTCRuntime.d.ts.map +1 -0
- package/dist/core/runtime/PTCRuntimeObservability.d.ts +26 -0
- package/dist/core/runtime/PTCRuntimeObservability.d.ts.map +1 -0
- package/dist/core/runtime/PTCRuntimePipeline.d.ts +69 -0
- package/dist/core/runtime/PTCRuntimePipeline.d.ts.map +1 -0
- package/dist/core/runtime/PolicyEngine.d.ts +67 -0
- package/dist/core/runtime/PolicyEngine.d.ts.map +1 -0
- package/dist/core/runtime/Retry.d.ts +33 -0
- package/dist/core/runtime/Retry.d.ts.map +1 -0
- package/dist/core/runtime/SchemaValidator.d.ts +42 -0
- package/dist/core/runtime/SchemaValidator.d.ts.map +1 -0
- package/dist/core/runtime/toolObservation.d.ts +7 -0
- package/dist/core/runtime/toolObservation.d.ts.map +1 -0
- package/dist/core/types/Events.d.ts +99 -0
- package/dist/core/types/Events.d.ts.map +1 -0
- package/dist/core/types/ToolIntent.d.ts +40 -0
- package/dist/core/types/ToolIntent.d.ts.map +1 -0
- package/dist/core/types/ToolResult.d.ts +44 -0
- package/dist/core/types/ToolResult.d.ts.map +1 -0
- package/dist/core/types/ToolSpec.d.ts +116 -0
- package/dist/core/types/ToolSpec.d.ts.map +1 -0
- package/dist/core/types/ToolTypeHandler.d.ts +88 -0
- package/dist/core/types/ToolTypeHandler.d.ts.map +1 -0
- package/dist/core/types/index.d.ts +7 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/index.cjs +399 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +394 -0
- package/dist/index.js.map +1 -0
- package/dist/observability/EventLog.d.ts +60 -0
- package/dist/observability/EventLog.d.ts.map +1 -0
- package/dist/observability/Logger.d.ts +33 -0
- package/dist/observability/Logger.d.ts.map +1 -0
- package/dist/observability/Metrics.d.ts +70 -0
- package/dist/observability/Metrics.d.ts.map +1 -0
- package/dist/observability/Tracing.d.ts +69 -0
- package/dist/observability/Tracing.d.ts.map +1 -0
- package/dist/sdk.cjs +493 -0
- package/dist/sdk.cjs.map +1 -0
- package/dist/sdk.d.ts +17 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +443 -0
- package/dist/sdk.js.map +1 -0
- package/dist/security/sandbox.d.ts +10 -0
- package/dist/security/sandbox.d.ts.map +1 -0
- package/dist/security/ssrf.d.ts +24 -0
- package/dist/security/ssrf.d.ts.map +1 -0
- package/dist/templates/mcp-server.js +48 -0
- package/dist/templates/n8n-invoker.js +11 -0
- package/dist/templates/skill-invoker.js +11 -0
- package/dist/templates/tool-index.js +9 -0
- package/dist/tools/discoveryFactory.d.ts +117 -0
- package/dist/tools/discoveryFactory.d.ts.map +1 -0
- package/dist/tools/function/index.d.ts +10 -0
- package/dist/tools/function/index.d.ts.map +1 -0
- package/dist/tools/function/scanner.d.ts +29 -0
- package/dist/tools/function/scanner.d.ts.map +1 -0
- package/dist/tools/function/schemaFromTs.d.ts +16 -0
- package/dist/tools/function/schemaFromTs.d.ts.map +1 -0
- package/dist/tools/function/types.d.ts +20 -0
- package/dist/tools/function/types.d.ts.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/langchain/LangChainLoader.d.ts +7 -0
- package/dist/tools/langchain/LangChainLoader.d.ts.map +1 -0
- package/dist/tools/langchain/directoryApply.d.ts +5 -0
- package/dist/tools/langchain/directoryApply.d.ts.map +1 -0
- package/dist/tools/langchain/directoryLoad.d.ts +13 -0
- package/dist/tools/langchain/directoryLoad.d.ts.map +1 -0
- package/dist/tools/langchain/index.d.ts +3 -0
- package/dist/tools/langchain/index.d.ts.map +1 -0
- package/dist/tools/langchain/scanner.d.ts +8 -0
- package/dist/tools/langchain/scanner.d.ts.map +1 -0
- package/dist/tools/langchain/types.d.ts +5 -0
- package/dist/tools/langchain/types.d.ts.map +1 -0
- package/dist/tools/mcp/MCPClientAdapter.d.ts +34 -0
- package/dist/tools/mcp/MCPClientAdapter.d.ts.map +1 -0
- package/dist/tools/mcp/MCPLoader.d.ts +8 -0
- package/dist/tools/mcp/MCPLoader.d.ts.map +1 -0
- package/dist/tools/mcp/MCPProcessManager.d.ts +29 -0
- package/dist/tools/mcp/MCPProcessManager.d.ts.map +1 -0
- package/dist/tools/mcp/connectMCP.d.ts +47 -0
- package/dist/tools/mcp/connectMCP.d.ts.map +1 -0
- package/dist/tools/mcp/directoryApply.d.ts +10 -0
- package/dist/tools/mcp/directoryApply.d.ts.map +1 -0
- package/dist/tools/mcp/index.d.ts +16 -0
- package/dist/tools/mcp/index.d.ts.map +1 -0
- package/dist/tools/mcp/mcpSpecToToolSpec.d.ts +8 -0
- package/dist/tools/mcp/mcpSpecToToolSpec.d.ts.map +1 -0
- package/dist/tools/mcp/registerMCPTools.d.ts +24 -0
- package/dist/tools/mcp/registerMCPTools.d.ts.map +1 -0
- package/dist/tools/mcp/scanner.d.ts +8 -0
- package/dist/tools/mcp/scanner.d.ts.map +1 -0
- package/dist/tools/mcp/support/types.d.ts +3 -0
- package/dist/tools/mcp/support/types.d.ts.map +1 -0
- package/dist/tools/n8n/N8nLoader.d.ts +25 -0
- package/dist/tools/n8n/N8nLoader.d.ts.map +1 -0
- package/dist/tools/n8n/directoryApply.d.ts +10 -0
- package/dist/tools/n8n/directoryApply.d.ts.map +1 -0
- package/dist/tools/n8n/index.d.ts +6 -0
- package/dist/tools/n8n/index.d.ts.map +1 -0
- package/dist/tools/n8n/scanN8n.d.ts +20 -0
- package/dist/tools/n8n/scanN8n.d.ts.map +1 -0
- package/dist/tools/n8n/types.d.ts +18 -0
- package/dist/tools/n8n/types.d.ts.map +1 -0
- package/dist/tools/scanPackage.d.ts +42 -0
- package/dist/tools/scanPackage.d.ts.map +1 -0
- package/dist/tools/skill/SkillLoader.d.ts +20 -0
- package/dist/tools/skill/SkillLoader.d.ts.map +1 -0
- package/dist/tools/skill/SkillManifest.d.ts +79 -0
- package/dist/tools/skill/SkillManifest.d.ts.map +1 -0
- package/dist/tools/skill/SkillMdParser.d.ts +31 -0
- package/dist/tools/skill/SkillMdParser.d.ts.map +1 -0
- package/dist/tools/skill/directoryApply.d.ts +10 -0
- package/dist/tools/skill/directoryApply.d.ts.map +1 -0
- package/dist/tools/skill/index.d.ts +8 -0
- package/dist/tools/skill/index.d.ts.map +1 -0
- package/dist/tools/skill/scanSkill.d.ts +20 -0
- package/dist/tools/skill/scanSkill.d.ts.map +1 -0
- package/dist/tools/skill/types.d.ts +19 -0
- package/dist/tools/skill/types.d.ts.map +1 -0
- package/dist/tools/util/canonicalCoreSchemas.d.ts +15 -0
- package/dist/tools/util/canonicalCoreSchemas.d.ts.map +1 -0
- package/dist/tools/util/index.d.ts +13 -0
- package/dist/tools/util/index.d.ts.map +1 -0
- package/dist/tools/util/resolveEntry.d.ts +6 -0
- package/dist/tools/util/resolveEntry.d.ts.map +1 -0
- package/dist/tools/util/scanUtil.d.ts +9 -0
- package/dist/tools/util/scanUtil.d.ts.map +1 -0
- package/dist/tools/util/toolConfig.d.ts +38 -0
- package/dist/tools/util/toolConfig.d.ts.map +1 -0
- package/dist/tools/util/toolDescriptor.d.ts +117 -0
- package/dist/tools/util/toolDescriptor.d.ts.map +1 -0
- package/dist/utils/cli/help.d.ts +2 -0
- package/dist/utils/cli/help.d.ts.map +1 -0
- package/dist/utils/cli/index.cjs +700 -0
- package/dist/utils/cli/index.cjs.map +1 -0
- package/dist/utils/cli/index.d.ts +9 -0
- package/dist/utils/cli/index.d.ts.map +1 -0
- package/dist/utils/cli/index.js +677 -0
- package/dist/utils/cli/index.js.map +1 -0
- package/dist/utils/cli/toolRuntime.d.ts +19 -0
- package/dist/utils/cli/toolRuntime.d.ts.map +1 -0
- package/dist/utils/log.d.ts +2 -0
- package/dist/utils/log.d.ts.map +1 -0
- package/dist/utils/npmCache.d.ts +11 -0
- package/dist/utils/npmCache.d.ts.map +1 -0
- package/dist/utils/npmVersion.d.ts +10 -0
- package/dist/utils/npmVersion.d.ts.map +1 -0
- package/dist/utils/overrideWithConfig.d.ts +2 -0
- package/dist/utils/overrideWithConfig.d.ts.map +1 -0
- package/package.json +125 -0
|
@@ -0,0 +1,1073 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkJW4EMVTE_cjs = require('./chunk-JW4EMVTE.cjs');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
|
+
var utils = require('@botbotgo/common/utils');
|
|
7
|
+
var url = require('url');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
28
|
+
|
|
29
|
+
// src/tools/mcp/support/types.ts
|
|
30
|
+
var MCP_KIND = "mcp";
|
|
31
|
+
var DEFAULT_EXTENSIONS = [".js", ".mjs"];
|
|
32
|
+
async function resolveEntryPoint(dirPath, baseName, extensions = DEFAULT_EXTENSIONS) {
|
|
33
|
+
if (extensions.some((ext) => baseName.endsWith(ext))) {
|
|
34
|
+
const fullPath = path.join(dirPath, baseName);
|
|
35
|
+
await promises.stat(fullPath);
|
|
36
|
+
return fullPath;
|
|
37
|
+
}
|
|
38
|
+
for (const ext of extensions) {
|
|
39
|
+
const fullPath = path.join(dirPath, `${baseName}${ext}`);
|
|
40
|
+
try {
|
|
41
|
+
await promises.stat(fullPath);
|
|
42
|
+
return fullPath;
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Could not find entry point in ${dirPath}. Tried: ${extensions.map((e) => baseName + e).join(", ")}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/tools/skill/SkillManifest.ts
|
|
52
|
+
var SkillManifestError = class extends Error {
|
|
53
|
+
constructor(path6, field, message) {
|
|
54
|
+
super(`SKILL.md error in ${path6}: ${message}`);
|
|
55
|
+
this.path = path6;
|
|
56
|
+
this.field = field;
|
|
57
|
+
this.name = "SkillManifestError";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var NAME_PATTERN = /^[a-z0-9-]+$/;
|
|
61
|
+
var NAME_MAX_LENGTH = 64;
|
|
62
|
+
var DESCRIPTION_MAX_LENGTH = 1024;
|
|
63
|
+
var COMPATIBILITY_MAX_LENGTH = 500;
|
|
64
|
+
var RESERVED_WORDS = ["anthropic", "claude"];
|
|
65
|
+
var XML_TAG_PATTERN = /<\/?[a-zA-Z][^>]*>/;
|
|
66
|
+
function validateFrontmatter(fm, filePath) {
|
|
67
|
+
if (!fm.name || typeof fm.name !== "string") {
|
|
68
|
+
throw new SkillManifestError(filePath, "name", "name is required");
|
|
69
|
+
}
|
|
70
|
+
if (fm.name.length > NAME_MAX_LENGTH) {
|
|
71
|
+
throw new SkillManifestError(
|
|
72
|
+
filePath,
|
|
73
|
+
"name",
|
|
74
|
+
`name must be at most ${NAME_MAX_LENGTH} characters (got ${fm.name.length})`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (!NAME_PATTERN.test(fm.name)) {
|
|
78
|
+
throw new SkillManifestError(
|
|
79
|
+
filePath,
|
|
80
|
+
"name",
|
|
81
|
+
"name must contain only lowercase letters, numbers, and hyphens"
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (fm.name.startsWith("-") || fm.name.endsWith("-")) {
|
|
85
|
+
throw new SkillManifestError(
|
|
86
|
+
filePath,
|
|
87
|
+
"name",
|
|
88
|
+
"name must not start or end with a hyphen"
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (fm.name.includes("--")) {
|
|
92
|
+
throw new SkillManifestError(
|
|
93
|
+
filePath,
|
|
94
|
+
"name",
|
|
95
|
+
"name must not contain consecutive hyphens"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (XML_TAG_PATTERN.test(fm.name)) {
|
|
99
|
+
throw new SkillManifestError(filePath, "name", "name cannot contain XML tags");
|
|
100
|
+
}
|
|
101
|
+
for (const reserved of RESERVED_WORDS) {
|
|
102
|
+
if (fm.name.includes(reserved)) {
|
|
103
|
+
throw new SkillManifestError(
|
|
104
|
+
filePath,
|
|
105
|
+
"name",
|
|
106
|
+
`name cannot contain reserved word "${reserved}"`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (!fm.description || typeof fm.description !== "string") {
|
|
111
|
+
throw new SkillManifestError(
|
|
112
|
+
filePath,
|
|
113
|
+
"description",
|
|
114
|
+
"description is required and must be non-empty"
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (fm.description.length > DESCRIPTION_MAX_LENGTH) {
|
|
118
|
+
throw new SkillManifestError(
|
|
119
|
+
filePath,
|
|
120
|
+
"description",
|
|
121
|
+
`description must be at most ${DESCRIPTION_MAX_LENGTH} characters (got ${fm.description.length})`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (XML_TAG_PATTERN.test(fm.description)) {
|
|
125
|
+
throw new SkillManifestError(
|
|
126
|
+
filePath,
|
|
127
|
+
"description",
|
|
128
|
+
"description cannot contain XML tags"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (fm.compatibility != null && typeof fm.compatibility === "string") {
|
|
132
|
+
if (fm.compatibility.length > COMPATIBILITY_MAX_LENGTH) {
|
|
133
|
+
throw new SkillManifestError(
|
|
134
|
+
filePath,
|
|
135
|
+
"compatibility",
|
|
136
|
+
`compatibility must be at most ${COMPATIBILITY_MAX_LENGTH} characters (got ${fm.compatibility.length})`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/tools/skill/SkillMdParser.ts
|
|
143
|
+
var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
144
|
+
".py",
|
|
145
|
+
".js",
|
|
146
|
+
".mjs",
|
|
147
|
+
".ts",
|
|
148
|
+
".sh",
|
|
149
|
+
".bash",
|
|
150
|
+
".rb",
|
|
151
|
+
".go"
|
|
152
|
+
]);
|
|
153
|
+
var INSTRUCTION_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt"]);
|
|
154
|
+
var EXCLUDED_FILES = /* @__PURE__ */ new Set(["SKILL.md", "tool.json"]);
|
|
155
|
+
function parseSkillMd(content, filePath) {
|
|
156
|
+
let raw;
|
|
157
|
+
let body = "";
|
|
158
|
+
try {
|
|
159
|
+
const parsed = utils.parseMarkdownYamlFrontmatter(content, filePath);
|
|
160
|
+
raw = parsed.frontmatter;
|
|
161
|
+
body = parsed.body;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
164
|
+
throw new SkillManifestError(
|
|
165
|
+
filePath,
|
|
166
|
+
"frontmatter",
|
|
167
|
+
`Invalid YAML frontmatter: ${message}`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const name = stringField(raw, "name", filePath);
|
|
171
|
+
const description = stringField(raw, "description", filePath);
|
|
172
|
+
if (!name || !description) {
|
|
173
|
+
throw new SkillManifestError(
|
|
174
|
+
filePath,
|
|
175
|
+
"frontmatter",
|
|
176
|
+
!name ? "name is required" : "description is required"
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
const license = stringField(raw, "license");
|
|
180
|
+
const compatibility = stringField(raw, "compatibility");
|
|
181
|
+
const allowedTools = stringField(raw, "allowed-tools");
|
|
182
|
+
const metadata = normalizeMetadata(raw.metadata);
|
|
183
|
+
const frontmatter = {
|
|
184
|
+
name,
|
|
185
|
+
description,
|
|
186
|
+
...license && { license },
|
|
187
|
+
...compatibility && { compatibility },
|
|
188
|
+
...allowedTools && { allowedTools },
|
|
189
|
+
...metadata && Object.keys(metadata).length > 0 && { metadata }
|
|
190
|
+
};
|
|
191
|
+
validateFrontmatter(frontmatter, filePath);
|
|
192
|
+
return { frontmatter, instructions: body };
|
|
193
|
+
}
|
|
194
|
+
function stringField(raw, key, filePath) {
|
|
195
|
+
const v = raw[key];
|
|
196
|
+
if (v == null) return "";
|
|
197
|
+
if (typeof v === "string") return v;
|
|
198
|
+
if (typeof v === "number" || typeof v === "boolean") return String(v);
|
|
199
|
+
if (Array.isArray(v)) {
|
|
200
|
+
return v.map((x) => typeof x === "string" ? x : String(x)).join("\n");
|
|
201
|
+
}
|
|
202
|
+
if (filePath) {
|
|
203
|
+
throw new SkillManifestError(
|
|
204
|
+
filePath,
|
|
205
|
+
"frontmatter",
|
|
206
|
+
`Frontmatter field "${key}" must be a string, number, boolean, or array`
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
return String(v);
|
|
210
|
+
}
|
|
211
|
+
function normalizeMetadata(val) {
|
|
212
|
+
if (val == null) return void 0;
|
|
213
|
+
if (typeof val === "object" && !Array.isArray(val)) {
|
|
214
|
+
const out = {};
|
|
215
|
+
for (const [k, v] of Object.entries(val)) {
|
|
216
|
+
if (typeof k === "string" && v !== void 0 && v !== null) {
|
|
217
|
+
out[k] = typeof v === "object" ? JSON.stringify(v) : String(v);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return Object.keys(out).length ? out : void 0;
|
|
221
|
+
}
|
|
222
|
+
if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
|
|
223
|
+
return { value: String(val) };
|
|
224
|
+
}
|
|
225
|
+
return void 0;
|
|
226
|
+
}
|
|
227
|
+
async function scanSkillResources(dirPath) {
|
|
228
|
+
const resources = [];
|
|
229
|
+
await scanDir(dirPath, dirPath, resources);
|
|
230
|
+
return resources;
|
|
231
|
+
}
|
|
232
|
+
async function scanDir(basePath, currentPath, resources) {
|
|
233
|
+
let entries;
|
|
234
|
+
try {
|
|
235
|
+
entries = await promises.readdir(currentPath, { withFileTypes: true });
|
|
236
|
+
} catch {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
for (const entry of entries) {
|
|
240
|
+
const fullPath = path.join(currentPath, entry.name);
|
|
241
|
+
if (entry.isDirectory()) {
|
|
242
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules") {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
await scanDir(basePath, fullPath, resources);
|
|
246
|
+
} else if (entry.isFile()) {
|
|
247
|
+
if (EXCLUDED_FILES.has(entry.name)) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
251
|
+
const relPath = path.relative(basePath, fullPath);
|
|
252
|
+
resources.push({
|
|
253
|
+
relativePath: relPath,
|
|
254
|
+
absolutePath: fullPath,
|
|
255
|
+
extension: ext,
|
|
256
|
+
type: inferResourceType(ext)
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function inferResourceType(ext) {
|
|
262
|
+
if (CODE_EXTENSIONS.has(ext)) return "code";
|
|
263
|
+
if (INSTRUCTION_EXTENSIONS.has(ext)) return "instructions";
|
|
264
|
+
return "data";
|
|
265
|
+
}
|
|
266
|
+
async function loadSkillDefinition(dirPath) {
|
|
267
|
+
const skillMdPath = path.join(dirPath, "SKILL.md");
|
|
268
|
+
let content;
|
|
269
|
+
try {
|
|
270
|
+
content = await promises.readFile(skillMdPath, "utf-8");
|
|
271
|
+
} catch (err) {
|
|
272
|
+
throw new SkillManifestError(
|
|
273
|
+
skillMdPath,
|
|
274
|
+
"file",
|
|
275
|
+
`Cannot read SKILL.md: ${err.message}`
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
const { frontmatter, instructions } = parseSkillMd(content, skillMdPath);
|
|
279
|
+
const resources = await scanSkillResources(dirPath);
|
|
280
|
+
return {
|
|
281
|
+
frontmatter,
|
|
282
|
+
instructions,
|
|
283
|
+
resources,
|
|
284
|
+
dirPath,
|
|
285
|
+
skillMdPath
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/tools/skill/scanSkill.ts
|
|
290
|
+
var defaultInputSchema = { type: "object", properties: {}, additionalProperties: true };
|
|
291
|
+
async function scanForSkill(projectPath) {
|
|
292
|
+
const projectRoot = path__namespace.resolve(projectPath);
|
|
293
|
+
const dirs = await chunkJW4EMVTE_cjs.findDirsContainingFile(projectRoot, "SKILL.md");
|
|
294
|
+
const skills = [];
|
|
295
|
+
const errors = [];
|
|
296
|
+
for (const dirPath of dirs) {
|
|
297
|
+
const relativePath = path__namespace.relative(projectRoot, dirPath) || path__namespace.basename(dirPath);
|
|
298
|
+
try {
|
|
299
|
+
const skillDef = await loadSkillDefinition(dirPath);
|
|
300
|
+
const name = chunkJW4EMVTE_cjs.pathToToolName(relativePath, skillDef.frontmatter.name);
|
|
301
|
+
skills.push({
|
|
302
|
+
kind: chunkJW4EMVTE_cjs.SKILL_KIND,
|
|
303
|
+
name,
|
|
304
|
+
description: skillDef.frontmatter.description,
|
|
305
|
+
inputSchema: defaultInputSchema,
|
|
306
|
+
_meta: { hitl: { sideEffect: "none" } },
|
|
307
|
+
sourcePath: relativePath.replace(/\\/g, "/")
|
|
308
|
+
});
|
|
309
|
+
} catch (err) {
|
|
310
|
+
errors.push({ dir: relativePath, message: err instanceof Error ? err.message : String(err) });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return { skills, errors };
|
|
314
|
+
}
|
|
315
|
+
async function scan2(projectPath, _options = {}) {
|
|
316
|
+
const root = path__namespace.resolve(projectPath);
|
|
317
|
+
const result = await scanForSkill(root);
|
|
318
|
+
const specs = result.skills.map((s) => chunkJW4EMVTE_cjs.mcpSpecToToolSpec(s, root));
|
|
319
|
+
return {
|
|
320
|
+
specs,
|
|
321
|
+
errors: result.errors.map((e) => ({ file: e.dir, message: e.message }))
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
async function readWorkflowMeta(dirPath, workflowFileName = "workflow.json") {
|
|
325
|
+
const workflowPath = path.join(dirPath, workflowFileName);
|
|
326
|
+
let raw;
|
|
327
|
+
try {
|
|
328
|
+
raw = await promises.readFile(workflowPath, "utf-8");
|
|
329
|
+
} catch (err) {
|
|
330
|
+
throw new DiscoveryError(
|
|
331
|
+
dirPath,
|
|
332
|
+
"load",
|
|
333
|
+
`Failed to read workflow: ${workflowPath}`,
|
|
334
|
+
err
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
let workflowDef;
|
|
338
|
+
try {
|
|
339
|
+
workflowDef = JSON.parse(raw);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
throw new DiscoveryError(
|
|
342
|
+
dirPath,
|
|
343
|
+
"load",
|
|
344
|
+
`Invalid JSON in ${workflowPath}`,
|
|
345
|
+
err
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
if (!workflowDef.nodes || !Array.isArray(workflowDef.nodes)) {
|
|
349
|
+
throw new DiscoveryError(
|
|
350
|
+
dirPath,
|
|
351
|
+
"validate",
|
|
352
|
+
`workflow.json must have a "nodes" array`
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
const meta = workflowDef.meta;
|
|
356
|
+
const name = workflowDef.name || meta?.name || path.basename(dirPath);
|
|
357
|
+
const description = workflowDef.description || meta?.description || `n8n workflow: ${name}`;
|
|
358
|
+
let webhookUrl;
|
|
359
|
+
const nodes = workflowDef.nodes;
|
|
360
|
+
if (Array.isArray(nodes)) {
|
|
361
|
+
const webhookNode = nodes.find(
|
|
362
|
+
(n) => n.type === "n8n-nodes-base.webhook" || n.type?.includes("webhook")
|
|
363
|
+
);
|
|
364
|
+
if (webhookNode?.parameters && typeof webhookNode.parameters === "object") {
|
|
365
|
+
const params = webhookNode.parameters;
|
|
366
|
+
const pathVal = params.path ?? params.webhookPath;
|
|
367
|
+
if (typeof pathVal === "string" && pathVal.startsWith("http")) {
|
|
368
|
+
webhookUrl = pathVal;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return { name, description, webhookUrl, workflowDef };
|
|
373
|
+
}
|
|
374
|
+
async function loadN8nTool(dirPath, manifest) {
|
|
375
|
+
const { workflowDef } = await readWorkflowMeta(
|
|
376
|
+
dirPath,
|
|
377
|
+
manifest.entryPoint ?? "workflow.json"
|
|
378
|
+
);
|
|
379
|
+
return { manifest, dirPath, workflowDef };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/tools/n8n/scanN8n.ts
|
|
383
|
+
var defaultInputSchema2 = { type: "object", properties: {}, additionalProperties: true };
|
|
384
|
+
async function scanForN8n(projectPath) {
|
|
385
|
+
const projectRoot = path__namespace.resolve(projectPath);
|
|
386
|
+
const dirs = await chunkJW4EMVTE_cjs.findDirsContainingFile(projectRoot, "workflow.json");
|
|
387
|
+
const n8n = [];
|
|
388
|
+
const errors = [];
|
|
389
|
+
for (const dirPath of dirs) {
|
|
390
|
+
const relativePath = path__namespace.relative(projectRoot, dirPath) || path__namespace.basename(dirPath);
|
|
391
|
+
try {
|
|
392
|
+
const { name: wfName, description: wfDesc, webhookUrl } = await readWorkflowMeta(dirPath);
|
|
393
|
+
const toolName = chunkJW4EMVTE_cjs.pathToToolName(relativePath, wfName);
|
|
394
|
+
n8n.push({
|
|
395
|
+
kind: chunkJW4EMVTE_cjs.N8N_KIND,
|
|
396
|
+
name: toolName,
|
|
397
|
+
description: wfDesc,
|
|
398
|
+
inputSchema: defaultInputSchema2,
|
|
399
|
+
_meta: { hitl: { sideEffect: "external_write" } },
|
|
400
|
+
sourcePath: relativePath.replace(/\\/g, "/"),
|
|
401
|
+
webhookUrl
|
|
402
|
+
});
|
|
403
|
+
} catch (err) {
|
|
404
|
+
errors.push({ dir: relativePath, message: err instanceof Error ? err.message : String(err) });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return { n8n, errors };
|
|
408
|
+
}
|
|
409
|
+
async function scan3(projectPath, _options = {}) {
|
|
410
|
+
const root = path__namespace.resolve(projectPath);
|
|
411
|
+
const result = await scanForN8n(root);
|
|
412
|
+
const specs = result.n8n.map((s) => chunkJW4EMVTE_cjs.mcpSpecToToolSpec(s, root));
|
|
413
|
+
return {
|
|
414
|
+
specs,
|
|
415
|
+
errors: result.errors.map((e) => ({ file: e.dir, message: e.message }))
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
async function scan4(projectPath, options = {}) {
|
|
419
|
+
const root = path__namespace.resolve(projectPath);
|
|
420
|
+
const namespace = options.namespace ?? "dir";
|
|
421
|
+
const errors = [];
|
|
422
|
+
const scanner = new DirectoryScanner({
|
|
423
|
+
roots: [root],
|
|
424
|
+
namespace,
|
|
425
|
+
extensions: options.extensions,
|
|
426
|
+
onError: (dir, err) => {
|
|
427
|
+
errors.push({ file: dir, message: err.message });
|
|
428
|
+
options.onError?.(dir, err);
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
let specs;
|
|
432
|
+
try {
|
|
433
|
+
specs = await scanner.scan();
|
|
434
|
+
} catch (err) {
|
|
435
|
+
errors.push({
|
|
436
|
+
file: root,
|
|
437
|
+
message: err instanceof Error ? err.message : String(err)
|
|
438
|
+
});
|
|
439
|
+
return { specs: [], errors };
|
|
440
|
+
}
|
|
441
|
+
const filtered = specs.filter((s) => s.kind === MCP_KIND);
|
|
442
|
+
return { specs: filtered, errors };
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// src/tools/langchain/types.ts
|
|
446
|
+
var LANGCHAIN_KIND = "langchain";
|
|
447
|
+
var LANGCHAIN_DIR_NAME = "langchain";
|
|
448
|
+
|
|
449
|
+
// src/tools/langchain/scanner.ts
|
|
450
|
+
async function scan5(projectPath, options = {}) {
|
|
451
|
+
const root = path__namespace.resolve(projectPath);
|
|
452
|
+
const namespace = options.namespace ?? "dir";
|
|
453
|
+
const errors = [];
|
|
454
|
+
const scanner = new DirectoryScanner({
|
|
455
|
+
roots: [root],
|
|
456
|
+
namespace,
|
|
457
|
+
extensions: options.extensions,
|
|
458
|
+
onError: (dir, err) => {
|
|
459
|
+
errors.push({ file: dir, message: err.message });
|
|
460
|
+
options.onError?.(dir, err);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
let specs;
|
|
464
|
+
try {
|
|
465
|
+
specs = await scanner.scan();
|
|
466
|
+
} catch (err) {
|
|
467
|
+
errors.push({
|
|
468
|
+
file: root,
|
|
469
|
+
message: err instanceof Error ? err.message : String(err)
|
|
470
|
+
});
|
|
471
|
+
return { specs: [], errors };
|
|
472
|
+
}
|
|
473
|
+
const filtered = specs.filter((s) => s.kind === LANGCHAIN_KIND);
|
|
474
|
+
return { specs: filtered, errors };
|
|
475
|
+
}
|
|
476
|
+
async function loadLangChainTool(dirPath, manifest, extensions) {
|
|
477
|
+
let entryFile;
|
|
478
|
+
try {
|
|
479
|
+
entryFile = await resolveEntryPoint(
|
|
480
|
+
dirPath,
|
|
481
|
+
manifest.entryPoint ?? "index",
|
|
482
|
+
extensions
|
|
483
|
+
);
|
|
484
|
+
} catch (err) {
|
|
485
|
+
throw new DiscoveryError(
|
|
486
|
+
dirPath,
|
|
487
|
+
"load",
|
|
488
|
+
`Cannot find LangChain entry point`,
|
|
489
|
+
err
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
let mod;
|
|
493
|
+
try {
|
|
494
|
+
mod = await import(url.pathToFileURL(entryFile).href);
|
|
495
|
+
} catch (err) {
|
|
496
|
+
throw new DiscoveryError(
|
|
497
|
+
dirPath,
|
|
498
|
+
"load",
|
|
499
|
+
`Failed to import ${entryFile}`,
|
|
500
|
+
err
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
const tool = mod.default ?? mod.tool ?? mod;
|
|
504
|
+
if (!tool || typeof tool.invoke !== "function") {
|
|
505
|
+
throw new DiscoveryError(
|
|
506
|
+
dirPath,
|
|
507
|
+
"validate",
|
|
508
|
+
`Entry point must export an object with invoke() method (LangChainToolLike)`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
return { manifest, dirPath, impl: tool };
|
|
512
|
+
}
|
|
513
|
+
var DEFAULT_EXTENSIONS2 = [".js", ".mjs"];
|
|
514
|
+
async function listSkillProgramFiles(dirPath, extensions = DEFAULT_EXTENSIONS2) {
|
|
515
|
+
let entries;
|
|
516
|
+
try {
|
|
517
|
+
const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
|
|
518
|
+
entries = dirEntries.map((entry) => ({
|
|
519
|
+
name: entry.name,
|
|
520
|
+
isFile: entry.isFile()
|
|
521
|
+
}));
|
|
522
|
+
} catch {
|
|
523
|
+
return [];
|
|
524
|
+
}
|
|
525
|
+
return entries.filter((e) => e.isFile).map((e) => e.name).filter((name) => {
|
|
526
|
+
if (name.startsWith(".") || name.startsWith("_")) return false;
|
|
527
|
+
if (name.includes(".test.") || name.includes(".spec.")) return false;
|
|
528
|
+
return extensions.some((ext) => name.endsWith(ext));
|
|
529
|
+
}).sort((a, b) => {
|
|
530
|
+
if (a === "handler.js" || a === "index.js") return -1;
|
|
531
|
+
if (b === "handler.js" || b === "index.js") return 1;
|
|
532
|
+
return a.localeCompare(b);
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
function isLangChainLikeTool(val) {
|
|
536
|
+
return val != null && typeof val === "object" && "invoke" in val && typeof val.invoke === "function";
|
|
537
|
+
}
|
|
538
|
+
function isConstructable(val) {
|
|
539
|
+
return typeof val === "function" && typeof val.prototype === "object";
|
|
540
|
+
}
|
|
541
|
+
async function loadOneSkillProgram(dirPath, manifest, entryFile, skillDef, programKey, extensions) {
|
|
542
|
+
let impl;
|
|
543
|
+
try {
|
|
544
|
+
const fullPath = await resolveEntryPoint(dirPath, entryFile, extensions ?? [".js", ".mjs"]);
|
|
545
|
+
const mod = await import(url.pathToFileURL(fullPath).href);
|
|
546
|
+
const fn = mod.default ?? mod.handler ?? mod.Tool;
|
|
547
|
+
if (isLangChainLikeTool(fn)) {
|
|
548
|
+
impl = fn;
|
|
549
|
+
} else if (isConstructable(fn)) {
|
|
550
|
+
const instance = new fn();
|
|
551
|
+
if (isLangChainLikeTool(instance)) impl = instance;
|
|
552
|
+
} else if (typeof fn === "function") {
|
|
553
|
+
impl = fn;
|
|
554
|
+
}
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
manifest,
|
|
559
|
+
dirPath,
|
|
560
|
+
impl,
|
|
561
|
+
skillDefinition: skillDef,
|
|
562
|
+
programKey
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
async function loadSkillTools(dirPath, manifest, extensions) {
|
|
566
|
+
let skillDef;
|
|
567
|
+
try {
|
|
568
|
+
skillDef = await loadSkillDefinition(dirPath);
|
|
569
|
+
} catch (err) {
|
|
570
|
+
throw new DiscoveryError(
|
|
571
|
+
dirPath,
|
|
572
|
+
"load",
|
|
573
|
+
`Failed to parse SKILL.md: ${err.message}`,
|
|
574
|
+
err
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const programs = manifest.programs;
|
|
578
|
+
if (programs && typeof programs === "object" && Object.keys(programs).length > 0) {
|
|
579
|
+
const result = [];
|
|
580
|
+
for (const [programKey, entryFile2] of Object.entries(programs)) {
|
|
581
|
+
const loaded2 = await loadOneSkillProgram(
|
|
582
|
+
dirPath,
|
|
583
|
+
manifest,
|
|
584
|
+
entryFile2,
|
|
585
|
+
skillDef,
|
|
586
|
+
programKey,
|
|
587
|
+
extensions
|
|
588
|
+
);
|
|
589
|
+
result.push(loaded2);
|
|
590
|
+
}
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
const exts = extensions ?? DEFAULT_EXTENSIONS2;
|
|
594
|
+
const files = await listSkillProgramFiles(dirPath, exts);
|
|
595
|
+
if (files.length >= 2) {
|
|
596
|
+
const result = [];
|
|
597
|
+
for (let i = 0; i < files.length; i++) {
|
|
598
|
+
const file = files[i];
|
|
599
|
+
const programKey = i === 0 ? "default" : file.replace(/\.[^.]+$/, "");
|
|
600
|
+
const loaded2 = await loadOneSkillProgram(
|
|
601
|
+
dirPath,
|
|
602
|
+
manifest,
|
|
603
|
+
file,
|
|
604
|
+
skillDef,
|
|
605
|
+
programKey,
|
|
606
|
+
extensions
|
|
607
|
+
);
|
|
608
|
+
result.push(loaded2);
|
|
609
|
+
}
|
|
610
|
+
return result;
|
|
611
|
+
}
|
|
612
|
+
const entryFile = manifest.entryPoint ?? files[0] ?? "handler";
|
|
613
|
+
const loaded = await loadOneSkillProgram(
|
|
614
|
+
dirPath,
|
|
615
|
+
manifest,
|
|
616
|
+
entryFile,
|
|
617
|
+
skillDef,
|
|
618
|
+
void 0,
|
|
619
|
+
extensions
|
|
620
|
+
);
|
|
621
|
+
return [loaded];
|
|
622
|
+
}
|
|
623
|
+
async function listLangchainEntryFiles(dirPath, extensions) {
|
|
624
|
+
let entries;
|
|
625
|
+
try {
|
|
626
|
+
const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
|
|
627
|
+
entries = dirEntries.map((entry) => ({
|
|
628
|
+
name: entry.name,
|
|
629
|
+
isFile: entry.isFile()
|
|
630
|
+
}));
|
|
631
|
+
} catch {
|
|
632
|
+
return [];
|
|
633
|
+
}
|
|
634
|
+
return entries.filter((e) => e.isFile).map((e) => e.name).filter((name) => {
|
|
635
|
+
if (name.startsWith(".") || name.startsWith("_")) return false;
|
|
636
|
+
if (name.endsWith(".d.ts")) return false;
|
|
637
|
+
if (name.includes(".test.") || name.includes(".spec.")) return false;
|
|
638
|
+
return extensions.some((ext) => name.endsWith(ext));
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
async function loadLangChainToolsFromDir(dirPath, dirName, manifest, strict, namespace, extensions, langchainDirName, toSpec, onError) {
|
|
642
|
+
const entryFiles = await listLangchainEntryFiles(dirPath, extensions);
|
|
643
|
+
if (entryFiles.length === 0) {
|
|
644
|
+
if (strict) {
|
|
645
|
+
throw new DiscoveryError(dirPath, "load", "No LangChain entry files found");
|
|
646
|
+
}
|
|
647
|
+
return [];
|
|
648
|
+
}
|
|
649
|
+
const specs = [];
|
|
650
|
+
const useDirNameForSingle = dirName !== langchainDirName;
|
|
651
|
+
for (const entryFile of entryFiles) {
|
|
652
|
+
const fileManifest = { ...manifest, entryPoint: entryFile };
|
|
653
|
+
try {
|
|
654
|
+
const loaded = await loadLangChainTool(dirPath, fileManifest, extensions);
|
|
655
|
+
const fileBase = path.basename(entryFile).replace(/\.[^.]+$/, "");
|
|
656
|
+
const nameHint = entryFiles.length === 1 && useDirNameForSingle ? dirName : fileBase;
|
|
657
|
+
specs.push(toSpec(loaded, nameHint, dirPath, namespace));
|
|
658
|
+
} catch (error) {
|
|
659
|
+
const err = error;
|
|
660
|
+
if (err instanceof DiscoveryError && err.phase === "validate") {
|
|
661
|
+
if (strict) throw err;
|
|
662
|
+
continue;
|
|
663
|
+
}
|
|
664
|
+
onError?.(path.join(dirPath, entryFile), err);
|
|
665
|
+
if (strict) throw err;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return specs;
|
|
669
|
+
}
|
|
670
|
+
function isCursorFormat(obj) {
|
|
671
|
+
return typeof obj === "object" && obj !== null && "mcpServers" in obj && typeof obj.mcpServers === "object" && obj.mcpServers !== null;
|
|
672
|
+
}
|
|
673
|
+
function extractMCPConfig(parsed, toolName) {
|
|
674
|
+
if (isCursorFormat(parsed)) {
|
|
675
|
+
const servers = parsed.mcpServers;
|
|
676
|
+
const keys = Object.keys(servers);
|
|
677
|
+
if (keys.length === 0) {
|
|
678
|
+
return {};
|
|
679
|
+
}
|
|
680
|
+
const name = toolName && keys.includes(toolName) ? toolName : keys[0];
|
|
681
|
+
return servers[name];
|
|
682
|
+
}
|
|
683
|
+
return parsed;
|
|
684
|
+
}
|
|
685
|
+
async function loadMCPTool(dirPath, manifest) {
|
|
686
|
+
const mcpPath = path.join(dirPath, manifest.entryPoint ?? "mcp.json");
|
|
687
|
+
let raw;
|
|
688
|
+
try {
|
|
689
|
+
raw = await promises.readFile(mcpPath, "utf-8");
|
|
690
|
+
} catch (err) {
|
|
691
|
+
throw new DiscoveryError(
|
|
692
|
+
dirPath,
|
|
693
|
+
"load",
|
|
694
|
+
`Failed to read MCP config: ${mcpPath}`,
|
|
695
|
+
err
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
let parsed;
|
|
699
|
+
try {
|
|
700
|
+
parsed = JSON.parse(raw);
|
|
701
|
+
} catch (err) {
|
|
702
|
+
throw new DiscoveryError(
|
|
703
|
+
dirPath,
|
|
704
|
+
"load",
|
|
705
|
+
`Invalid JSON in ${mcpPath}`,
|
|
706
|
+
err
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
const baseName = manifest.name?.split("/").pop();
|
|
710
|
+
const config = extractMCPConfig(parsed, baseName);
|
|
711
|
+
if (!config.command && !config.url) {
|
|
712
|
+
throw new DiscoveryError(
|
|
713
|
+
dirPath,
|
|
714
|
+
"validate",
|
|
715
|
+
`mcp.json must have either "command" or "url" field`
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
return { manifest, dirPath, mcpConfig: config };
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// src/tools/mcp/directoryApply.ts
|
|
722
|
+
function applyLoadedToSpec(spec, loaded, _manifest, _defaultDirName, _namespace) {
|
|
723
|
+
if (loaded.mcpConfig?.url) spec.endpoint = loaded.mcpConfig.url;
|
|
724
|
+
spec.impl = loaded.mcpConfig;
|
|
725
|
+
}
|
|
726
|
+
var directoryMarker = {
|
|
727
|
+
kind: "mcp",
|
|
728
|
+
markerFile: "mcp.json",
|
|
729
|
+
defaultEntryPoint: "mcp.json"
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
// src/tools/langchain/directoryApply.ts
|
|
733
|
+
function applyLoadedToSpec2(spec, loaded, manifest, _defaultDirName, namespace) {
|
|
734
|
+
spec.impl = loaded.impl;
|
|
735
|
+
if (!manifest.name && loaded.impl) {
|
|
736
|
+
const toolName = loaded.impl.name;
|
|
737
|
+
if (toolName) spec.name = `${namespace}/${toolName}`;
|
|
738
|
+
}
|
|
739
|
+
if (!manifest.description && loaded.impl) {
|
|
740
|
+
const d = loaded.impl.description;
|
|
741
|
+
if (d) spec.description = d;
|
|
742
|
+
}
|
|
743
|
+
if (!manifest.inputSchema && loaded.impl) {
|
|
744
|
+
const schema = loaded.impl.schema;
|
|
745
|
+
if (schema) spec.inputSchema = schema;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/tools/skill/directoryApply.ts
|
|
750
|
+
function applyLoadedToSpec3(spec, loaded, manifest, defaultDirName, namespace) {
|
|
751
|
+
const skillDef = loaded.skillDefinition;
|
|
752
|
+
if (skillDef) {
|
|
753
|
+
spec.name = manifest.name ?? skillDef.frontmatter.name;
|
|
754
|
+
spec.description = skillDef.frontmatter.description;
|
|
755
|
+
if (loaded.programKey === "default") {
|
|
756
|
+
spec.name = `${namespace}/${defaultDirName}`;
|
|
757
|
+
} else if (loaded.programKey) {
|
|
758
|
+
spec.name = `${namespace}/${defaultDirName}/${loaded.programKey}`;
|
|
759
|
+
}
|
|
760
|
+
const impl = loaded.impl;
|
|
761
|
+
if (impl && typeof impl === "object" && typeof impl.invoke === "function") {
|
|
762
|
+
if (impl.description != null && impl.description !== "")
|
|
763
|
+
spec.description = impl.description;
|
|
764
|
+
if (impl.schema != null && typeof impl.schema === "object")
|
|
765
|
+
spec.inputSchema = impl.schema;
|
|
766
|
+
}
|
|
767
|
+
spec.impl = { ...skillDef, handler: loaded.impl };
|
|
768
|
+
} else {
|
|
769
|
+
spec.impl = loaded.impl;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
var directoryMarker2 = {
|
|
773
|
+
kind: "skill",
|
|
774
|
+
markerFile: "SKILL.md",
|
|
775
|
+
defaultEntryPoint: "handler"
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
// src/tools/n8n/directoryApply.ts
|
|
779
|
+
function applyLoadedToSpec4(spec, loaded, manifest, _defaultDirName, _namespace) {
|
|
780
|
+
const workflow = loaded.workflowDef;
|
|
781
|
+
if (workflow?.id) spec.resourceId = String(workflow.id);
|
|
782
|
+
if (!manifest.description && workflow) {
|
|
783
|
+
const d = workflow.description ?? workflow.meta?.description ?? (typeof workflow.name === "string" ? workflow.name : void 0);
|
|
784
|
+
if (d) spec.description = d;
|
|
785
|
+
}
|
|
786
|
+
spec.impl = loaded.workflowDef;
|
|
787
|
+
}
|
|
788
|
+
var directoryMarker3 = {
|
|
789
|
+
kind: "n8n",
|
|
790
|
+
markerFile: "workflow.json",
|
|
791
|
+
defaultEntryPoint: "workflow.json"
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
// src/tools/discoveryFactory.ts
|
|
795
|
+
var DiscoveryError = class extends Error {
|
|
796
|
+
toolDir;
|
|
797
|
+
phase;
|
|
798
|
+
cause;
|
|
799
|
+
constructor(toolDir, phase, message, cause) {
|
|
800
|
+
super(`[${phase}] ${toolDir}: ${message}`);
|
|
801
|
+
this.name = "DiscoveryError";
|
|
802
|
+
this.toolDir = toolDir;
|
|
803
|
+
this.phase = phase;
|
|
804
|
+
this.cause = cause;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var DIRECTORY_KINDS = ["mcp", "langchain", "skill", "n8n"];
|
|
808
|
+
var DIRECTORY_DISCOVERABLE_KINDS = DIRECTORY_KINDS;
|
|
809
|
+
var DIRECTORY_KIND_MARKERS = [
|
|
810
|
+
directoryMarker2,
|
|
811
|
+
directoryMarker3,
|
|
812
|
+
directoryMarker
|
|
813
|
+
];
|
|
814
|
+
var DIRECTORY_LOADERS = {
|
|
815
|
+
mcp: async (dirPath, manifest) => [await loadMCPTool(dirPath, manifest)],
|
|
816
|
+
langchain: async (dirPath, manifest, ext) => [await loadLangChainTool(dirPath, manifest, ext)],
|
|
817
|
+
skill: (dirPath, manifest, ext) => loadSkillTools(dirPath, manifest, ext),
|
|
818
|
+
n8n: async (dirPath, manifest) => [await loadN8nTool(dirPath, manifest)]
|
|
819
|
+
};
|
|
820
|
+
function getDirectoryLoader(kind) {
|
|
821
|
+
const loader = DIRECTORY_LOADERS[kind];
|
|
822
|
+
if (!loader) {
|
|
823
|
+
throw new DiscoveryError("", "manifest", `Unknown directory tool kind: "${kind}"`);
|
|
824
|
+
}
|
|
825
|
+
return loader;
|
|
826
|
+
}
|
|
827
|
+
function applyDirectoryLoadedToSpec(spec, loaded, manifest, defaultDirName, namespace) {
|
|
828
|
+
switch (manifest.kind) {
|
|
829
|
+
case "mcp":
|
|
830
|
+
return applyLoadedToSpec(spec, loaded);
|
|
831
|
+
case "langchain":
|
|
832
|
+
return applyLoadedToSpec2(spec, loaded, manifest, defaultDirName, namespace);
|
|
833
|
+
case "skill":
|
|
834
|
+
return applyLoadedToSpec3(spec, loaded, manifest, defaultDirName, namespace);
|
|
835
|
+
case "n8n":
|
|
836
|
+
return applyLoadedToSpec4(spec, loaded, manifest);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
async function discoverTools(type, projectPath, options = {}) {
|
|
840
|
+
const root = path__namespace.resolve(projectPath);
|
|
841
|
+
switch (type) {
|
|
842
|
+
case "function":
|
|
843
|
+
return chunkJW4EMVTE_cjs.scan(root, options);
|
|
844
|
+
case "skill":
|
|
845
|
+
return scan2(root, options);
|
|
846
|
+
case "n8n":
|
|
847
|
+
return scan3(root, options);
|
|
848
|
+
case "mcp":
|
|
849
|
+
return scan4(root, options);
|
|
850
|
+
case "langchain":
|
|
851
|
+
return scan5(root, options);
|
|
852
|
+
default: {
|
|
853
|
+
const _ = type;
|
|
854
|
+
return _;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
var DEFAULT_EXTENSIONS3 = [".js", ".mjs"];
|
|
859
|
+
var DirectoryScanner = class {
|
|
860
|
+
roots;
|
|
861
|
+
extensions;
|
|
862
|
+
onError;
|
|
863
|
+
constructor(options) {
|
|
864
|
+
const defaultNamespace = options.namespace ?? "dir";
|
|
865
|
+
this.roots = options.roots.map((root) => {
|
|
866
|
+
if (typeof root === "string") {
|
|
867
|
+
return { path: root, namespace: defaultNamespace };
|
|
868
|
+
}
|
|
869
|
+
return {
|
|
870
|
+
path: root.path,
|
|
871
|
+
namespace: root.namespace ?? defaultNamespace
|
|
872
|
+
};
|
|
873
|
+
});
|
|
874
|
+
this.extensions = options.extensions ?? DEFAULT_EXTENSIONS3;
|
|
875
|
+
this.onError = options.onError;
|
|
876
|
+
}
|
|
877
|
+
async scan() {
|
|
878
|
+
const specs = [];
|
|
879
|
+
for (const root of this.roots) {
|
|
880
|
+
const rootSpecs = await this.scanRoot(root.path, root.namespace);
|
|
881
|
+
specs.push(...rootSpecs);
|
|
882
|
+
}
|
|
883
|
+
return specs;
|
|
884
|
+
}
|
|
885
|
+
async scanRoot(rootPath, namespace) {
|
|
886
|
+
return this.scanRecursive(rootPath, namespace);
|
|
887
|
+
}
|
|
888
|
+
async scanRecursive(dirPath, namespace) {
|
|
889
|
+
const specs = [];
|
|
890
|
+
let dirEntries;
|
|
891
|
+
try {
|
|
892
|
+
const entries = await promises.readdir(dirPath, { withFileTypes: true });
|
|
893
|
+
dirEntries = entries.map((entry) => ({
|
|
894
|
+
name: entry.name,
|
|
895
|
+
isDirectory: entry.isDirectory()
|
|
896
|
+
}));
|
|
897
|
+
} catch (error) {
|
|
898
|
+
this.onError?.(dirPath, error);
|
|
899
|
+
return specs;
|
|
900
|
+
}
|
|
901
|
+
const dirName = path.basename(dirPath);
|
|
902
|
+
try {
|
|
903
|
+
const loadedSpecs = await this.loadToolDir(dirPath, dirName, namespace);
|
|
904
|
+
if (loadedSpecs.length > 0) specs.push(...loadedSpecs);
|
|
905
|
+
} catch (error) {
|
|
906
|
+
this.onError?.(dirPath, error);
|
|
907
|
+
}
|
|
908
|
+
for (const entry of dirEntries) {
|
|
909
|
+
if (!entry.isDirectory) continue;
|
|
910
|
+
const childPath = path.join(dirPath, entry.name);
|
|
911
|
+
try {
|
|
912
|
+
const childSpecs = await this.scanRecursive(childPath, namespace);
|
|
913
|
+
specs.push(...childSpecs);
|
|
914
|
+
} catch (error) {
|
|
915
|
+
this.onError?.(childPath, error);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return specs;
|
|
919
|
+
}
|
|
920
|
+
async loadToolDir(dirPath, dirName, namespace) {
|
|
921
|
+
const manifestPath = path.join(dirPath, "tool.json");
|
|
922
|
+
let manifestRaw;
|
|
923
|
+
try {
|
|
924
|
+
manifestRaw = await promises.readFile(manifestPath, "utf-8");
|
|
925
|
+
} catch {
|
|
926
|
+
const inferred = await this.inferManifest(dirPath, dirName);
|
|
927
|
+
if (!inferred) return [];
|
|
928
|
+
if (inferred.kind === "langchain") {
|
|
929
|
+
if (inferred.entryPoint) {
|
|
930
|
+
const loaded3 = await loadLangChainTool(dirPath, inferred, this.extensions);
|
|
931
|
+
return [this.toToolSpec(loaded3, dirName, dirPath, namespace)];
|
|
932
|
+
}
|
|
933
|
+
return loadLangChainToolsFromDir(
|
|
934
|
+
dirPath,
|
|
935
|
+
dirName,
|
|
936
|
+
inferred,
|
|
937
|
+
false,
|
|
938
|
+
namespace,
|
|
939
|
+
this.extensions,
|
|
940
|
+
LANGCHAIN_DIR_NAME,
|
|
941
|
+
(loaded3, nameHint, dp, ns) => this.toToolSpec(loaded3, nameHint, dp, ns),
|
|
942
|
+
this.onError
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
if (inferred.kind === "skill") {
|
|
946
|
+
const loadedList = await loadSkillTools(dirPath, inferred, this.extensions);
|
|
947
|
+
return loadedList.map(
|
|
948
|
+
(loaded3) => this.toToolSpec(loaded3, dirName, dirPath, namespace)
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
const loaded2 = await this.loadByKind(dirPath, inferred);
|
|
952
|
+
return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
|
|
953
|
+
}
|
|
954
|
+
let manifest;
|
|
955
|
+
try {
|
|
956
|
+
manifest = JSON.parse(manifestRaw);
|
|
957
|
+
} catch (err) {
|
|
958
|
+
throw new DiscoveryError(dirPath, "manifest", "Invalid JSON in tool.json", err);
|
|
959
|
+
}
|
|
960
|
+
if (!manifest.kind) {
|
|
961
|
+
throw new DiscoveryError(dirPath, "manifest", `tool.json must have a "kind" field`);
|
|
962
|
+
}
|
|
963
|
+
if (manifest.enabled === false) return [];
|
|
964
|
+
if (manifest.kind === "langchain") {
|
|
965
|
+
if (manifest.entryPoint) {
|
|
966
|
+
const loaded2 = await loadLangChainTool(dirPath, manifest, this.extensions);
|
|
967
|
+
return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
|
|
968
|
+
}
|
|
969
|
+
return loadLangChainToolsFromDir(
|
|
970
|
+
dirPath,
|
|
971
|
+
dirName,
|
|
972
|
+
manifest,
|
|
973
|
+
true,
|
|
974
|
+
namespace,
|
|
975
|
+
this.extensions,
|
|
976
|
+
LANGCHAIN_DIR_NAME,
|
|
977
|
+
(loaded2, nameHint, dp, ns) => this.toToolSpec(loaded2, nameHint, dp, ns),
|
|
978
|
+
this.onError
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
if (manifest.kind === "skill") {
|
|
982
|
+
const loadedList = await loadSkillTools(dirPath, manifest, this.extensions);
|
|
983
|
+
return loadedList.map(
|
|
984
|
+
(loaded2) => this.toToolSpec(loaded2, dirName, dirPath, namespace)
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
const loaded = await this.loadByKind(dirPath, manifest);
|
|
988
|
+
return [this.toToolSpec(loaded, dirName, dirPath, namespace)];
|
|
989
|
+
}
|
|
990
|
+
async inferManifest(dirPath, dirName) {
|
|
991
|
+
const kinds = [];
|
|
992
|
+
for (const m of DIRECTORY_KIND_MARKERS) {
|
|
993
|
+
if (await this.fileExists(path.join(dirPath, m.markerFile))) kinds.push(m.kind);
|
|
994
|
+
}
|
|
995
|
+
const isLangchainDir = dirName === LANGCHAIN_DIR_NAME;
|
|
996
|
+
const hasLangchain = isLangchainDir ? (await listLangchainEntryFiles(dirPath, this.extensions)).length > 0 : dirName !== chunkJW4EMVTE_cjs.SKILL_DIR_NAME && await this.hasEntryPoint(dirPath, "index");
|
|
997
|
+
if (hasLangchain) kinds.push("langchain");
|
|
998
|
+
if (kinds.length === 0) return null;
|
|
999
|
+
if (kinds.length > 1) {
|
|
1000
|
+
throw new DiscoveryError(
|
|
1001
|
+
dirPath,
|
|
1002
|
+
"manifest",
|
|
1003
|
+
`Ambiguous tool kind (found ${kinds.join(", ")}). Add tool.json to disambiguate.`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
const kind = kinds[0];
|
|
1007
|
+
const manifest = { kind };
|
|
1008
|
+
const marker = DIRECTORY_KIND_MARKERS.find((m) => m.kind === kind);
|
|
1009
|
+
if (marker) {
|
|
1010
|
+
manifest.entryPoint = marker.defaultEntryPoint;
|
|
1011
|
+
}
|
|
1012
|
+
if (kind === "langchain" && !isLangchainDir) manifest.entryPoint = "index";
|
|
1013
|
+
return manifest;
|
|
1014
|
+
}
|
|
1015
|
+
async fileExists(path6) {
|
|
1016
|
+
try {
|
|
1017
|
+
await promises.access(path6);
|
|
1018
|
+
return true;
|
|
1019
|
+
} catch {
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
async hasEntryPoint(dirPath, baseName) {
|
|
1024
|
+
try {
|
|
1025
|
+
await resolveEntryPoint(dirPath, baseName, this.extensions);
|
|
1026
|
+
return true;
|
|
1027
|
+
} catch {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
async loadByKind(dirPath, manifest) {
|
|
1032
|
+
const kind = manifest.kind;
|
|
1033
|
+
const loader = getDirectoryLoader(kind);
|
|
1034
|
+
const result = await loader(dirPath, manifest, this.extensions);
|
|
1035
|
+
const list = Array.isArray(result) ? result : [result];
|
|
1036
|
+
if (list.length === 0) {
|
|
1037
|
+
throw new DiscoveryError(dirPath, "load", "No tools loaded", new Error("empty"));
|
|
1038
|
+
}
|
|
1039
|
+
return list[0];
|
|
1040
|
+
}
|
|
1041
|
+
toToolSpec(loaded, dirName, dirPath, namespace) {
|
|
1042
|
+
const { manifest } = loaded;
|
|
1043
|
+
const kindDirNames = new Set(DIRECTORY_DISCOVERABLE_KINDS);
|
|
1044
|
+
const parentName = path.basename(path.join(dirPath, ".."));
|
|
1045
|
+
const isKindDir = kindDirNames.has(dirName);
|
|
1046
|
+
const defaultDirName = isKindDir ? parentName : dirName;
|
|
1047
|
+
const inferredName = isKindDir ? `${namespace}/${defaultDirName}-${dirName}` : `${namespace}/${defaultDirName}`;
|
|
1048
|
+
const name = manifest.name ?? inferredName;
|
|
1049
|
+
const spec = this.buildBaseSpec(manifest, name, dirName);
|
|
1050
|
+
applyDirectoryLoadedToSpec(spec, loaded, manifest, defaultDirName, namespace);
|
|
1051
|
+
return spec;
|
|
1052
|
+
}
|
|
1053
|
+
buildBaseSpec(manifest, name, dirName) {
|
|
1054
|
+
return {
|
|
1055
|
+
name,
|
|
1056
|
+
version: manifest.version ?? "1.0.0",
|
|
1057
|
+
kind: manifest.kind,
|
|
1058
|
+
description: manifest.description ?? `${manifest.kind} tool: ${dirName}`,
|
|
1059
|
+
tags: manifest.tags,
|
|
1060
|
+
inputSchema: manifest.inputSchema ?? { type: "object", additionalProperties: true },
|
|
1061
|
+
outputSchema: manifest.outputSchema ?? { type: "object", additionalProperties: true },
|
|
1062
|
+
capabilities: manifest.capabilities ?? [],
|
|
1063
|
+
costHints: manifest.costHints
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
1067
|
+
|
|
1068
|
+
exports.DirectoryScanner = DirectoryScanner;
|
|
1069
|
+
exports.LANGCHAIN_KIND = LANGCHAIN_KIND;
|
|
1070
|
+
exports.MCP_KIND = MCP_KIND;
|
|
1071
|
+
exports.discoverTools = discoverTools;
|
|
1072
|
+
//# sourceMappingURL=chunk-AZUXVVGV.cjs.map
|
|
1073
|
+
//# sourceMappingURL=chunk-AZUXVVGV.cjs.map
|