@easynet/agent-tool 1.0.59 → 1.0.61

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.
Files changed (81) hide show
  1. package/dist/api/expose/index.d.ts +1 -1
  2. package/dist/api/expose/index.d.ts.map +1 -1
  3. package/dist/api/expose/mcp-build/build.d.ts +1 -3
  4. package/dist/api/expose/mcp-build/build.d.ts.map +1 -1
  5. package/dist/api/expose/mcp-build/index.d.ts +2 -2
  6. package/dist/api/expose/mcp-build/index.d.ts.map +1 -1
  7. package/dist/api/expose/mcp-build/run.d.ts +1 -3
  8. package/dist/api/expose/mcp-build/run.d.ts.map +1 -1
  9. package/dist/api/main.cjs +19 -15
  10. package/dist/api/main.js +8 -4
  11. package/dist/build.cjs +31 -0
  12. package/dist/build.cjs.map +1 -0
  13. package/dist/build.d.ts +13 -0
  14. package/dist/build.d.ts.map +1 -0
  15. package/dist/build.js +6 -0
  16. package/dist/build.js.map +1 -0
  17. package/dist/chunk-45S2HPVU.js +463 -0
  18. package/dist/chunk-45S2HPVU.js.map +1 -0
  19. package/dist/{chunk-Y75CRPVF.js → chunk-5J27MF7S.js} +11 -12
  20. package/dist/chunk-5J27MF7S.js.map +1 -0
  21. package/dist/{chunk-JXYANBTH.cjs → chunk-HK4GTFTQ.cjs} +57 -1645
  22. package/dist/chunk-HK4GTFTQ.cjs.map +1 -0
  23. package/dist/chunk-JNIWNSCQ.cjs +494 -0
  24. package/dist/chunk-JNIWNSCQ.cjs.map +1 -0
  25. package/dist/{chunk-DPOLJN7F.cjs → chunk-NMZ4IMEW.cjs} +22 -25
  26. package/dist/chunk-NMZ4IMEW.cjs.map +1 -0
  27. package/dist/{chunk-A5C2MUNA.js → chunk-NVT4X4CB.js} +41 -1600
  28. package/dist/chunk-NVT4X4CB.js.map +1 -0
  29. package/dist/chunk-OG5ZSXQ5.cjs +1099 -0
  30. package/dist/chunk-OG5ZSXQ5.cjs.map +1 -0
  31. package/dist/{chunk-WQMHMPNC.cjs → chunk-PYCCJF7C.cjs} +2 -68
  32. package/dist/chunk-PYCCJF7C.cjs.map +1 -0
  33. package/dist/{chunk-IWM5B5DU.js → chunk-QPKBEU64.js} +4 -3
  34. package/dist/chunk-QPKBEU64.js.map +1 -0
  35. package/dist/chunk-QXQ4477T.js +49 -0
  36. package/dist/chunk-QXQ4477T.js.map +1 -0
  37. package/dist/chunk-RZTTO5MQ.js +65 -0
  38. package/dist/chunk-RZTTO5MQ.js.map +1 -0
  39. package/dist/{chunk-FCYBA7PR.js → chunk-WUMLZERG.js} +3 -62
  40. package/dist/chunk-WUMLZERG.js.map +1 -0
  41. package/dist/chunk-XPGHS4W7.cjs +73 -0
  42. package/dist/chunk-XPGHS4W7.cjs.map +1 -0
  43. package/dist/chunk-YRFUGA3C.js +1072 -0
  44. package/dist/chunk-YRFUGA3C.js.map +1 -0
  45. package/dist/chunk-ZDSZHEQU.cjs +52 -0
  46. package/dist/chunk-ZDSZHEQU.cjs.map +1 -0
  47. package/dist/{chunk-MUBZV65R.cjs → chunk-ZH5MH3AK.cjs} +16 -15
  48. package/dist/chunk-ZH5MH3AK.cjs.map +1 -0
  49. package/dist/core/runtime.cjs +6 -5
  50. package/dist/core/runtime.js +2 -1
  51. package/dist/extension.cjs +359 -0
  52. package/dist/extension.cjs.map +1 -0
  53. package/dist/extension.d.ts +6 -0
  54. package/dist/extension.d.ts.map +1 -0
  55. package/dist/extension.js +341 -0
  56. package/dist/extension.js.map +1 -0
  57. package/dist/index.cjs +17 -609
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.d.ts +1 -25
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +8 -520
  62. package/dist/index.js.map +1 -1
  63. package/dist/security.cjs +193 -0
  64. package/dist/security.cjs.map +1 -0
  65. package/dist/security.d.ts +6 -0
  66. package/dist/security.d.ts.map +1 -0
  67. package/dist/security.js +182 -0
  68. package/dist/security.js.map +1 -0
  69. package/dist/utils/cli/index.cjs +25 -21
  70. package/dist/utils/cli/index.cjs.map +1 -1
  71. package/dist/utils/cli/index.js +13 -9
  72. package/dist/utils/cli/index.js.map +1 -1
  73. package/package.json +16 -2
  74. package/dist/chunk-A5C2MUNA.js.map +0 -1
  75. package/dist/chunk-DPOLJN7F.cjs.map +0 -1
  76. package/dist/chunk-FCYBA7PR.js.map +0 -1
  77. package/dist/chunk-IWM5B5DU.js.map +0 -1
  78. package/dist/chunk-JXYANBTH.cjs.map +0 -1
  79. package/dist/chunk-MUBZV65R.cjs.map +0 -1
  80. package/dist/chunk-WQMHMPNC.cjs.map +0 -1
  81. package/dist/chunk-Y75CRPVF.js.map +0 -1
@@ -1,8 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkWQMHMPNC_cjs = require('./chunk-WQMHMPNC.cjs');
4
- var chunkQEJF3KDV_cjs = require('./chunk-QEJF3KDV.cjs');
5
3
  var chunkUUNG3GL3_cjs = require('./chunk-UUNG3GL3.cjs');
4
+ var chunkOG5ZSXQ5_cjs = require('./chunk-OG5ZSXQ5.cjs');
5
+ var chunkZDSZHEQU_cjs = require('./chunk-ZDSZHEQU.cjs');
6
+ var chunkPYCCJF7C_cjs = require('./chunk-PYCCJF7C.cjs');
7
+ var chunkXPGHS4W7_cjs = require('./chunk-XPGHS4W7.cjs');
8
+ var chunkQEJF3KDV_cjs = require('./chunk-QEJF3KDV.cjs');
6
9
  var fs = require('fs');
7
10
  var path = require('path');
8
11
  var agentCommon = require('@easynet/agent-common');
@@ -12,42 +15,17 @@ var cockatiel = require('cockatiel');
12
15
  var eventemitter3 = require('eventemitter3');
13
16
  var uuid = require('uuid');
14
17
  var pTimeout = require('p-timeout');
15
- var promises = require('fs/promises');
16
- var ts2 = require('typescript');
17
18
  var module$1 = require('module');
18
19
  var url = require('url');
19
- var yaml = require('js-yaml');
20
20
  var npm = require('@easynet/agent-common/npm');
21
21
  var http = require('http');
22
22
 
23
23
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
24
24
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
25
25
 
26
- function _interopNamespace(e) {
27
- if (e && e.__esModule) return e;
28
- var n = Object.create(null);
29
- if (e) {
30
- Object.keys(e).forEach(function (k) {
31
- if (k !== 'default') {
32
- var d = Object.getOwnPropertyDescriptor(e, k);
33
- Object.defineProperty(n, k, d.get ? d : {
34
- enumerable: true,
35
- get: function () { return e[k]; }
36
- });
37
- }
38
- });
39
- }
40
- n.default = e;
41
- return Object.freeze(n);
42
- }
43
-
44
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
45
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
46
26
  var Ajv__default = /*#__PURE__*/_interopDefault(Ajv);
47
27
  var addFormats__default = /*#__PURE__*/_interopDefault(addFormats);
48
28
  var pTimeout__default = /*#__PURE__*/_interopDefault(pTimeout);
49
- var ts2__namespace = /*#__PURE__*/_interopNamespace(ts2);
50
- var yaml__default = /*#__PURE__*/_interopDefault(yaml);
51
29
 
52
30
  function loadToolConfig(toolYamlPath) {
53
31
  const abs = path.resolve(toolYamlPath);
@@ -226,13 +204,13 @@ function expandToolDescriptorsToRegistryNames(descriptors, registryNames) {
226
204
  out.push(s);
227
205
  continue;
228
206
  }
229
- const path7 = parseToolPath(s);
230
- if (path7) {
231
- const packagePrefix = path7.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path7.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
207
+ const path = parseToolPath(s);
208
+ if (path) {
209
+ const packagePrefix = path.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
232
210
  const prefixWithDot = packagePrefix ? packagePrefix + "." : "";
233
211
  if (prefixWithDot) {
234
- if (path7.toolName) {
235
- const suffix = "." + path7.toolName;
212
+ if (path.toolName) {
213
+ const suffix = "." + path.toolName;
236
214
  for (const r of registryNames) {
237
215
  if (r.startsWith(prefixWithDot) && r.endsWith(suffix) && !seen.has(r)) {
238
216
  seen.add(r);
@@ -261,9 +239,9 @@ function resolveToolDescriptor(descriptor) {
261
239
  return s;
262
240
  }
263
241
  function fileDescriptorToPackagePrefix(descriptor) {
264
- const path7 = parseToolPath(descriptor.trim());
265
- if (!path7 || path7.protocol !== "file") return "";
266
- const pathPart = `${path7.scope}/${path7.packageWithVersion}`;
242
+ const path = parseToolPath(descriptor.trim());
243
+ if (!path || path.protocol !== "file") return "";
244
+ const pathPart = `${path.scope}/${path.packageWithVersion}`;
267
245
  const normalized = chunkQEJF3KDV_cjs.normalizeToolName(pathPart);
268
246
  if (!normalized) return "";
269
247
  return chunkQEJF3KDV_cjs.normalizeToolName("file." + normalized);
@@ -563,17 +541,17 @@ var PolicyEngine = class {
563
541
  */
564
542
  extractStringValues(args, keyPatterns) {
565
543
  const results = [];
566
- const walk2 = (obj) => {
544
+ const walk = (obj) => {
567
545
  for (const [key, val] of Object.entries(obj)) {
568
546
  const lowerKey = key.toLowerCase();
569
547
  if (typeof val === "string" && keyPatterns.some((p) => lowerKey.includes(p))) {
570
548
  results.push(val);
571
549
  } else if (val && typeof val === "object" && !Array.isArray(val)) {
572
- walk2(val);
550
+ walk(val);
573
551
  }
574
552
  }
575
553
  };
576
- walk2(args);
554
+ walk(args);
577
555
  return results;
578
556
  }
579
557
  };
@@ -758,30 +736,30 @@ function summarizeValue(value, maxLen) {
758
736
  }
759
737
  function extractUrls(obj) {
760
738
  const urls = [];
761
- const walk2 = (val) => {
739
+ const walk = (val) => {
762
740
  if (typeof val === "string" && /^https?:\/\//i.test(val)) {
763
741
  urls.push(val);
764
742
  } else if (val && typeof val === "object") {
765
743
  for (const v of Object.values(val)) {
766
- walk2(v);
744
+ walk(v);
767
745
  }
768
746
  }
769
747
  };
770
- walk2(obj);
748
+ walk(obj);
771
749
  return urls.slice(0, 10);
772
750
  }
773
751
  function extractFilePaths(obj) {
774
752
  const paths = [];
775
- const walk2 = (val) => {
753
+ const walk = (val) => {
776
754
  if (typeof val === "string" && (val.startsWith("/") || val.startsWith("./")) && val.includes(".")) {
777
755
  paths.push(val);
778
756
  } else if (val && typeof val === "object") {
779
757
  for (const v of Object.values(val)) {
780
- walk2(v);
758
+ walk(v);
781
759
  }
782
760
  }
783
761
  };
784
- walk2(obj);
762
+ walk(obj);
785
763
  return paths.slice(0, 10);
786
764
  }
787
765
  var EventLog = class {
@@ -1191,7 +1169,7 @@ function resolveTool(toolName, registry) {
1191
1169
  const key = chunkQEJF3KDV_cjs.normalizeToolName(toolName);
1192
1170
  const spec = registry.get(key);
1193
1171
  if (!spec) {
1194
- throw chunkWQMHMPNC_cjs.createTaggedError(
1172
+ throw chunkXPGHS4W7_cjs.createTaggedError(
1195
1173
  "TOOL_NOT_FOUND",
1196
1174
  `Tool not found: ${toolName}`,
1197
1175
  { availableTools: registry.snapshot().slice(0, 20).map((s) => s.name) }
@@ -1230,7 +1208,7 @@ function validateInput(spec, args, validator) {
1230
1208
  if (error instanceof SchemaValidationError) {
1231
1209
  const requiredKeys = getRequiredKeys(spec.inputSchema);
1232
1210
  const passedKeys = args != null && typeof args === "object" && !Array.isArray(args) ? Object.keys(args) : [];
1233
- throw chunkWQMHMPNC_cjs.createTaggedError("INPUT_SCHEMA_INVALID", error.message, {
1211
+ throw chunkXPGHS4W7_cjs.createTaggedError("INPUT_SCHEMA_INVALID", error.message, {
1234
1212
  errors: error.errors,
1235
1213
  schema: spec.inputSchema,
1236
1214
  requiredKeys: requiredKeys.length ? requiredKeys : void 0,
@@ -1303,7 +1281,7 @@ async function requireHumanApproval(spec, args, ctx, deps) {
1303
1281
  sideEffect,
1304
1282
  reason: err instanceof Error ? err.message : String(err)
1305
1283
  });
1306
- throw chunkWQMHMPNC_cjs.createTaggedError(
1284
+ throw chunkXPGHS4W7_cjs.createTaggedError(
1307
1285
  "HITL_DENIED",
1308
1286
  `Human denied approval for ${spec.name} (${sideEffect})`,
1309
1287
  { reason: err instanceof Error ? err.message : String(err) }
@@ -1316,7 +1294,7 @@ async function requireHumanApproval(spec, args, ctx, deps) {
1316
1294
  sideEffect,
1317
1295
  reason: "User rejected"
1318
1296
  });
1319
- throw chunkWQMHMPNC_cjs.createTaggedError("HITL_DENIED", `Human denied approval for ${spec.name} (${sideEffect})`);
1297
+ throw chunkXPGHS4W7_cjs.createTaggedError("HITL_DENIED", `Human denied approval for ${spec.name} (${sideEffect})`);
1320
1298
  }
1321
1299
  deps.eventLog.append({
1322
1300
  ...baseEvent,
@@ -1328,7 +1306,7 @@ async function requireHumanApproval(spec, args, ctx, deps) {
1328
1306
  async function executeWithBudget(spec, args, ctx, spanId, deps) {
1329
1307
  const adapter = deps.adaptersByToolName.get(spec.name) ?? deps.adapters.get(spec.kind);
1330
1308
  if (!adapter) {
1331
- throw chunkWQMHMPNC_cjs.createTaggedError(
1309
+ throw chunkXPGHS4W7_cjs.createTaggedError(
1332
1310
  "TOOL_NOT_FOUND",
1333
1311
  `No adapter registered for kind: ${spec.kind}`
1334
1312
  );
@@ -1356,7 +1334,7 @@ async function executeWithBudget(spec, args, ctx, spanId, deps) {
1356
1334
  return result;
1357
1335
  });
1358
1336
  };
1359
- const retryFn = () => chunkWQMHMPNC_cjs.withRetry(executeFn, {
1337
+ const retryFn = () => chunkXPGHS4W7_cjs.withRetry(executeFn, {
1360
1338
  maxRetries,
1361
1339
  onRetry: (error, attempt) => {
1362
1340
  deps.metrics.recordRetry(spec.name);
@@ -1383,7 +1361,7 @@ async function executeWithBudget(spec, args, ctx, spanId, deps) {
1383
1361
  });
1384
1362
  } catch (error) {
1385
1363
  if (error instanceof Error && error.message.includes("timed out")) {
1386
- throw chunkWQMHMPNC_cjs.createTaggedError("TIMEOUT", error.message);
1364
+ throw chunkXPGHS4W7_cjs.createTaggedError("TIMEOUT", error.message);
1387
1365
  }
1388
1366
  throw error;
1389
1367
  }
@@ -1397,7 +1375,7 @@ function validateOutput(spec, result, validator) {
1397
1375
  );
1398
1376
  } catch (error) {
1399
1377
  if (error instanceof SchemaValidationError) {
1400
- throw chunkWQMHMPNC_cjs.createTaggedError("OUTPUT_SCHEMA_INVALID", error.message, {
1378
+ throw chunkXPGHS4W7_cjs.createTaggedError("OUTPUT_SCHEMA_INVALID", error.message, {
1401
1379
  errors: error.errors
1402
1380
  });
1403
1381
  }
@@ -1491,7 +1469,7 @@ var PTCRuntime = class {
1491
1469
  logger;
1492
1470
  constructor(options = {}) {
1493
1471
  this.config = options.config ?? {};
1494
- this.registry = options.registry ?? new chunkWQMHMPNC_cjs.ToolRegistry();
1472
+ this.registry = options.registry ?? new chunkPYCCJF7C_cjs.ToolRegistry();
1495
1473
  this.validator = options.validator ?? new SchemaValidator();
1496
1474
  this.policy = options.policy ?? new PolicyEngine(this.config.policy);
1497
1475
  this.budget = options.budget ?? new BudgetManager(this.config.budget);
@@ -1601,7 +1579,7 @@ var PTCRuntime = class {
1601
1579
  tracing: this.tracing
1602
1580
  });
1603
1581
  if (!this.budget.checkRateLimit(spec.name)) {
1604
- throw chunkWQMHMPNC_cjs.createTaggedError(
1582
+ throw chunkXPGHS4W7_cjs.createTaggedError(
1605
1583
  "BUDGET_EXCEEDED",
1606
1584
  `Rate limit exceeded for tool: ${spec.name}`
1607
1585
  );
@@ -1624,7 +1602,7 @@ var PTCRuntime = class {
1624
1602
  const toolError = asToolReturnedError(result);
1625
1603
  if (toolError) {
1626
1604
  const hint = buildInputSchemaHint(spec.inputSchema);
1627
- throw chunkWQMHMPNC_cjs.createTaggedError("UPSTREAM_ERROR", toolError.message, {
1605
+ throw chunkXPGHS4W7_cjs.createTaggedError("UPSTREAM_ERROR", toolError.message, {
1628
1606
  ...toolError.details && typeof toolError.details === "object" && !Array.isArray(toolError.details) ? toolError.details : {},
1629
1607
  hint: hint ?? "Check the tool's input schema for required property names."
1630
1608
  });
@@ -1748,1566 +1726,9 @@ function buildInputSchemaHint(inputSchema) {
1748
1726
  if (names.length === 0) return null;
1749
1727
  return `This tool expects input property ${names.length === 1 ? `'${names[0]}'` : `one of [${names.map((n) => `'${n}'`).join(", ")}]`}. Use the exact property names from the tool schema.`;
1750
1728
  }
1751
- var sandboxValidationEnabled = false;
1752
- function setSandboxValidationEnabled(enabled) {
1753
- sandboxValidationEnabled = enabled;
1754
- }
1755
- async function resolveSandboxedPath2(inputPath, sandboxRoot) {
1756
- let normalizedRoot;
1757
- try {
1758
- normalizedRoot = await promises.realpath(path.resolve(sandboxRoot));
1759
- } catch {
1760
- normalizedRoot = path.normalize(path.resolve(sandboxRoot));
1761
- }
1762
- const resolved = path.resolve(normalizedRoot, inputPath);
1763
- let real;
1764
- try {
1765
- await promises.access(resolved);
1766
- real = await promises.realpath(resolved);
1767
- } catch {
1768
- const parentDir = path.dirname(resolved);
1769
- let realParent;
1770
- try {
1771
- await promises.access(parentDir);
1772
- realParent = await promises.realpath(parentDir);
1773
- } catch {
1774
- realParent = path.normalize(parentDir);
1775
- }
1776
- real = path.resolve(realParent, path.basename(resolved));
1777
- }
1778
- if (sandboxValidationEnabled && !isWithinRoot(real, normalizedRoot)) {
1779
- throw chunkWQMHMPNC_cjs.createTaggedError(
1780
- "PATH_OUTSIDE_SANDBOX",
1781
- `Path "${inputPath}" resolves to "${real}" which is outside sandbox "${normalizedRoot}"`,
1782
- { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot }
1783
- );
1784
- }
1785
- return real;
1786
- }
1787
- function isWithinRoot(path7, root) {
1788
- const normalizedPath = path.normalize(path7);
1789
- const normalizedRoot = path.normalize(root);
1790
- return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + "/");
1791
- }
1792
- async function findDirsContainingFile(rootPath, fileName) {
1793
- const found = [];
1794
- await collectDirsWithFile(rootPath, fileName, found);
1795
- return found;
1796
- }
1797
- async function collectDirsWithFile(dir, fileName, acc) {
1798
- let entries;
1799
- try {
1800
- const e = await promises.readdir(dir, { withFileTypes: true });
1801
- entries = e.map((x) => ({
1802
- name: x.name,
1803
- isDirectory: x.isDirectory(),
1804
- isFile: x.isFile()
1805
- }));
1806
- } catch {
1807
- return;
1808
- }
1809
- if (entries.some((x) => x.isFile && x.name === fileName)) acc.push(dir);
1810
- for (const entry of entries) {
1811
- if (!entry.isDirectory || entry.name === "node_modules" || entry.name.startsWith(".")) continue;
1812
- await collectDirsWithFile(path.join(dir, entry.name), fileName, acc);
1813
- }
1814
- }
1815
- function pathToToolName(sourcePath, programName) {
1816
- const normalized = sourcePath.replace(/\\/g, "/").replace(/\.(ts|tsx|js|mjs|json)$/i, "");
1817
- const segments = normalized.split("/").filter(Boolean);
1818
- return segments.length === 0 ? programName : `${segments.join(".")}.${programName}`;
1819
- }
1820
- function buildOutputSchemaFromReturnType(node, typeChecker, onWarn) {
1821
- const sig = typeChecker.getSignatureFromDeclaration(node);
1822
- if (!sig) {
1823
- onWarn?.("Could not get signature for return type, using object");
1824
- return { type: "object", additionalProperties: true };
1825
- }
1826
- let returnType = typeChecker.getReturnTypeOfSignature(sig);
1827
- if (returnType.getSymbol?.()?.getName() === "Promise") {
1828
- const typeArgs = returnType.typeArguments;
1829
- if (typeArgs?.[0]) returnType = typeArgs[0];
1830
- }
1831
- const schema = typeToJsonSchema(returnType, typeChecker, onWarn);
1832
- const hasProps = typeof schema === "object" && schema.type === "object" && Object.keys(schema.properties ?? {}).length > 0;
1833
- return hasProps ? schema : { type: "object", additionalProperties: true };
1834
- }
1835
- function buildInputSchemaFromParams(node, typeChecker, onWarn) {
1836
- const properties = {};
1837
- const required = [];
1838
- if (!node.parameters.length) {
1839
- return { schema: { type: "object", properties: {} }, required: [] };
1840
- }
1841
- for (const param of node.parameters) {
1842
- const name = param.name.getText();
1843
- if (name.startsWith("_") && name.length <= 2) continue;
1844
- const sym = param.symbol;
1845
- const paramType = sym ? typeChecker.getTypeOfSymbolAtLocation(sym, param) : typeChecker.getTypeAtLocation(param);
1846
- const isOptional = !!param.questionToken || param.initializer !== void 0;
1847
- const propSchema = typeToJsonSchema(paramType, typeChecker, onWarn);
1848
- properties[name] = propSchema;
1849
- if (!isOptional) required.push(name);
1850
- }
1851
- const paramNames = Object.keys(properties);
1852
- if (paramNames.length === 1) {
1853
- const soleName = paramNames[0];
1854
- const inner = properties[soleName];
1855
- if (inner && typeof inner === "object" && inner.type === "object" && inner.properties && typeof inner.properties === "object") {
1856
- return {
1857
- schema: {
1858
- type: "object",
1859
- properties: inner.properties,
1860
- ...Array.isArray(inner.required) && inner.required.length > 0 ? { required: inner.required } : {},
1861
- ...inner.additionalProperties !== void 0 ? { additionalProperties: inner.additionalProperties } : {}
1862
- },
1863
- required: inner.required ?? []
1864
- };
1865
- }
1866
- }
1867
- return {
1868
- schema: {
1869
- type: "object",
1870
- properties,
1871
- ...required.length > 0 ? { required } : {}
1872
- },
1873
- required
1874
- };
1875
- }
1876
- function typeToJsonSchema(type, typeChecker, onWarn) {
1877
- const flags = type.flags;
1878
- if (flags & ts2__namespace.TypeFlags.String) return { type: "string" };
1879
- if (flags & ts2__namespace.TypeFlags.Number) return { type: "number" };
1880
- if (flags & ts2__namespace.TypeFlags.Boolean) return { type: "boolean" };
1881
- if (flags & ts2__namespace.TypeFlags.BooleanLiteral) return { type: "boolean" };
1882
- if (flags & ts2__namespace.TypeFlags.Null) return { type: "null" };
1883
- if (flags & ts2__namespace.TypeFlags.Undefined || flags & ts2__namespace.TypeFlags.Void) return {};
1884
- if (flags & ts2__namespace.TypeFlags.Any || flags & ts2__namespace.TypeFlags.Unknown) {
1885
- onWarn?.(`Unsupported type: any/unknown, using empty schema`);
1886
- return {};
1887
- }
1888
- if (type.isUnion?.()) {
1889
- const union = type;
1890
- const types = union.types;
1891
- const withoutUndef = types.filter(
1892
- (t) => !(t.flags & ts2__namespace.TypeFlags.Undefined) && !(t.flags & ts2__namespace.TypeFlags.Void)
1893
- );
1894
- if (withoutUndef.length === 1) return typeToJsonSchema(withoutUndef[0], typeChecker, onWarn);
1895
- if (withoutUndef.length === 0) return {};
1896
- const stringEnumValues = [];
1897
- let allStringLiterals = true;
1898
- for (const t of withoutUndef) {
1899
- if (t.flags & ts2__namespace.TypeFlags.StringLiteral) {
1900
- const lit = t;
1901
- if (typeof lit.value === "string") stringEnumValues.push(lit.value);
1902
- } else {
1903
- allStringLiterals = false;
1904
- break;
1905
- }
1906
- }
1907
- if (allStringLiterals && stringEnumValues.length > 0) {
1908
- return { type: "string", enum: [...new Set(stringEnumValues)] };
1909
- }
1910
- let allBooleanLiterals = true;
1911
- for (const t of withoutUndef) {
1912
- if (!(t.flags & ts2__namespace.TypeFlags.BooleanLiteral)) {
1913
- allBooleanLiterals = false;
1914
- break;
1915
- }
1916
- }
1917
- if (allBooleanLiterals) return { type: "boolean" };
1918
- }
1919
- if (flags & ts2__namespace.TypeFlags.StringLiteral) {
1920
- const lit = type;
1921
- if (typeof lit.value === "string") {
1922
- return { type: "string", enum: [lit.value] };
1923
- }
1924
- return { type: "string" };
1925
- }
1926
- if (typeChecker.isArrayType(type)) {
1927
- const typeRef = type;
1928
- const typeArgs = typeRef.typeArguments;
1929
- const itemType = typeArgs?.[0];
1930
- const items = itemType ? typeToJsonSchema(itemType, typeChecker, onWarn) : {};
1931
- return { type: "array", items: Object.keys(items).length ? items : {} };
1932
- }
1933
- const str = typeChecker.typeToString(type);
1934
- if (str === "string") return { type: "string" };
1935
- if (str === "number") return { type: "number" };
1936
- if (str === "boolean") return { type: "boolean" };
1937
- if (str.endsWith("[]")) {
1938
- const inner = str.slice(0, -2).trim();
1939
- const itemType = inner === "string" ? { type: "string" } : inner === "number" ? { type: "number" } : {};
1940
- return { type: "array", items: itemType };
1941
- }
1942
- if (type.getProperties && type.getProperties().length >= 0) {
1943
- const props = type.getProperties();
1944
- const properties = {};
1945
- const required = [];
1946
- for (const p of props) {
1947
- const decl = p.valueDeclaration;
1948
- const propType = decl ? typeChecker.getTypeAtLocation(decl) : typeChecker.getTypeOfSymbolAtLocation(p, p.valueDeclaration);
1949
- const optional = decl && ts2__namespace.isPropertySignature(decl) ? !!decl.questionToken : false;
1950
- properties[p.name] = typeToJsonSchema(propType, typeChecker, onWarn);
1951
- if (!optional) required.push(p.name);
1952
- }
1953
- return { type: "object", properties, ...required.length ? { required } : {} };
1954
- }
1955
- onWarn?.(`Unsupported type: ${str}, using object`);
1956
- return { type: "object" };
1957
- }
1958
-
1959
- // src/tools/function/types.ts
1960
- var FUNCTION_KIND = "function";
1961
-
1962
- // src/tools/skill/types.ts
1963
- var SKILL_KIND = "skill";
1964
- var SKILL_DIR_NAME = "skill";
1965
-
1966
- // src/tools/n8n/types.ts
1967
- var N8N_KIND = "n8n";
1968
-
1969
- // src/tools/mcp/mcpSpecToToolSpec.ts
1970
- var DEFAULT_OUTPUT = { type: "object", additionalProperties: true };
1971
- function mcpSpecToToolSpec(spec, projectPath) {
1972
- const base = {
1973
- name: spec.name,
1974
- version: "1.0.0",
1975
- kind: spec.kind,
1976
- description: spec.description,
1977
- inputSchema: spec.inputSchema ?? DEFAULT_OUTPUT,
1978
- outputSchema: "outputSchema" in spec && spec.outputSchema ? spec.outputSchema : chunkQEJF3KDV_cjs.DEFAULT_OUTPUT_SCHEMA,
1979
- capabilities: [],
1980
- _meta: spec._meta,
1981
- ...spec.kind === N8N_KIND && "webhookUrl" in spec && spec.webhookUrl ? { endpoint: spec.webhookUrl } : {}
1982
- };
1983
- if (spec.kind === FUNCTION_KIND && "sourcePath" in spec && "exportName" in spec) {
1984
- base._meta = {
1985
- ...base._meta,
1986
- sourcePath: spec.sourcePath,
1987
- exportName: spec.exportName,
1988
- ...projectPath && { projectPath }
1989
- };
1990
- }
1991
- if (spec.kind === SKILL_KIND && "sourcePath" in spec && projectPath) {
1992
- base._meta = { ...base._meta, sourcePath: spec.sourcePath, projectPath };
1993
- }
1994
- if (spec.kind === N8N_KIND && "sourcePath" in spec && projectPath) {
1995
- base._meta = { ...base._meta, sourcePath: spec.sourcePath, projectPath };
1996
- }
1997
- return base;
1998
- }
1999
-
2000
- // src/tools/function/scanner.ts
2001
- var TOOL_TAG = "@tool";
2002
- var EFFECT_VALUES = ["none", "local_write", "external_write", "destructive"];
2003
- function scanForTools(options) {
2004
- const projectPath = path__namespace.resolve(options.projectPath);
2005
- const tsconfigPath = options.tsconfigPath ?? path__namespace.join(projectPath, "tsconfig.json");
2006
- const include = options.include ?? ["**/*.ts"];
2007
- const errors = [];
2008
- const warnings = [];
2009
- let config;
2010
- let configPathResolved = path__namespace.resolve(projectPath, tsconfigPath);
2011
- if (!fs__namespace.existsSync(configPathResolved)) {
2012
- configPathResolved = path__namespace.join(projectPath, "tsconfig.json");
2013
- }
2014
- if (fs__namespace.existsSync(configPathResolved)) {
2015
- const configFile = ts2__namespace.readConfigFile(configPathResolved, ts2__namespace.sys.readFile);
2016
- if (configFile.error) {
2017
- errors.push({ file: configPathResolved, message: String(configFile.error.messageText) });
2018
- return { specs: [], errors, warnings };
2019
- }
2020
- const parsed = ts2__namespace.parseJsonConfigFileContent(
2021
- configFile.config,
2022
- ts2__namespace.sys,
2023
- path__namespace.dirname(configPathResolved)
2024
- );
2025
- if (parsed.errors.length) {
2026
- for (const e of parsed.errors) {
2027
- errors.push({ file: e.file?.fileName ?? "tsconfig", message: String(e.messageText) });
2028
- }
2029
- return { specs: [], errors, warnings };
2030
- }
2031
- config = parsed;
2032
- } else {
2033
- config = {
2034
- options: {
2035
- target: ts2__namespace.ScriptTarget.ES2022,
2036
- module: ts2__namespace.ModuleKind.ESNext,
2037
- moduleResolution: ts2__namespace.ModuleResolutionKind.NodeNext,
2038
- strict: true,
2039
- skipLibCheck: true,
2040
- noEmit: true
2041
- },
2042
- fileNames: resolveGlob(projectPath, include),
2043
- errors: []
2044
- };
2045
- }
2046
- const program = ts2__namespace.createProgram(config.fileNames, config.options);
2047
- const typeChecker = program.getTypeChecker();
2048
- const specs = [];
2049
- for (const sourceFile of program.getSourceFiles()) {
2050
- const fileName = sourceFile.fileName;
2051
- if (fileName.includes("node_modules") || fileName.endsWith(".d.ts")) continue;
2052
- if (!config.fileNames.some((f) => path__namespace.resolve(f) === path__namespace.resolve(fileName))) continue;
2053
- ts2__namespace.forEachChild(sourceFile, (node) => {
2054
- const decl = getExportedFunctionDeclaration(node);
2055
- if (!decl) return;
2056
- const func = decl.func;
2057
- const name = decl.name;
2058
- if (!name) return;
2059
- const host = getJSDocHost(func);
2060
- if (!hasToolTag(host)) return;
2061
- const jsDoc = getJSDocComments(host);
2062
- const description = getDescription(jsDoc);
2063
- if (!description) {
2064
- warnings.push({ file: fileName, message: `Tool ${name}: missing description, using humanized name` });
2065
- }
2066
- const sideEffect = getEffect(host);
2067
- const onWarn = (msg) => warnings.push({ file: fileName, message: `${name}: ${msg}` });
2068
- const { schema } = buildInputSchemaFromParams(func, typeChecker, onWarn);
2069
- const inputSchema = Object.keys(schema.properties ?? {}).length > 0 ? schema : { type: "object", properties: {} };
2070
- const outputSchema = buildOutputSchemaFromReturnType(func, typeChecker, onWarn);
2071
- const sourcePath = path__namespace.relative(projectPath, fileName) || path__namespace.basename(fileName);
2072
- const toolName = pathToToolName(sourcePath, name);
2073
- specs.push({
2074
- kind: FUNCTION_KIND,
2075
- name: toolName,
2076
- description: description || humanize(name),
2077
- inputSchema,
2078
- outputSchema,
2079
- _meta: { hitl: { sideEffect } },
2080
- sourcePath,
2081
- exportName: name
2082
- });
2083
- });
2084
- }
2085
- return { specs, errors, warnings };
2086
- }
2087
- function resolveGlob(projectPath, patterns) {
2088
- const result = [];
2089
- const seen = /* @__PURE__ */ new Set();
2090
- const add = (f) => {
2091
- const abs = path__namespace.resolve(f);
2092
- if (f.endsWith(".ts") && !f.endsWith(".d.ts") && !seen.has(abs)) {
2093
- seen.add(abs);
2094
- result.push(abs);
2095
- }
2096
- };
2097
- for (const p of patterns) {
2098
- const full = path__namespace.join(projectPath, p);
2099
- if (full.includes("*")) {
2100
- const baseDir = full.replace(/\*\*\/.*$/, "").replace(/\*.*$/, "").replace(/\/?$/, "") || ".";
2101
- const dir = path__namespace.resolve(projectPath, baseDir);
2102
- if (fs__namespace.existsSync(dir)) walk(dir, add);
2103
- } else {
2104
- const resolved = path__namespace.resolve(projectPath, full);
2105
- if (fs__namespace.existsSync(resolved)) {
2106
- if (fs__namespace.statSync(resolved).isFile()) add(resolved);
2107
- else walk(resolved, add);
2108
- }
2109
- }
2110
- }
2111
- if (result.length > 0) return result;
2112
- const srcDir = path__namespace.join(projectPath, "src");
2113
- if (fs__namespace.existsSync(srcDir)) return walkCollect(srcDir);
2114
- return [];
2115
- }
2116
- function walkCollect(dir) {
2117
- const out = [];
2118
- walk(dir, (fullPath) => {
2119
- if (fullPath.endsWith(".ts") && !fullPath.endsWith(".d.ts")) out.push(path__namespace.resolve(fullPath));
2120
- });
2121
- return out;
2122
- }
2123
- var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", "generated", "dist"]);
2124
- function walk(dir, visit) {
2125
- try {
2126
- const entries = fs__namespace.readdirSync(dir, { withFileTypes: true });
2127
- for (const e of entries) {
2128
- const full = path__namespace.join(dir, e.name);
2129
- if (e.isDirectory() && !SKIP_DIRS.has(e.name)) walk(full, visit);
2130
- else if (e.isFile()) visit(full);
2131
- }
2132
- } catch {
2133
- }
2134
- }
2135
- function getExportedFunctionDeclaration(node, _sourceFile) {
2136
- if (ts2__namespace.isFunctionDeclaration(node) && node.name) {
2137
- const exported = (ts2__namespace.getModifiers(node) ?? []).some((m) => m.kind === ts2__namespace.SyntaxKind.ExportKeyword);
2138
- if (exported) return { func: node, name: node.name.getText() };
2139
- return null;
2140
- }
2141
- if (ts2__namespace.isVariableStatement(node)) {
2142
- const exported = (ts2__namespace.getModifiers(node) ?? []).some((m) => m.kind === ts2__namespace.SyntaxKind.ExportKeyword);
2143
- if (!exported) return null;
2144
- for (const decl of node.declarationList.declarations) {
2145
- let init = decl.initializer;
2146
- while (init && (ts2__namespace.isParenthesizedExpression(init) || ts2__namespace.isAsExpression(init)))
2147
- init = init.expression;
2148
- if (init && ts2__namespace.isArrowFunction(init)) {
2149
- const name = decl.name.getText();
2150
- return { func: init, name };
2151
- }
2152
- if (init && ts2__namespace.isFunctionExpression(init)) {
2153
- const name = decl.name.getText();
2154
- return { func: init, name };
2155
- }
2156
- }
2157
- }
2158
- return null;
2159
- }
2160
- function getJSDocHost(node) {
2161
- const parent = node.parent;
2162
- if (ts2__namespace.isVariableDeclaration(parent)) {
2163
- const gp = parent.parent;
2164
- if (ts2__namespace.isVariableDeclarationList(gp) && gp.parent && ts2__namespace.isVariableStatement(gp.parent)) return gp.parent;
2165
- }
2166
- return node;
2167
- }
2168
- function getJSDocComments(host) {
2169
- const all = ts2__namespace.getJSDocCommentsAndTags(host);
2170
- return all.filter((t) => ts2__namespace.isJSDoc(t));
2171
- }
2172
- function hasToolTag(host) {
2173
- const tags = ts2__namespace.getJSDocTags(host);
2174
- for (const tag of tags) {
2175
- const name = tag.tagName?.getText() ?? "";
2176
- if (name === "tool") return true;
2177
- }
2178
- const all = ts2__namespace.getJSDocCommentsAndTags(host);
2179
- for (const t of all) {
2180
- if (ts2__namespace.isJSDoc(t)) {
2181
- const full = t.getFullText();
2182
- if (full.includes(TOOL_TAG)) return true;
2183
- }
2184
- }
2185
- return false;
2186
- }
2187
- function getDescription(jsDocs, fallbackName) {
2188
- for (const doc of jsDocs) {
2189
- const comment = doc.comment;
2190
- if (typeof comment === "string") {
2191
- const first = comment.split(/\n/)[0]?.trim() ?? "";
2192
- if (first && !first.startsWith("@")) return first;
2193
- }
2194
- if (Array.isArray(comment)) {
2195
- const first = comment[0];
2196
- if (first && typeof first === "object" && "text" in first) {
2197
- const t = first.text.trim();
2198
- if (t && !t.startsWith("@")) return t;
2199
- }
2200
- }
2201
- const full = doc.getFullText();
2202
- const match = full.match(/\*\s*@tool\s+(.+?)(?=\n|$|\*\/)/s);
2203
- if (match?.[1]) return match[1].trim();
2204
- }
2205
- return "";
2206
- }
2207
- function getEffect(host) {
2208
- const tags = ts2__namespace.getJSDocTags(host);
2209
- for (const tag of tags) {
2210
- const name = tag.tagName?.getText() ?? "";
2211
- if (name === "effect") {
2212
- const comment = tag.comment;
2213
- const v = (typeof comment === "string" ? comment : "").trim().toLowerCase();
2214
- if (EFFECT_VALUES.includes(v)) return v;
2215
- }
2216
- }
2217
- const all = ts2__namespace.getJSDocCommentsAndTags(host);
2218
- for (const t of all) {
2219
- if (ts2__namespace.isJSDoc(t)) {
2220
- const full = t.getFullText();
2221
- const match = full.match(/\*\s*@effect\s+(\w+)/);
2222
- if (match && EFFECT_VALUES.includes(match[1])) return match[1];
2223
- }
2224
- }
2225
- return "none";
2226
- }
2227
- function humanize(name) {
2228
- return name.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()).trim();
2229
- }
2230
- function scan(projectPath, options = {}) {
2231
- const root = path__namespace.resolve(projectPath);
2232
- const result = scanForTools({
2233
- projectPath: root,
2234
- include: options.include ?? ["**/*.ts"],
2235
- tsconfigPath: options.tsconfigPath
2236
- });
2237
- const specs = result.specs.map((s) => mcpSpecToToolSpec(s, root));
2238
- return Promise.resolve({
2239
- specs,
2240
- errors: result.errors,
2241
- warnings: result.warnings
2242
- });
2243
- }
2244
- var DEFAULT_EXTENSIONS = [".js", ".mjs"];
2245
- async function resolveEntryPoint(dirPath, baseName, extensions = DEFAULT_EXTENSIONS) {
2246
- if (extensions.some((ext) => baseName.endsWith(ext))) {
2247
- const fullPath = path.join(dirPath, baseName);
2248
- await promises.stat(fullPath);
2249
- return fullPath;
2250
- }
2251
- for (const ext of extensions) {
2252
- const fullPath = path.join(dirPath, `${baseName}${ext}`);
2253
- try {
2254
- await promises.stat(fullPath);
2255
- return fullPath;
2256
- } catch {
2257
- }
2258
- }
2259
- throw new Error(
2260
- `Could not find entry point in ${dirPath}. Tried: ${extensions.map((e) => baseName + e).join(", ")}`
2261
- );
2262
- }
2263
-
2264
- // src/tools/skill/SkillManifest.ts
2265
- var SkillManifestError = class extends Error {
2266
- constructor(path7, field, message) {
2267
- super(`SKILL.md error in ${path7}: ${message}`);
2268
- this.path = path7;
2269
- this.field = field;
2270
- this.name = "SkillManifestError";
2271
- }
2272
- };
2273
- var NAME_PATTERN = /^[a-z0-9-]+$/;
2274
- var NAME_MAX_LENGTH = 64;
2275
- var DESCRIPTION_MAX_LENGTH = 1024;
2276
- var COMPATIBILITY_MAX_LENGTH = 500;
2277
- var RESERVED_WORDS = ["anthropic", "claude"];
2278
- var XML_TAG_PATTERN = /<\/?[a-zA-Z][^>]*>/;
2279
- function validateFrontmatter(fm, filePath) {
2280
- if (!fm.name || typeof fm.name !== "string") {
2281
- throw new SkillManifestError(filePath, "name", "name is required");
2282
- }
2283
- if (fm.name.length > NAME_MAX_LENGTH) {
2284
- throw new SkillManifestError(
2285
- filePath,
2286
- "name",
2287
- `name must be at most ${NAME_MAX_LENGTH} characters (got ${fm.name.length})`
2288
- );
2289
- }
2290
- if (!NAME_PATTERN.test(fm.name)) {
2291
- throw new SkillManifestError(
2292
- filePath,
2293
- "name",
2294
- "name must contain only lowercase letters, numbers, and hyphens"
2295
- );
2296
- }
2297
- if (fm.name.startsWith("-") || fm.name.endsWith("-")) {
2298
- throw new SkillManifestError(
2299
- filePath,
2300
- "name",
2301
- "name must not start or end with a hyphen"
2302
- );
2303
- }
2304
- if (fm.name.includes("--")) {
2305
- throw new SkillManifestError(
2306
- filePath,
2307
- "name",
2308
- "name must not contain consecutive hyphens"
2309
- );
2310
- }
2311
- if (XML_TAG_PATTERN.test(fm.name)) {
2312
- throw new SkillManifestError(filePath, "name", "name cannot contain XML tags");
2313
- }
2314
- for (const reserved of RESERVED_WORDS) {
2315
- if (fm.name.includes(reserved)) {
2316
- throw new SkillManifestError(
2317
- filePath,
2318
- "name",
2319
- `name cannot contain reserved word "${reserved}"`
2320
- );
2321
- }
2322
- }
2323
- if (!fm.description || typeof fm.description !== "string") {
2324
- throw new SkillManifestError(
2325
- filePath,
2326
- "description",
2327
- "description is required and must be non-empty"
2328
- );
2329
- }
2330
- if (fm.description.length > DESCRIPTION_MAX_LENGTH) {
2331
- throw new SkillManifestError(
2332
- filePath,
2333
- "description",
2334
- `description must be at most ${DESCRIPTION_MAX_LENGTH} characters (got ${fm.description.length})`
2335
- );
2336
- }
2337
- if (XML_TAG_PATTERN.test(fm.description)) {
2338
- throw new SkillManifestError(
2339
- filePath,
2340
- "description",
2341
- "description cannot contain XML tags"
2342
- );
2343
- }
2344
- if (fm.compatibility != null && typeof fm.compatibility === "string") {
2345
- if (fm.compatibility.length > COMPATIBILITY_MAX_LENGTH) {
2346
- throw new SkillManifestError(
2347
- filePath,
2348
- "compatibility",
2349
- `compatibility must be at most ${COMPATIBILITY_MAX_LENGTH} characters (got ${fm.compatibility.length})`
2350
- );
2351
- }
2352
- }
2353
- }
2354
-
2355
- // src/tools/skill/SkillMdParser.ts
2356
- var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
2357
- ".py",
2358
- ".js",
2359
- ".mjs",
2360
- ".ts",
2361
- ".sh",
2362
- ".bash",
2363
- ".rb",
2364
- ".go"
2365
- ]);
2366
- var INSTRUCTION_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt"]);
2367
- var EXCLUDED_FILES = /* @__PURE__ */ new Set(["SKILL.md", "tool.json"]);
2368
- function parseSkillMd(content, filePath) {
2369
- const trimmed = content.trimStart();
2370
- if (!trimmed.startsWith("---")) {
2371
- throw new SkillManifestError(
2372
- filePath,
2373
- "frontmatter",
2374
- "SKILL.md must start with YAML frontmatter (---)"
2375
- );
2376
- }
2377
- const endIndex = trimmed.indexOf("\n---", 3);
2378
- if (endIndex === -1) {
2379
- throw new SkillManifestError(
2380
- filePath,
2381
- "frontmatter",
2382
- "SKILL.md frontmatter is not closed (missing closing ---)"
2383
- );
2384
- }
2385
- const yamlBlock = trimmed.slice(4, endIndex).trim();
2386
- const body = trimmed.slice(endIndex + 4).trim();
2387
- let raw;
2388
- try {
2389
- const parsed = yaml__default.default.load(yamlBlock);
2390
- if (parsed == null || typeof parsed !== "object" || Array.isArray(parsed)) {
2391
- throw new SkillManifestError(
2392
- filePath,
2393
- "frontmatter",
2394
- "YAML frontmatter must be an object (key: value)"
2395
- );
2396
- }
2397
- raw = parsed;
2398
- } catch (err) {
2399
- const message = err instanceof Error ? err.message : String(err);
2400
- throw new SkillManifestError(
2401
- filePath,
2402
- "frontmatter",
2403
- `Invalid YAML frontmatter: ${message}`
2404
- );
2405
- }
2406
- const name = stringField(raw, "name", filePath);
2407
- const description = stringField(raw, "description", filePath);
2408
- if (!name || !description) {
2409
- throw new SkillManifestError(
2410
- filePath,
2411
- "frontmatter",
2412
- !name ? "name is required" : "description is required"
2413
- );
2414
- }
2415
- const license = stringField(raw, "license");
2416
- const compatibility = stringField(raw, "compatibility");
2417
- const allowedTools = stringField(raw, "allowed-tools");
2418
- const metadata = normalizeMetadata(raw.metadata);
2419
- const frontmatter = {
2420
- name,
2421
- description,
2422
- ...license && { license },
2423
- ...compatibility && { compatibility },
2424
- ...allowedTools && { allowedTools },
2425
- ...metadata && Object.keys(metadata).length > 0 && { metadata }
2426
- };
2427
- validateFrontmatter(frontmatter, filePath);
2428
- return { frontmatter, instructions: body };
2429
- }
2430
- function stringField(raw, key, filePath) {
2431
- const v = raw[key];
2432
- if (v == null) return "";
2433
- if (typeof v === "string") return v;
2434
- if (typeof v === "number" || typeof v === "boolean") return String(v);
2435
- if (Array.isArray(v)) {
2436
- return v.map((x) => typeof x === "string" ? x : String(x)).join("\n");
2437
- }
2438
- if (filePath) {
2439
- throw new SkillManifestError(
2440
- filePath,
2441
- "frontmatter",
2442
- `Frontmatter field "${key}" must be a string, number, boolean, or array`
2443
- );
2444
- }
2445
- return String(v);
2446
- }
2447
- function normalizeMetadata(val) {
2448
- if (val == null) return void 0;
2449
- if (typeof val === "object" && !Array.isArray(val)) {
2450
- const out = {};
2451
- for (const [k, v] of Object.entries(val)) {
2452
- if (typeof k === "string" && v !== void 0 && v !== null) {
2453
- out[k] = typeof v === "object" ? JSON.stringify(v) : String(v);
2454
- }
2455
- }
2456
- return Object.keys(out).length ? out : void 0;
2457
- }
2458
- if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
2459
- return { value: String(val) };
2460
- }
2461
- return void 0;
2462
- }
2463
- async function scanSkillResources(dirPath) {
2464
- const resources = [];
2465
- await scanDir(dirPath, dirPath, resources);
2466
- return resources;
2467
- }
2468
- async function scanDir(basePath, currentPath, resources) {
2469
- let entries;
2470
- try {
2471
- entries = await promises.readdir(currentPath, { withFileTypes: true });
2472
- } catch {
2473
- return;
2474
- }
2475
- for (const entry of entries) {
2476
- const fullPath = path.join(currentPath, entry.name);
2477
- if (entry.isDirectory()) {
2478
- if (entry.name.startsWith(".") || entry.name === "node_modules") {
2479
- continue;
2480
- }
2481
- await scanDir(basePath, fullPath, resources);
2482
- } else if (entry.isFile()) {
2483
- if (EXCLUDED_FILES.has(entry.name)) {
2484
- continue;
2485
- }
2486
- const ext = path.extname(entry.name).toLowerCase();
2487
- const relPath = path.relative(basePath, fullPath);
2488
- resources.push({
2489
- relativePath: relPath,
2490
- absolutePath: fullPath,
2491
- extension: ext,
2492
- type: inferResourceType(ext)
2493
- });
2494
- }
2495
- }
2496
- }
2497
- function inferResourceType(ext) {
2498
- if (CODE_EXTENSIONS.has(ext)) return "code";
2499
- if (INSTRUCTION_EXTENSIONS.has(ext)) return "instructions";
2500
- return "data";
2501
- }
2502
- async function loadSkillDefinition(dirPath) {
2503
- const skillMdPath = path.join(dirPath, "SKILL.md");
2504
- let content;
2505
- try {
2506
- content = await promises.readFile(skillMdPath, "utf-8");
2507
- } catch (err) {
2508
- throw new SkillManifestError(
2509
- skillMdPath,
2510
- "file",
2511
- `Cannot read SKILL.md: ${err.message}`
2512
- );
2513
- }
2514
- const { frontmatter, instructions } = parseSkillMd(content, skillMdPath);
2515
- const resources = await scanSkillResources(dirPath);
2516
- return {
2517
- frontmatter,
2518
- instructions,
2519
- resources,
2520
- dirPath,
2521
- skillMdPath
2522
- };
2523
- }
2524
-
2525
- // src/tools/skill/scanSkill.ts
2526
- var defaultInputSchema = { type: "object", properties: {}, additionalProperties: true };
2527
- async function scanForSkill(projectPath) {
2528
- const projectRoot = path__namespace.resolve(projectPath);
2529
- const dirs = await findDirsContainingFile(projectRoot, "SKILL.md");
2530
- const skills = [];
2531
- const errors = [];
2532
- for (const dirPath of dirs) {
2533
- const relativePath = path__namespace.relative(projectRoot, dirPath) || path__namespace.basename(dirPath);
2534
- try {
2535
- const skillDef = await loadSkillDefinition(dirPath);
2536
- const name = pathToToolName(relativePath, skillDef.frontmatter.name);
2537
- skills.push({
2538
- kind: SKILL_KIND,
2539
- name,
2540
- description: skillDef.frontmatter.description,
2541
- inputSchema: defaultInputSchema,
2542
- _meta: { hitl: { sideEffect: "none" } },
2543
- sourcePath: relativePath.replace(/\\/g, "/")
2544
- });
2545
- } catch (err) {
2546
- errors.push({ dir: relativePath, message: err instanceof Error ? err.message : String(err) });
2547
- }
2548
- }
2549
- return { skills, errors };
2550
- }
2551
- async function scan2(projectPath, _options = {}) {
2552
- const root = path__namespace.resolve(projectPath);
2553
- const result = await scanForSkill(root);
2554
- const specs = result.skills.map((s) => mcpSpecToToolSpec(s, root));
2555
- return {
2556
- specs,
2557
- errors: result.errors.map((e) => ({ file: e.dir, message: e.message }))
2558
- };
2559
- }
2560
- async function readWorkflowMeta(dirPath, workflowFileName = "workflow.json") {
2561
- const workflowPath = path.join(dirPath, workflowFileName);
2562
- let raw;
2563
- try {
2564
- raw = await promises.readFile(workflowPath, "utf-8");
2565
- } catch (err) {
2566
- throw new DiscoveryError(
2567
- dirPath,
2568
- "load",
2569
- `Failed to read workflow: ${workflowPath}`,
2570
- err
2571
- );
2572
- }
2573
- let workflowDef;
2574
- try {
2575
- workflowDef = JSON.parse(raw);
2576
- } catch (err) {
2577
- throw new DiscoveryError(
2578
- dirPath,
2579
- "load",
2580
- `Invalid JSON in ${workflowPath}`,
2581
- err
2582
- );
2583
- }
2584
- if (!workflowDef.nodes || !Array.isArray(workflowDef.nodes)) {
2585
- throw new DiscoveryError(
2586
- dirPath,
2587
- "validate",
2588
- `workflow.json must have a "nodes" array`
2589
- );
2590
- }
2591
- const meta = workflowDef.meta;
2592
- const name = workflowDef.name || meta?.name || path.basename(dirPath);
2593
- const description = workflowDef.description || meta?.description || `n8n workflow: ${name}`;
2594
- let webhookUrl;
2595
- const nodes = workflowDef.nodes;
2596
- if (Array.isArray(nodes)) {
2597
- const webhookNode = nodes.find(
2598
- (n) => n.type === "n8n-nodes-base.webhook" || n.type?.includes("webhook")
2599
- );
2600
- if (webhookNode?.parameters && typeof webhookNode.parameters === "object") {
2601
- const params = webhookNode.parameters;
2602
- const pathVal = params.path ?? params.webhookPath;
2603
- if (typeof pathVal === "string" && pathVal.startsWith("http")) {
2604
- webhookUrl = pathVal;
2605
- }
2606
- }
2607
- }
2608
- return { name, description, webhookUrl, workflowDef };
2609
- }
2610
- async function loadN8nTool(dirPath, manifest) {
2611
- const { workflowDef } = await readWorkflowMeta(
2612
- dirPath,
2613
- manifest.entryPoint ?? "workflow.json"
2614
- );
2615
- return { manifest, dirPath, workflowDef };
2616
- }
2617
-
2618
- // src/tools/n8n/scanN8n.ts
2619
- var defaultInputSchema2 = { type: "object", properties: {}, additionalProperties: true };
2620
- async function scanForN8n(projectPath) {
2621
- const projectRoot = path__namespace.resolve(projectPath);
2622
- const dirs = await findDirsContainingFile(projectRoot, "workflow.json");
2623
- const n8n = [];
2624
- const errors = [];
2625
- for (const dirPath of dirs) {
2626
- const relativePath = path__namespace.relative(projectRoot, dirPath) || path__namespace.basename(dirPath);
2627
- try {
2628
- const { name: wfName, description: wfDesc, webhookUrl } = await readWorkflowMeta(dirPath);
2629
- const toolName = pathToToolName(relativePath, wfName);
2630
- n8n.push({
2631
- kind: N8N_KIND,
2632
- name: toolName,
2633
- description: wfDesc,
2634
- inputSchema: defaultInputSchema2,
2635
- _meta: { hitl: { sideEffect: "external_write" } },
2636
- sourcePath: relativePath.replace(/\\/g, "/"),
2637
- webhookUrl
2638
- });
2639
- } catch (err) {
2640
- errors.push({ dir: relativePath, message: err instanceof Error ? err.message : String(err) });
2641
- }
2642
- }
2643
- return { n8n, errors };
2644
- }
2645
- async function scan3(projectPath, _options = {}) {
2646
- const root = path__namespace.resolve(projectPath);
2647
- const result = await scanForN8n(root);
2648
- const specs = result.n8n.map((s) => mcpSpecToToolSpec(s, root));
2649
- return {
2650
- specs,
2651
- errors: result.errors.map((e) => ({ file: e.dir, message: e.message }))
2652
- };
2653
- }
2654
-
2655
- // src/tools/mcp/types.ts
2656
- var MCP_KIND = "mcp";
2657
-
2658
- // src/tools/mcp/scanner.ts
2659
- async function scan4(projectPath, options = {}) {
2660
- const root = path__namespace.resolve(projectPath);
2661
- const namespace = options.namespace ?? "dir";
2662
- const errors = [];
2663
- const scanner = new DirectoryScanner({
2664
- roots: [root],
2665
- namespace,
2666
- extensions: options.extensions,
2667
- onError: (dir, err) => {
2668
- errors.push({ file: dir, message: err.message });
2669
- options.onError?.(dir, err);
2670
- }
2671
- });
2672
- let specs;
2673
- try {
2674
- specs = await scanner.scan();
2675
- } catch (err) {
2676
- errors.push({
2677
- file: root,
2678
- message: err instanceof Error ? err.message : String(err)
2679
- });
2680
- return { specs: [], errors };
2681
- }
2682
- const filtered = specs.filter((s) => s.kind === MCP_KIND);
2683
- return { specs: filtered, errors };
2684
- }
2685
-
2686
- // src/tools/langchain/types.ts
2687
- var LANGCHAIN_KIND = "langchain";
2688
- var LANGCHAIN_DIR_NAME = "langchain";
2689
-
2690
- // src/tools/langchain/scanner.ts
2691
- async function scan5(projectPath, options = {}) {
2692
- const root = path__namespace.resolve(projectPath);
2693
- const namespace = options.namespace ?? "dir";
2694
- const errors = [];
2695
- const scanner = new DirectoryScanner({
2696
- roots: [root],
2697
- namespace,
2698
- extensions: options.extensions,
2699
- onError: (dir, err) => {
2700
- errors.push({ file: dir, message: err.message });
2701
- options.onError?.(dir, err);
2702
- }
2703
- });
2704
- let specs;
2705
- try {
2706
- specs = await scanner.scan();
2707
- } catch (err) {
2708
- errors.push({
2709
- file: root,
2710
- message: err instanceof Error ? err.message : String(err)
2711
- });
2712
- return { specs: [], errors };
2713
- }
2714
- const filtered = specs.filter((s) => s.kind === LANGCHAIN_KIND);
2715
- return { specs: filtered, errors };
2716
- }
2717
- async function loadLangChainTool(dirPath, manifest, extensions) {
2718
- let entryFile;
2719
- try {
2720
- entryFile = await resolveEntryPoint(
2721
- dirPath,
2722
- manifest.entryPoint ?? "index",
2723
- extensions
2724
- );
2725
- } catch (err) {
2726
- throw new DiscoveryError(
2727
- dirPath,
2728
- "load",
2729
- `Cannot find LangChain entry point`,
2730
- err
2731
- );
2732
- }
2733
- let mod;
2734
- try {
2735
- mod = await import(url.pathToFileURL(entryFile).href);
2736
- } catch (err) {
2737
- throw new DiscoveryError(
2738
- dirPath,
2739
- "load",
2740
- `Failed to import ${entryFile}`,
2741
- err
2742
- );
2743
- }
2744
- const tool = mod.default ?? mod.tool ?? mod;
2745
- if (!tool || typeof tool.invoke !== "function") {
2746
- throw new DiscoveryError(
2747
- dirPath,
2748
- "validate",
2749
- `Entry point must export an object with invoke() method (LangChainToolLike)`
2750
- );
2751
- }
2752
- return { manifest, dirPath, impl: tool };
2753
- }
2754
- var DEFAULT_EXTENSIONS2 = [".js", ".mjs"];
2755
- async function listSkillProgramFiles(dirPath, extensions = DEFAULT_EXTENSIONS2) {
2756
- let entries;
2757
- try {
2758
- const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
2759
- entries = dirEntries.map((entry) => ({
2760
- name: entry.name,
2761
- isFile: entry.isFile()
2762
- }));
2763
- } catch {
2764
- return [];
2765
- }
2766
- return entries.filter((e) => e.isFile).map((e) => e.name).filter((name) => {
2767
- if (name.startsWith(".") || name.startsWith("_")) return false;
2768
- if (name.includes(".test.") || name.includes(".spec.")) return false;
2769
- return extensions.some((ext) => name.endsWith(ext));
2770
- }).sort((a, b) => {
2771
- if (a === "handler.js" || a === "index.js") return -1;
2772
- if (b === "handler.js" || b === "index.js") return 1;
2773
- return a.localeCompare(b);
2774
- });
2775
- }
2776
- function isLangChainLikeTool(val) {
2777
- return val != null && typeof val === "object" && "invoke" in val && typeof val.invoke === "function";
2778
- }
2779
- function isConstructable(val) {
2780
- return typeof val === "function" && typeof val.prototype === "object";
2781
- }
2782
- async function loadOneSkillProgram(dirPath, manifest, entryFile, skillDef, programKey, extensions) {
2783
- let impl;
2784
- try {
2785
- const fullPath = await resolveEntryPoint(dirPath, entryFile, extensions ?? [".js", ".mjs"]);
2786
- const mod = await import(url.pathToFileURL(fullPath).href);
2787
- const fn = mod.default ?? mod.handler ?? mod.Tool;
2788
- if (isLangChainLikeTool(fn)) {
2789
- impl = fn;
2790
- } else if (isConstructable(fn)) {
2791
- const instance = new fn();
2792
- if (isLangChainLikeTool(instance)) impl = instance;
2793
- } else if (typeof fn === "function") {
2794
- impl = fn;
2795
- }
2796
- } catch {
2797
- }
2798
- return {
2799
- manifest,
2800
- dirPath,
2801
- impl,
2802
- skillDefinition: skillDef,
2803
- programKey
2804
- };
2805
- }
2806
- async function loadSkillTools(dirPath, manifest, extensions) {
2807
- let skillDef;
2808
- try {
2809
- skillDef = await loadSkillDefinition(dirPath);
2810
- } catch (err) {
2811
- throw new DiscoveryError(
2812
- dirPath,
2813
- "load",
2814
- `Failed to parse SKILL.md: ${err.message}`,
2815
- err
2816
- );
2817
- }
2818
- const programs = manifest.programs;
2819
- if (programs && typeof programs === "object" && Object.keys(programs).length > 0) {
2820
- const result = [];
2821
- for (const [programKey, entryFile2] of Object.entries(programs)) {
2822
- const loaded2 = await loadOneSkillProgram(
2823
- dirPath,
2824
- manifest,
2825
- entryFile2,
2826
- skillDef,
2827
- programKey,
2828
- extensions
2829
- );
2830
- result.push(loaded2);
2831
- }
2832
- return result;
2833
- }
2834
- const exts = extensions ?? DEFAULT_EXTENSIONS2;
2835
- const files = await listSkillProgramFiles(dirPath, exts);
2836
- if (files.length >= 2) {
2837
- const result = [];
2838
- for (let i = 0; i < files.length; i++) {
2839
- const file = files[i];
2840
- const programKey = i === 0 ? "default" : file.replace(/\.[^.]+$/, "");
2841
- const loaded2 = await loadOneSkillProgram(
2842
- dirPath,
2843
- manifest,
2844
- file,
2845
- skillDef,
2846
- programKey,
2847
- extensions
2848
- );
2849
- result.push(loaded2);
2850
- }
2851
- return result;
2852
- }
2853
- const entryFile = manifest.entryPoint ?? files[0] ?? "handler";
2854
- const loaded = await loadOneSkillProgram(
2855
- dirPath,
2856
- manifest,
2857
- entryFile,
2858
- skillDef,
2859
- void 0,
2860
- extensions
2861
- );
2862
- return [loaded];
2863
- }
2864
- async function listLangchainEntryFiles(dirPath, extensions) {
2865
- let entries;
2866
- try {
2867
- const dirEntries = await promises.readdir(dirPath, { withFileTypes: true });
2868
- entries = dirEntries.map((entry) => ({
2869
- name: entry.name,
2870
- isFile: entry.isFile()
2871
- }));
2872
- } catch {
2873
- return [];
2874
- }
2875
- return entries.filter((e) => e.isFile).map((e) => e.name).filter((name) => {
2876
- if (name.startsWith(".") || name.startsWith("_")) return false;
2877
- if (name.endsWith(".d.ts")) return false;
2878
- if (name.includes(".test.") || name.includes(".spec.")) return false;
2879
- return extensions.some((ext) => name.endsWith(ext));
2880
- });
2881
- }
2882
- async function loadLangChainToolsFromDir(dirPath, dirName, manifest, strict, namespace, extensions, langchainDirName, toSpec, onError) {
2883
- const entryFiles = await listLangchainEntryFiles(dirPath, extensions);
2884
- if (entryFiles.length === 0) {
2885
- if (strict) {
2886
- throw new DiscoveryError(dirPath, "load", "No LangChain entry files found");
2887
- }
2888
- return [];
2889
- }
2890
- const specs = [];
2891
- const useDirNameForSingle = dirName !== langchainDirName;
2892
- for (const entryFile of entryFiles) {
2893
- const fileManifest = { ...manifest, entryPoint: entryFile };
2894
- try {
2895
- const loaded = await loadLangChainTool(dirPath, fileManifest, extensions);
2896
- const fileBase = path.basename(entryFile).replace(/\.[^.]+$/, "");
2897
- const nameHint = entryFiles.length === 1 && useDirNameForSingle ? dirName : fileBase;
2898
- specs.push(toSpec(loaded, nameHint, dirPath, namespace));
2899
- } catch (error) {
2900
- const err = error;
2901
- if (err instanceof DiscoveryError && err.phase === "validate") {
2902
- if (strict) throw err;
2903
- continue;
2904
- }
2905
- onError?.(path.join(dirPath, entryFile), err);
2906
- if (strict) throw err;
2907
- }
2908
- }
2909
- return specs;
2910
- }
2911
- function isCursorFormat(obj) {
2912
- return typeof obj === "object" && obj !== null && "mcpServers" in obj && typeof obj.mcpServers === "object" && obj.mcpServers !== null;
2913
- }
2914
- function extractMCPConfig(parsed, toolName) {
2915
- if (isCursorFormat(parsed)) {
2916
- const servers = parsed.mcpServers;
2917
- const keys = Object.keys(servers);
2918
- if (keys.length === 0) {
2919
- return {};
2920
- }
2921
- const name = toolName && keys.includes(toolName) ? toolName : keys[0];
2922
- return servers[name];
2923
- }
2924
- return parsed;
2925
- }
2926
- async function loadMCPTool(dirPath, manifest) {
2927
- const mcpPath = path.join(dirPath, manifest.entryPoint ?? "mcp.json");
2928
- let raw;
2929
- try {
2930
- raw = await promises.readFile(mcpPath, "utf-8");
2931
- } catch (err) {
2932
- throw new DiscoveryError(
2933
- dirPath,
2934
- "load",
2935
- `Failed to read MCP config: ${mcpPath}`,
2936
- err
2937
- );
2938
- }
2939
- let parsed;
2940
- try {
2941
- parsed = JSON.parse(raw);
2942
- } catch (err) {
2943
- throw new DiscoveryError(
2944
- dirPath,
2945
- "load",
2946
- `Invalid JSON in ${mcpPath}`,
2947
- err
2948
- );
2949
- }
2950
- const baseName = manifest.name?.split("/").pop();
2951
- const config = extractMCPConfig(parsed, baseName);
2952
- if (!config.command && !config.url) {
2953
- throw new DiscoveryError(
2954
- dirPath,
2955
- "validate",
2956
- `mcp.json must have either "command" or "url" field`
2957
- );
2958
- }
2959
- return { manifest, dirPath, mcpConfig: config };
2960
- }
2961
-
2962
- // src/tools/mcp/directoryApply.ts
2963
- function applyLoadedToSpec(spec, loaded, _manifest, _defaultDirName, _namespace) {
2964
- if (loaded.mcpConfig?.url) spec.endpoint = loaded.mcpConfig.url;
2965
- spec.impl = loaded.mcpConfig;
2966
- }
2967
- var directoryMarker = {
2968
- kind: "mcp",
2969
- markerFile: "mcp.json",
2970
- defaultEntryPoint: "mcp.json"
2971
- };
2972
-
2973
- // src/tools/langchain/directoryApply.ts
2974
- function applyLoadedToSpec2(spec, loaded, manifest, _defaultDirName, namespace) {
2975
- spec.impl = loaded.impl;
2976
- if (!manifest.name && loaded.impl) {
2977
- const toolName = loaded.impl.name;
2978
- if (toolName) spec.name = `${namespace}/${toolName}`;
2979
- }
2980
- if (!manifest.description && loaded.impl) {
2981
- const d = loaded.impl.description;
2982
- if (d) spec.description = d;
2983
- }
2984
- if (!manifest.inputSchema && loaded.impl) {
2985
- const schema = loaded.impl.schema;
2986
- if (schema) spec.inputSchema = schema;
2987
- }
2988
- }
2989
-
2990
- // src/tools/skill/directoryApply.ts
2991
- function applyLoadedToSpec3(spec, loaded, manifest, defaultDirName, namespace) {
2992
- const skillDef = loaded.skillDefinition;
2993
- if (skillDef) {
2994
- spec.name = manifest.name ?? skillDef.frontmatter.name;
2995
- spec.description = skillDef.frontmatter.description;
2996
- if (loaded.programKey === "default") {
2997
- spec.name = `${namespace}/${defaultDirName}`;
2998
- } else if (loaded.programKey) {
2999
- spec.name = `${namespace}/${defaultDirName}/${loaded.programKey}`;
3000
- }
3001
- const impl = loaded.impl;
3002
- if (impl && typeof impl === "object" && typeof impl.invoke === "function") {
3003
- if (impl.description != null && impl.description !== "")
3004
- spec.description = impl.description;
3005
- if (impl.schema != null && typeof impl.schema === "object")
3006
- spec.inputSchema = impl.schema;
3007
- }
3008
- spec.impl = { ...skillDef, handler: loaded.impl };
3009
- } else {
3010
- spec.impl = loaded.impl;
3011
- }
3012
- }
3013
- var directoryMarker2 = {
3014
- kind: "skill",
3015
- markerFile: "SKILL.md",
3016
- defaultEntryPoint: "handler"
3017
- };
3018
-
3019
- // src/tools/n8n/directoryApply.ts
3020
- function applyLoadedToSpec4(spec, loaded, manifest, _defaultDirName, _namespace) {
3021
- const workflow = loaded.workflowDef;
3022
- if (workflow?.id) spec.resourceId = String(workflow.id);
3023
- if (!manifest.description && workflow) {
3024
- const d = workflow.description ?? workflow.meta?.description ?? (typeof workflow.name === "string" ? workflow.name : void 0);
3025
- if (d) spec.description = d;
3026
- }
3027
- spec.impl = loaded.workflowDef;
3028
- }
3029
- var directoryMarker3 = {
3030
- kind: "n8n",
3031
- markerFile: "workflow.json",
3032
- defaultEntryPoint: "workflow.json"
3033
- };
3034
-
3035
- // src/tools/discoveryFactory.ts
3036
- var DiscoveryError = class extends Error {
3037
- toolDir;
3038
- phase;
3039
- cause;
3040
- constructor(toolDir, phase, message, cause) {
3041
- super(`[${phase}] ${toolDir}: ${message}`);
3042
- this.name = "DiscoveryError";
3043
- this.toolDir = toolDir;
3044
- this.phase = phase;
3045
- this.cause = cause;
3046
- }
3047
- };
3048
- var DIRECTORY_KINDS = ["mcp", "langchain", "skill", "n8n"];
3049
- var DIRECTORY_DISCOVERABLE_KINDS = DIRECTORY_KINDS;
3050
- var DIRECTORY_KIND_MARKERS = [
3051
- directoryMarker2,
3052
- directoryMarker3,
3053
- directoryMarker
3054
- ];
3055
- var DIRECTORY_LOADERS = {
3056
- mcp: async (dirPath, manifest) => [await loadMCPTool(dirPath, manifest)],
3057
- langchain: async (dirPath, manifest, ext) => [await loadLangChainTool(dirPath, manifest, ext)],
3058
- skill: (dirPath, manifest, ext) => loadSkillTools(dirPath, manifest, ext),
3059
- n8n: async (dirPath, manifest) => [await loadN8nTool(dirPath, manifest)]
3060
- };
3061
- function getDirectoryLoader(kind) {
3062
- const loader = DIRECTORY_LOADERS[kind];
3063
- if (!loader) {
3064
- throw new DiscoveryError("", "manifest", `Unknown directory tool kind: "${kind}"`);
3065
- }
3066
- return loader;
3067
- }
3068
- function applyDirectoryLoadedToSpec(spec, loaded, manifest, defaultDirName, namespace) {
3069
- switch (manifest.kind) {
3070
- case "mcp":
3071
- return applyLoadedToSpec(spec, loaded);
3072
- case "langchain":
3073
- return applyLoadedToSpec2(spec, loaded, manifest, defaultDirName, namespace);
3074
- case "skill":
3075
- return applyLoadedToSpec3(spec, loaded, manifest, defaultDirName, namespace);
3076
- case "n8n":
3077
- return applyLoadedToSpec4(spec, loaded, manifest);
3078
- }
3079
- }
3080
- async function discoverTools(type, projectPath, options = {}) {
3081
- const root = path__namespace.resolve(projectPath);
3082
- switch (type) {
3083
- case "function":
3084
- return scan(root, options);
3085
- case "skill":
3086
- return scan2(root, options);
3087
- case "n8n":
3088
- return scan3(root, options);
3089
- case "mcp":
3090
- return scan4(root, options);
3091
- case "langchain":
3092
- return scan5(root, options);
3093
- default: {
3094
- const _ = type;
3095
- return _;
3096
- }
3097
- }
3098
- }
3099
- var DEFAULT_EXTENSIONS3 = [".js", ".mjs"];
3100
- var DirectoryScanner = class {
3101
- roots;
3102
- extensions;
3103
- onError;
3104
- constructor(options) {
3105
- const defaultNamespace = options.namespace ?? "dir";
3106
- this.roots = options.roots.map((root) => {
3107
- if (typeof root === "string") {
3108
- return { path: root, namespace: defaultNamespace };
3109
- }
3110
- return {
3111
- path: root.path,
3112
- namespace: root.namespace ?? defaultNamespace
3113
- };
3114
- });
3115
- this.extensions = options.extensions ?? DEFAULT_EXTENSIONS3;
3116
- this.onError = options.onError;
3117
- }
3118
- async scan() {
3119
- const specs = [];
3120
- for (const root of this.roots) {
3121
- const rootSpecs = await this.scanRoot(root.path, root.namespace);
3122
- specs.push(...rootSpecs);
3123
- }
3124
- return specs;
3125
- }
3126
- async scanRoot(rootPath, namespace) {
3127
- return this.scanRecursive(rootPath, namespace);
3128
- }
3129
- async scanRecursive(dirPath, namespace) {
3130
- const specs = [];
3131
- let dirEntries;
3132
- try {
3133
- const entries = await promises.readdir(dirPath, { withFileTypes: true });
3134
- dirEntries = entries.map((entry) => ({
3135
- name: entry.name,
3136
- isDirectory: entry.isDirectory()
3137
- }));
3138
- } catch (error) {
3139
- this.onError?.(dirPath, error);
3140
- return specs;
3141
- }
3142
- const dirName = path.basename(dirPath);
3143
- try {
3144
- const loadedSpecs = await this.loadToolDir(dirPath, dirName, namespace);
3145
- if (loadedSpecs.length > 0) specs.push(...loadedSpecs);
3146
- } catch (error) {
3147
- this.onError?.(dirPath, error);
3148
- }
3149
- for (const entry of dirEntries) {
3150
- if (!entry.isDirectory) continue;
3151
- const childPath = path.join(dirPath, entry.name);
3152
- try {
3153
- const childSpecs = await this.scanRecursive(childPath, namespace);
3154
- specs.push(...childSpecs);
3155
- } catch (error) {
3156
- this.onError?.(childPath, error);
3157
- }
3158
- }
3159
- return specs;
3160
- }
3161
- async loadToolDir(dirPath, dirName, namespace) {
3162
- const manifestPath = path.join(dirPath, "tool.json");
3163
- let manifestRaw;
3164
- try {
3165
- manifestRaw = await promises.readFile(manifestPath, "utf-8");
3166
- } catch {
3167
- const inferred = await this.inferManifest(dirPath, dirName);
3168
- if (!inferred) return [];
3169
- if (inferred.kind === "langchain") {
3170
- if (inferred.entryPoint) {
3171
- const loaded3 = await loadLangChainTool(dirPath, inferred, this.extensions);
3172
- return [this.toToolSpec(loaded3, dirName, dirPath, namespace)];
3173
- }
3174
- return loadLangChainToolsFromDir(
3175
- dirPath,
3176
- dirName,
3177
- inferred,
3178
- false,
3179
- namespace,
3180
- this.extensions,
3181
- LANGCHAIN_DIR_NAME,
3182
- (loaded3, nameHint, dp, ns) => this.toToolSpec(loaded3, nameHint, dp, ns),
3183
- this.onError
3184
- );
3185
- }
3186
- if (inferred.kind === "skill") {
3187
- const loadedList = await loadSkillTools(dirPath, inferred, this.extensions);
3188
- return loadedList.map(
3189
- (loaded3) => this.toToolSpec(loaded3, dirName, dirPath, namespace)
3190
- );
3191
- }
3192
- const loaded2 = await this.loadByKind(dirPath, inferred);
3193
- return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
3194
- }
3195
- let manifest;
3196
- try {
3197
- manifest = JSON.parse(manifestRaw);
3198
- } catch (err) {
3199
- throw new DiscoveryError(dirPath, "manifest", "Invalid JSON in tool.json", err);
3200
- }
3201
- if (!manifest.kind) {
3202
- throw new DiscoveryError(dirPath, "manifest", `tool.json must have a "kind" field`);
3203
- }
3204
- if (manifest.enabled === false) return [];
3205
- if (manifest.kind === "langchain") {
3206
- if (manifest.entryPoint) {
3207
- const loaded2 = await loadLangChainTool(dirPath, manifest, this.extensions);
3208
- return [this.toToolSpec(loaded2, dirName, dirPath, namespace)];
3209
- }
3210
- return loadLangChainToolsFromDir(
3211
- dirPath,
3212
- dirName,
3213
- manifest,
3214
- true,
3215
- namespace,
3216
- this.extensions,
3217
- LANGCHAIN_DIR_NAME,
3218
- (loaded2, nameHint, dp, ns) => this.toToolSpec(loaded2, nameHint, dp, ns),
3219
- this.onError
3220
- );
3221
- }
3222
- if (manifest.kind === "skill") {
3223
- const loadedList = await loadSkillTools(dirPath, manifest, this.extensions);
3224
- return loadedList.map(
3225
- (loaded2) => this.toToolSpec(loaded2, dirName, dirPath, namespace)
3226
- );
3227
- }
3228
- const loaded = await this.loadByKind(dirPath, manifest);
3229
- return [this.toToolSpec(loaded, dirName, dirPath, namespace)];
3230
- }
3231
- async inferManifest(dirPath, dirName) {
3232
- const kinds = [];
3233
- for (const m of DIRECTORY_KIND_MARKERS) {
3234
- if (await this.fileExists(path.join(dirPath, m.markerFile))) kinds.push(m.kind);
3235
- }
3236
- const isLangchainDir = dirName === LANGCHAIN_DIR_NAME;
3237
- const hasLangchain = isLangchainDir ? (await listLangchainEntryFiles(dirPath, this.extensions)).length > 0 : dirName !== SKILL_DIR_NAME && await this.hasEntryPoint(dirPath, "index");
3238
- if (hasLangchain) kinds.push("langchain");
3239
- if (kinds.length === 0) return null;
3240
- if (kinds.length > 1) {
3241
- throw new DiscoveryError(
3242
- dirPath,
3243
- "manifest",
3244
- `Ambiguous tool kind (found ${kinds.join(", ")}). Add tool.json to disambiguate.`
3245
- );
3246
- }
3247
- const kind = kinds[0];
3248
- const manifest = { kind };
3249
- const marker = DIRECTORY_KIND_MARKERS.find((m) => m.kind === kind);
3250
- if (marker) {
3251
- manifest.entryPoint = marker.defaultEntryPoint;
3252
- }
3253
- if (kind === "langchain" && !isLangchainDir) manifest.entryPoint = "index";
3254
- return manifest;
3255
- }
3256
- async fileExists(path7) {
3257
- try {
3258
- await promises.access(path7);
3259
- return true;
3260
- } catch {
3261
- return false;
3262
- }
3263
- }
3264
- async hasEntryPoint(dirPath, baseName) {
3265
- try {
3266
- await resolveEntryPoint(dirPath, baseName, this.extensions);
3267
- return true;
3268
- } catch {
3269
- return false;
3270
- }
3271
- }
3272
- async loadByKind(dirPath, manifest) {
3273
- const kind = manifest.kind;
3274
- const loader = getDirectoryLoader(kind);
3275
- const result = await loader(dirPath, manifest, this.extensions);
3276
- const list = Array.isArray(result) ? result : [result];
3277
- if (list.length === 0) {
3278
- throw new DiscoveryError(dirPath, "load", "No tools loaded", new Error("empty"));
3279
- }
3280
- return list[0];
3281
- }
3282
- toToolSpec(loaded, dirName, dirPath, namespace) {
3283
- const { manifest } = loaded;
3284
- const kindDirNames = new Set(DIRECTORY_DISCOVERABLE_KINDS);
3285
- const parentName = path.basename(path.join(dirPath, ".."));
3286
- const isKindDir = kindDirNames.has(dirName);
3287
- const defaultDirName = isKindDir ? parentName : dirName;
3288
- const inferredName = isKindDir ? `${namespace}/${defaultDirName}-${dirName}` : `${namespace}/${defaultDirName}`;
3289
- const name = manifest.name ?? inferredName;
3290
- const spec = this.buildBaseSpec(manifest, name, dirName);
3291
- applyDirectoryLoadedToSpec(spec, loaded, manifest, defaultDirName, namespace);
3292
- return spec;
3293
- }
3294
- buildBaseSpec(manifest, name, dirName) {
3295
- return {
3296
- name,
3297
- version: manifest.version ?? "1.0.0",
3298
- kind: manifest.kind,
3299
- description: manifest.description ?? `${manifest.kind} tool: ${dirName}`,
3300
- tags: manifest.tags,
3301
- inputSchema: manifest.inputSchema ?? { type: "object", additionalProperties: true },
3302
- outputSchema: manifest.outputSchema ?? { type: "object", additionalProperties: true },
3303
- capabilities: manifest.capabilities ?? [],
3304
- costHints: manifest.costHints
3305
- };
3306
- }
3307
- };
3308
1729
 
3309
1730
  // src/api/runtimeFromConfig.ts
3310
- var requireFromPackage = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-JXYANBTH.cjs', document.baseURI).href)));
1731
+ var requireFromPackage = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-HK4GTFTQ.cjs', document.baseURI).href)));
3311
1732
  function getProjectRequire() {
3312
1733
  const cwd = process.cwd();
3313
1734
  if (fs.existsSync(path.join(cwd, "package.json"))) return module$1.createRequire(path.join(cwd, "package.json"));
@@ -3501,11 +1922,11 @@ function parseNpmDescriptor(entry) {
3501
1922
  }
3502
1923
  function loadExtensionFromFileDescriptorSync(descriptor, configFilePath, stepLog) {
3503
1924
  const entryStr = descriptor.trim();
3504
- const path7 = parseToolPath(entryStr);
3505
- if (!path7 || path7.protocol !== "file") return null;
1925
+ const path$1 = parseToolPath(entryStr);
1926
+ if (!path$1 || path$1.protocol !== "file") return null;
3506
1927
  const localPath = path.isAbsolute(configFilePath) ? configFilePath : path.resolve(process.cwd(), configFilePath);
3507
1928
  const configDir = path.dirname(localPath);
3508
- const pathPart = `${path7.scope}/${path7.packageWithVersion}`;
1929
+ const pathPart = `${path$1.scope}/${path$1.packageWithVersion}`;
3509
1930
  const resolvedPath = path.resolve(configDir, pathPart);
3510
1931
  if (!fs.existsSync(resolvedPath) || !fs.statSync(resolvedPath).isDirectory()) return null;
3511
1932
  try {
@@ -3653,7 +2074,7 @@ async function loadLocalDirectoryForFileDescriptor(descriptor, configFilePath, s
3653
2074
  if (!resolvedPath || !fs.existsSync(resolvedPath) || !fs.statSync(resolvedPath).isDirectory()) return null;
3654
2075
  if (fs.existsSync(path.join(resolvedPath, "package.json"))) return null;
3655
2076
  const scanErrors = [];
3656
- const scanner = new DirectoryScanner({
2077
+ const scanner = new chunkOG5ZSXQ5_cjs.DirectoryScanner({
3657
2078
  roots: [{ path: resolvedPath, namespace: "local" }],
3658
2079
  onError: (toolDir, error) => scanErrors.push(`${toolDir}: ${error.message}`)
3659
2080
  });
@@ -3697,9 +2118,9 @@ async function loadAllExtensionsFromToolYamlAsync(configFilePath, stepLog) {
3697
2118
  return loaded;
3698
2119
  }
3699
2120
  function createRuntimeFromConfigSync(options = {}) {
3700
- const registry = new chunkWQMHMPNC_cjs.ToolRegistry();
2121
+ const registry = new chunkPYCCJF7C_cjs.ToolRegistry();
3701
2122
  const stepLog = options.stepLog;
3702
- setSandboxValidationEnabled(options.coreTools?.enableSandboxValidation === true);
2123
+ chunkZDSZHEQU_cjs.setSandboxValidationEnabled(options.coreTools?.enableSandboxValidation === true);
3703
2124
  if (options.coreTools !== void 0) {
3704
2125
  if (options.configFilePath) {
3705
2126
  const all = loadAllExtensionsFromToolYamlSync(options.configFilePath, stepLog);
@@ -3741,12 +2162,12 @@ function createRuntimeFromConfigSync(options = {}) {
3741
2162
  return { runtime, registry };
3742
2163
  }
3743
2164
  async function createRuntimeFromConfig(options = {}) {
3744
- setSandboxValidationEnabled(options.coreTools?.enableSandboxValidation === true);
2165
+ chunkZDSZHEQU_cjs.setSandboxValidationEnabled(options.coreTools?.enableSandboxValidation === true);
3745
2166
  if (options.coreTools !== void 0 && options.configFilePath) {
3746
2167
  const all = await loadAllExtensionsFromToolYamlAsync(options.configFilePath, options.stepLog);
3747
2168
  if (all.length > 0) {
3748
2169
  if (options.stepLog) options.stepLog(`Registered ${all.length} extension(s) from tool.yaml`);
3749
- const registry = new chunkWQMHMPNC_cjs.ToolRegistry();
2170
+ const registry = new chunkPYCCJF7C_cjs.ToolRegistry();
3750
2171
  const runtime = new PTCRuntime({ registry });
3751
2172
  for (const ext of all) {
3752
2173
  const before = new Set(registry.snapshot().map((s) => s.name));
@@ -3972,18 +2393,18 @@ var BodyParseError = class extends Error {
3972
2393
  }
3973
2394
  };
3974
2395
  function parseBody(req) {
3975
- return new Promise((resolve10, reject) => {
2396
+ return new Promise((resolve3, reject) => {
3976
2397
  const chunks = [];
3977
2398
  req.on("data", (chunk) => chunks.push(chunk));
3978
2399
  req.on("end", () => {
3979
2400
  const raw = Buffer.concat(chunks).toString("utf-8");
3980
2401
  if (!raw.trim()) {
3981
- resolve10({});
2402
+ resolve3({});
3982
2403
  return;
3983
2404
  }
3984
2405
  const parsed = safeParseToolArgs(raw);
3985
2406
  if (parsed.ok) {
3986
- resolve10(parsed.value);
2407
+ resolve3(parsed.value);
3987
2408
  return;
3988
2409
  }
3989
2410
  reject(new BodyParseError("Invalid JSON body", parsed.hint));
@@ -4031,8 +2452,8 @@ function createOpenAPIHttpServer(runtime, options = {}) {
4031
2452
  const ctxFactory = options.execContextFactory ?? (() => ({ ...DEFAULT_CTX }));
4032
2453
  const server = http.createServer(async (req, res) => {
4033
2454
  const url = req.url ?? "/";
4034
- const path7 = url.split("?")[0] ?? "/";
4035
- const norm = basePath ? path7 === basePath ? "" : path7.replace(basePath, "") || "/" : path7;
2455
+ const path = url.split("?")[0] ?? "/";
2456
+ const norm = basePath ? path === basePath ? "" : path.replace(basePath, "") || "/" : path;
4036
2457
  try {
4037
2458
  if (req.method === "GET" && (norm === "/" || norm === "/swagger")) {
4038
2459
  const specPath = basePath ? `${basePath}/openapi.json` : "/openapi.json";
@@ -4141,13 +2562,13 @@ function createOpenAPIHttpServer(runtime, options = {}) {
4141
2562
  return server;
4142
2563
  }
4143
2564
  function listenOpenAPIHttpServer(server, options = {}) {
4144
- return new Promise((resolve10, reject) => {
2565
+ return new Promise((resolve3, reject) => {
4145
2566
  const port = options.port ?? 0;
4146
2567
  const host = options.host ?? "localhost";
4147
2568
  server.listen(port, host, () => {
4148
2569
  const addr = server.address();
4149
2570
  const actualPort = typeof addr === "object" && addr?.port != null ? addr.port : port;
4150
- resolve10({ port: actualPort, host });
2571
+ resolve3({ port: actualPort, host });
4151
2572
  });
4152
2573
  server.on("error", reject);
4153
2574
  });
@@ -4205,7 +2626,7 @@ async function createMcpServerWithTools(runtime, options) {
4205
2626
  async (args) => {
4206
2627
  const ctx = ctxFactory();
4207
2628
  const result = await runtime.invoke(
4208
- { tool: spec.name, args: args ?? {}, purpose: MCP_KIND },
2629
+ { tool: spec.name, args: args ?? {}, purpose: chunkOG5ZSXQ5_cjs.MCP_KIND },
4209
2630
  ctx
4210
2631
  );
4211
2632
  if (result.ok) {
@@ -4269,24 +2690,24 @@ function createMCPStreamableHttpHandler(runtimeOrConfig, options = {}) {
4269
2690
  })();
4270
2691
  }
4271
2692
  async function createMCPServerStreamableHttp(runtimeOrConfig, options = {}) {
4272
- const path7 = options.path ?? "/mcp";
2693
+ const path = options.path ?? "/mcp";
4273
2694
  const host = options.host ?? "127.0.0.1";
4274
2695
  const port = options.port ?? 3e3;
4275
2696
  const { createMcpExpressApp } = await import('@modelcontextprotocol/sdk/server/express.js');
4276
2697
  const handler = "invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function" ? createMCPStreamableHttpHandler(runtimeOrConfig, options) : await createMCPStreamableHttpHandler(runtimeOrConfig, options);
4277
2698
  const app = createMcpExpressApp({ host });
4278
- app.post(path7, handler);
2699
+ app.post(path, handler);
4279
2700
  return {
4280
2701
  app,
4281
- path: path7,
2702
+ path,
4282
2703
  async listen(listenPort, listenHost) {
4283
2704
  const p = listenPort ?? port;
4284
2705
  const h = listenHost ?? host;
4285
- return new Promise((resolve10, reject) => {
2706
+ return new Promise((resolve3, reject) => {
4286
2707
  const server = app.listen(p, h, () => {
4287
2708
  const addr = server.address();
4288
2709
  const actualPort = typeof addr === "object" && addr !== null && "port" in addr ? addr.port : p;
4289
- resolve10({ url: `http://${h}:${actualPort}${path7}`, port: actualPort });
2710
+ resolve3({ url: `http://${h}:${actualPort}${path}`, port: actualPort });
4290
2711
  });
4291
2712
  });
4292
2713
  }
@@ -4298,18 +2719,13 @@ async function runMCPServerOverStdio(runtime, options = {}) {
4298
2719
  return result;
4299
2720
  }
4300
2721
 
4301
- exports.FUNCTION_KIND = FUNCTION_KIND;
4302
- exports.LANGCHAIN_KIND = LANGCHAIN_KIND;
4303
- exports.N8N_KIND = N8N_KIND;
4304
2722
  exports.PTCRuntime = PTCRuntime;
4305
- exports.SKILL_KIND = SKILL_KIND;
4306
2723
  exports.createHttpService = createHttpService;
4307
2724
  exports.createMCPServer = createMCPServer;
4308
2725
  exports.createMCPServerStreamableHttp = createMCPServerStreamableHttp;
4309
2726
  exports.createMCPStreamableHttpHandler = createMCPStreamableHttpHandler;
4310
2727
  exports.createRuntimeFromConfig = createRuntimeFromConfig;
4311
2728
  exports.createRuntimeFromConfigSync = createRuntimeFromConfigSync;
4312
- exports.discoverTools = discoverTools;
4313
2729
  exports.expandToolDescriptorsToRegistryNames = expandToolDescriptorsToRegistryNames;
4314
2730
  exports.fileDescriptorToPackagePrefix = fileDescriptorToPackagePrefix;
4315
2731
  exports.findAndLoadToolConfig = findAndLoadToolConfig;
@@ -4318,11 +2734,7 @@ exports.isBarePackageDescriptor = isBarePackageDescriptor;
4318
2734
  exports.loadToolConfig = loadToolConfig;
4319
2735
  exports.npmDescriptorToPackagePrefixWithVersion = npmDescriptorToPackagePrefixWithVersion;
4320
2736
  exports.resolveSandboxedPath = resolveSandboxedPath;
4321
- exports.resolveSandboxedPath2 = resolveSandboxedPath2;
4322
2737
  exports.resolveToolDescriptor = resolveToolDescriptor;
4323
2738
  exports.runMCPServerOverStdio = runMCPServerOverStdio;
4324
- exports.scan = scan;
4325
- exports.scanForTools = scanForTools;
4326
- exports.setSandboxValidationEnabled = setSandboxValidationEnabled;
4327
- //# sourceMappingURL=chunk-JXYANBTH.cjs.map
4328
- //# sourceMappingURL=chunk-JXYANBTH.cjs.map
2739
+ //# sourceMappingURL=chunk-HK4GTFTQ.cjs.map
2740
+ //# sourceMappingURL=chunk-HK4GTFTQ.cjs.map