@easynet/agent-tool 1.0.91 → 1.0.93

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.
@@ -2,9 +2,9 @@ import { DirectoryScanner, MCP_KIND } from './chunk-SNN4QJ5Z.js';
2
2
  import { ToolRegistry, setSandboxValidationEnabled, createTaggedError, withRetry } from './chunk-IVL4TBFB.js';
3
3
  import { normalizeToolName } from './chunk-BDUSB6GT.js';
4
4
  import { enrichSpecWithCanonicalSchema } from './chunk-NTWOVFEY.js';
5
- import { readFileSync, existsSync, statSync } from 'fs';
6
- import { resolve, dirname, join, isAbsolute, basename } from 'path';
7
- import { parseYamlContent, resolveConfigPath, summarizeForLog } from '@easynet/agent-common';
5
+ import { readFileSync, existsSync, statSync, rmSync, mkdirSync, readdirSync, renameSync } from 'fs';
6
+ import { join, resolve, dirname, isAbsolute, basename } from 'path';
7
+ import { parseYamlContent, resolveConfigPath } from '@easynet/agent-common';
8
8
  import { createRequire } from 'module';
9
9
  import { pathToFileURL } from 'url';
10
10
  import Ajv from 'ajv';
@@ -13,7 +13,8 @@ import { bulkhead, circuitBreaker, handleAll, ConsecutiveBreaker } from 'cockati
13
13
  import { EventEmitter } from 'eventemitter3';
14
14
  import { v4 } from 'uuid';
15
15
  import pTimeout from 'p-timeout';
16
- import { resolveLatestVersionFromRegistry, ensurePackageInCache, getPackageEntryPath, importFromCache } from '@easynet/agent-common/npm';
16
+ import { execSync, execFileSync } from 'child_process';
17
+ import { homedir } from 'os';
17
18
  import express from 'express';
18
19
 
19
20
  function normalizeMcpConfig(raw) {
@@ -219,13 +220,13 @@ function expandToolDescriptorsToRegistryNames(descriptors, registryNames) {
219
220
  out.push(s);
220
221
  continue;
221
222
  }
222
- const path = parseToolPath(s);
223
- if (path) {
224
- const packagePrefix = path.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
223
+ const path2 = parseToolPath(s);
224
+ if (path2) {
225
+ const packagePrefix = path2.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path2.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
225
226
  const prefixWithDot = packagePrefix ? packagePrefix + "." : "";
226
227
  if (prefixWithDot) {
227
- if (path.toolName) {
228
- const suffix = "." + path.toolName;
228
+ if (path2.toolName) {
229
+ const suffix = "." + path2.toolName;
229
230
  for (const r of registryNames) {
230
231
  if (r.startsWith(prefixWithDot) && r.endsWith(suffix) && !seen.has(r)) {
231
232
  seen.add(r);
@@ -254,9 +255,9 @@ function resolveToolDescriptor(descriptor) {
254
255
  return s;
255
256
  }
256
257
  function fileDescriptorToPackagePrefix(descriptor) {
257
- const path = parseToolPath(descriptor.trim());
258
- if (!path || path.protocol !== "file") return "";
259
- const pathPart = `${path.scope}/${path.packageWithVersion}`;
258
+ const path2 = parseToolPath(descriptor.trim());
259
+ if (!path2 || path2.protocol !== "file") return "";
260
+ const pathPart = `${path2.scope}/${path2.packageWithVersion}`;
260
261
  const normalized = normalizeToolName(pathPart);
261
262
  if (!normalized) return "";
262
263
  return normalizeToolName("file." + normalized);
@@ -854,6 +855,22 @@ var EventLog = class {
854
855
  this.seq = 0;
855
856
  }
856
857
  };
858
+
859
+ // src/utils/log.ts
860
+ function summarizeForLog(value, maxLen = 220) {
861
+ const raw = typeof value === "string" ? value : value == null ? "" : (() => {
862
+ try {
863
+ return JSON.stringify(value);
864
+ } catch {
865
+ return String(value);
866
+ }
867
+ })();
868
+ const compact = raw.replace(/\s+/g, " ").trim();
869
+ if (!compact) return "(empty)";
870
+ return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
871
+ }
872
+
873
+ // src/observability/Logger.ts
857
874
  var LEVEL_ORDER = {
858
875
  silent: 0,
859
876
  error: 1,
@@ -1741,6 +1758,147 @@ function buildInputSchemaHint(inputSchema) {
1741
1758
  if (names.length === 0) return null;
1742
1759
  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.`;
1743
1760
  }
1761
+ var versionCache = /* @__PURE__ */ new Map();
1762
+ var CACHE_TTL = 5 * 60 * 1e3;
1763
+ function resolveNpmPackageVersion(packageName, tag, options = {}) {
1764
+ const cacheKey = packageName;
1765
+ const cached = versionCache.get(cacheKey);
1766
+ if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
1767
+ return cached.version;
1768
+ }
1769
+ try {
1770
+ const spec = tag ? `${packageName}@${tag}` : packageName;
1771
+ const out = execFileSync("npm", ["view", spec, "version"], {
1772
+ cwd: options.cwd ?? process.cwd(),
1773
+ encoding: "utf-8",
1774
+ timeout: options.timeoutMs ?? 8e3,
1775
+ stdio: ["ignore", "pipe", "pipe"]
1776
+ });
1777
+ const version = out?.trim() ?? null;
1778
+ if (version) {
1779
+ versionCache.set(cacheKey, { version, timestamp: Date.now() });
1780
+ }
1781
+ return version;
1782
+ } catch {
1783
+ return null;
1784
+ }
1785
+ }
1786
+ function resolveLatestVersionFromRegistry(packageName, options = {}) {
1787
+ const version = resolveNpmPackageVersion(packageName, void 0, options);
1788
+ if (!version) {
1789
+ throw new Error(`Failed to resolve latest version for ${packageName}`);
1790
+ }
1791
+ return version;
1792
+ }
1793
+
1794
+ // src/utils/npmCache.ts
1795
+ var DEFAULT_CACHE_BASE = join(homedir(), ".agent", "cache");
1796
+ function isLatestRequest(version) {
1797
+ const normalized = (version ?? "").trim().toLowerCase();
1798
+ return normalized === "" || normalized === "latest";
1799
+ }
1800
+ function getCachedPackageVersion(cacheDir) {
1801
+ const pkgPath = join(cacheDir, "package.json");
1802
+ if (!existsSync(pkgPath)) return void 0;
1803
+ try {
1804
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1805
+ return typeof pkg.version === "string" ? pkg.version : void 0;
1806
+ } catch {
1807
+ return void 0;
1808
+ }
1809
+ }
1810
+ function packagePathSegments(name) {
1811
+ const withoutScope = name.replace(/^@/, "");
1812
+ return withoutScope.split("/").filter(Boolean);
1813
+ }
1814
+ function resolveCacheDir(cacheBase, packageName, version) {
1815
+ const segments = packagePathSegments(packageName);
1816
+ return join(cacheBase, ...segments, version);
1817
+ }
1818
+ function ensurePackageInCache(packageName, version = "latest", options = {}) {
1819
+ const cacheBase = options.cacheBase ?? DEFAULT_CACHE_BASE;
1820
+ const cwd = options.cwd ?? process.cwd();
1821
+ const resolvedVersion = isLatestRequest(version) ? resolveLatestVersionFromRegistry(packageName, { cwd }) : version;
1822
+ const cacheDir = resolveCacheDir(cacheBase, packageName, resolvedVersion);
1823
+ const packageJsonPath = join(cacheDir, "package.json");
1824
+ const nodeModulesPath = join(cacheDir, "node_modules");
1825
+ if (existsSync(packageJsonPath) && existsSync(nodeModulesPath)) {
1826
+ const cachedVersion = getCachedPackageVersion(cacheDir);
1827
+ if (cachedVersion === resolvedVersion) {
1828
+ options.afterInstall?.(cacheDir, packageName);
1829
+ return cacheDir;
1830
+ }
1831
+ rmSync(cacheDir, { recursive: true, force: true });
1832
+ }
1833
+ const packDest = join(cacheBase, ".pack-tmp", packageName.replace(/@/g, "").replace(/\//g, "_"));
1834
+ mkdirSync(packDest, { recursive: true });
1835
+ try {
1836
+ execSync(`npm pack ${packageName}@${resolvedVersion} --pack-destination "${packDest}"`, {
1837
+ cwd,
1838
+ stdio: "pipe",
1839
+ encoding: "utf-8"
1840
+ });
1841
+ const files = readdirSync(packDest);
1842
+ const tgz = files.find((file) => file.endsWith(".tgz"));
1843
+ if (!tgz) throw new Error(`npm pack did not produce a .tgz in ${packDest}`);
1844
+ const extractDir = join(packDest, "extract");
1845
+ mkdirSync(extractDir, { recursive: true });
1846
+ execSync(`tar -xzf "${join(packDest, tgz)}" -C "${extractDir}"`, {
1847
+ stdio: "pipe",
1848
+ encoding: "utf-8"
1849
+ });
1850
+ const extractedPackage = join(extractDir, "package");
1851
+ if (!existsSync(extractedPackage)) {
1852
+ throw new Error(`Extracted tarball did not contain "package" dir in ${extractDir}`);
1853
+ }
1854
+ mkdirSync(join(cacheDir, ".."), { recursive: true });
1855
+ if (existsSync(cacheDir)) rmSync(cacheDir, { recursive: true, force: true });
1856
+ renameSync(extractedPackage, cacheDir);
1857
+ const npmInstallTimeout = 12e4;
1858
+ const maxAttempts = 3;
1859
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1860
+ try {
1861
+ execSync("npm install --prefer-offline --no-audit --no-fund", {
1862
+ cwd: cacheDir,
1863
+ stdio: "pipe",
1864
+ encoding: "utf-8",
1865
+ timeout: npmInstallTimeout
1866
+ });
1867
+ break;
1868
+ } catch (error) {
1869
+ if (attempt >= maxAttempts) {
1870
+ const lastError = error instanceof Error ? error : new Error(String(error));
1871
+ throw new Error(`npm install in cache failed after ${maxAttempts} attempts: ${lastError.message}`);
1872
+ }
1873
+ const delayMs = 5e3 * attempt;
1874
+ const deadline = Date.now() + delayMs;
1875
+ while (Date.now() < deadline) {
1876
+ }
1877
+ }
1878
+ }
1879
+ options.afterInstall?.(cacheDir, packageName);
1880
+ return cacheDir;
1881
+ } finally {
1882
+ if (existsSync(packDest)) rmSync(packDest, { recursive: true, force: true });
1883
+ }
1884
+ }
1885
+ function getPackageEntryPath(packageRoot) {
1886
+ const pkgPath = join(packageRoot, "package.json");
1887
+ if (!existsSync(pkgPath)) throw new Error(`No package.json in ${packageRoot}`);
1888
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1889
+ const main = pkg.main ?? "dist/index.js";
1890
+ const entryPath = join(packageRoot, main);
1891
+ if (!existsSync(entryPath)) throw new Error(`Entry not found: ${entryPath}`);
1892
+ return entryPath;
1893
+ }
1894
+ async function importFromCache(packageRoot) {
1895
+ const entryPath = getPackageEntryPath(packageRoot);
1896
+ const fileUrl = pathToFileURL(entryPath).href;
1897
+ return import(
1898
+ /* @vite-ignore */
1899
+ fileUrl
1900
+ );
1901
+ }
1744
1902
  var requireFromPackage = createRequire(import.meta.url);
1745
1903
  function getProjectRequire() {
1746
1904
  const cwd = process.cwd();
@@ -1938,11 +2096,11 @@ function loadExtensionFromNodeModules() {
1938
2096
  }
1939
2097
  function loadExtensionFromFileDescriptorSync(descriptor, configFilePath, stepLog) {
1940
2098
  const entryStr = descriptor.trim();
1941
- const path = parseToolPath(entryStr);
1942
- if (!path || path.protocol !== "file") return null;
2099
+ const path2 = parseToolPath(entryStr);
2100
+ if (!path2 || path2.protocol !== "file") return null;
1943
2101
  const localPath = isAbsolute(configFilePath) ? configFilePath : resolve(process.cwd(), configFilePath);
1944
2102
  const configDir = dirname(localPath);
1945
- const pathPart = `${path.scope}/${path.packageWithVersion}`;
2103
+ const pathPart = `${path2.scope}/${path2.packageWithVersion}`;
1946
2104
  const resolvedPath = resolve(configDir, pathPart);
1947
2105
  if (!existsSync(resolvedPath) || !statSync(resolvedPath).isDirectory()) return null;
1948
2106
  try {
@@ -2360,16 +2518,16 @@ function createMCPStreamableHttpHandler(runtimeOrConfig, options = {}) {
2360
2518
  })();
2361
2519
  }
2362
2520
  async function createMCPServerStreamableHttp(runtimeOrConfig, options = {}) {
2363
- const path = options.path ?? "/mcp";
2521
+ const path2 = options.path ?? "/mcp";
2364
2522
  const host = options.host ?? "127.0.0.1";
2365
2523
  const port = options.port ?? 3e3;
2366
2524
  const { createMcpExpressApp } = await import('@modelcontextprotocol/sdk/server/express.js');
2367
2525
  const handler = "invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function" ? createMCPStreamableHttpHandler(runtimeOrConfig, options) : await createMCPStreamableHttpHandler(runtimeOrConfig, options);
2368
2526
  const app = createMcpExpressApp({ host });
2369
- app.post(path, handler);
2527
+ app.post(path2, handler);
2370
2528
  return {
2371
2529
  app,
2372
- path,
2530
+ path: path2,
2373
2531
  async listen(listenPort, listenHost) {
2374
2532
  const p = listenPort ?? port;
2375
2533
  const h = listenHost ?? host;
@@ -2377,7 +2535,7 @@ async function createMCPServerStreamableHttp(runtimeOrConfig, options = {}) {
2377
2535
  const server = app.listen(p, h, () => {
2378
2536
  const addr = server.address();
2379
2537
  const actualPort = typeof addr === "object" && addr !== null && "port" in addr ? addr.port : p;
2380
- resolve4({ url: `http://${h}:${actualPort}${path}`, port: actualPort });
2538
+ resolve4({ url: `http://${h}:${actualPort}${path2}`, port: actualPort });
2381
2539
  });
2382
2540
  });
2383
2541
  }
@@ -2774,5 +2932,5 @@ async function createHttpService(runtimeOrConfig, options = {}) {
2774
2932
  }
2775
2933
 
2776
2934
  export { createHttpService, createMCPServerStreamableHttp, createRuntimeFromConfig, createRuntimeFromConfigSync, expandToolDescriptorsToRegistryNames, fileDescriptorToPackagePrefix, findAndLoadToolConfig, getDisplayScope, isBarePackageDescriptor, loadAllExtensionsFromToolYamlSync, loadToolConfig, npmDescriptorToPackagePrefixWithVersion, resolveSandboxedPath, resolveToolDescriptor, runMCPServerOverStdio, toToolObservationText };
2777
- //# sourceMappingURL=chunk-GAC3N3KH.js.map
2778
- //# sourceMappingURL=chunk-GAC3N3KH.js.map
2935
+ //# sourceMappingURL=chunk-Z6FD2GKB.js.map
2936
+ //# sourceMappingURL=chunk-Z6FD2GKB.js.map