@easynet/agent-tool 1.0.45 → 1.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -105
- package/dist/api/extension/groupPrefix.d.ts.map +1 -1
- package/dist/api/main.cjs +19 -20
- package/dist/api/main.js +2 -3
- package/dist/api/runtimeFromConfig.d.ts.map +1 -1
- package/dist/{chunk-JH6TWGP4.js → chunk-2ZPDD7ZO.js} +722 -279
- package/dist/chunk-2ZPDD7ZO.js.map +1 -0
- package/dist/{chunk-ONXFQ6K5.js → chunk-64ZQQV5C.js} +79 -75
- package/dist/chunk-64ZQQV5C.js.map +1 -0
- package/dist/{chunk-YVL3UMM2.cjs → chunk-A5B6Q6EG.cjs} +733 -317
- package/dist/chunk-A5B6Q6EG.cjs.map +1 -0
- package/dist/{chunk-5WY557HJ.cjs → chunk-IAEVDXWS.cjs} +15 -16
- package/dist/chunk-IAEVDXWS.cjs.map +1 -0
- package/dist/{chunk-YUA6KJWF.js → chunk-KYBIKD5R.js} +5 -5
- package/dist/chunk-KYBIKD5R.js.map +1 -0
- package/dist/{chunk-ETXVT6FE.cjs → chunk-MDPU7EIO.cjs} +83 -87
- package/dist/chunk-MDPU7EIO.cjs.map +1 -0
- package/dist/index.cjs +195 -413
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +16 -63
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +171 -281
- package/dist/index.js.map +1 -1
- package/dist/utils/cli/index.cjs +16 -17
- package/dist/utils/cli/index.cjs.map +1 -1
- package/dist/utils/cli/index.js +3 -4
- package/dist/utils/cli/index.js.map +1 -1
- package/dist/utils/npmCache.d.ts +1 -1
- package/dist/utils/npmCache.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-5WY557HJ.cjs.map +0 -1
- package/dist/chunk-CLJCCBXA.js +0 -474
- package/dist/chunk-CLJCCBXA.js.map +0 -1
- package/dist/chunk-ETXVT6FE.cjs.map +0 -1
- package/dist/chunk-H5SPD2O7.cjs +0 -480
- package/dist/chunk-H5SPD2O7.cjs.map +0 -1
- package/dist/chunk-JH6TWGP4.js.map +0 -1
- package/dist/chunk-ONXFQ6K5.js.map +0 -1
- package/dist/chunk-YUA6KJWF.js.map +0 -1
- package/dist/chunk-YVL3UMM2.cjs.map +0 -1
|
@@ -1,18 +1,243 @@
|
|
|
1
1
|
import { ToolRegistry, createTaggedError, withRetry } from './chunk-ZRHPGW7W.js';
|
|
2
2
|
import { normalizeToolName } from './chunk-KDB3MY2H.js';
|
|
3
|
+
import { enrichSpecWithCanonicalSchema } from './chunk-NTWOVFEY.js';
|
|
4
|
+
import { readFileSync, existsSync, statSync } from 'fs';
|
|
5
|
+
import { resolve, dirname, join, normalize, basename, isAbsolute } from 'path';
|
|
6
|
+
import { parseYamlContent, resolveConfigPath } from '@easynet/agent-common';
|
|
3
7
|
import Ajv from 'ajv';
|
|
4
8
|
import addFormats from 'ajv-formats';
|
|
5
9
|
import { bulkhead, circuitBreaker, handleAll, ConsecutiveBreaker } from 'cockatiel';
|
|
6
10
|
import { EventEmitter } from 'eventemitter3';
|
|
7
11
|
import { v4 } from 'uuid';
|
|
8
12
|
import pTimeout from 'p-timeout';
|
|
9
|
-
import { resolve, normalize, dirname, basename, join, isAbsolute } from 'path';
|
|
10
13
|
import { realpath, access } from 'fs/promises';
|
|
11
|
-
import { readFileSync, existsSync, statSync } from 'fs';
|
|
12
|
-
import { parseYamlContent, resolveConfigPath, resolveLatestVersionFromRegistry, ensurePackageInCache, getPackageEntryPath, importFromCache } from '@easynet/agent-common';
|
|
13
|
-
export { ensurePackageInCache, getPackageEntryPath, importFromCache, resolveLatestVersionFromRegistry } from '@easynet/agent-common';
|
|
14
14
|
import { createRequire } from 'module';
|
|
15
|
+
import { resolveLatestVersionFromRegistry, ensurePackageInCache, getPackageEntryPath, importFromCache } from '@easynet/agent-common/npm';
|
|
16
|
+
import { createServer } from 'http';
|
|
17
|
+
|
|
18
|
+
function loadToolConfig(toolYamlPath) {
|
|
19
|
+
const abs = resolve(toolYamlPath);
|
|
20
|
+
const raw = readFileSync(abs, "utf8");
|
|
21
|
+
const parsed = parseYamlContent(raw, {
|
|
22
|
+
substituteEnv: false
|
|
23
|
+
});
|
|
24
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
25
|
+
const toolsBlock = parsed.tools;
|
|
26
|
+
if (toolsBlock != null && typeof toolsBlock === "object" && !Array.isArray(toolsBlock)) {
|
|
27
|
+
const toolDefaults = toolsBlock.defaults != null && typeof toolsBlock.defaults === "object" && !Array.isArray(toolsBlock.defaults) ? toolsBlock.defaults : void 0;
|
|
28
|
+
const packageToolDefaults2 = toolsBlock.packages != null && typeof toolsBlock.packages === "object" && !Array.isArray(toolsBlock.packages) ? toolsBlock.packages : void 0;
|
|
29
|
+
const list2 = Array.isArray(toolsBlock.list) && toolsBlock.list.length > 0 ? toolsBlock.list : void 0;
|
|
30
|
+
return {
|
|
31
|
+
tools: list2 ?? (packageToolDefaults2 ? Object.keys(packageToolDefaults2) : void 0),
|
|
32
|
+
sandboxedPath: typeof toolsBlock.sandboxedPath === "string" ? toolsBlock.sandboxedPath : parsed.sandboxedPath,
|
|
33
|
+
enableSandboxValidation: typeof toolsBlock.enableSandboxValidation === "boolean" ? toolsBlock.enableSandboxValidation : parsed.enableSandboxValidation,
|
|
34
|
+
allowedHosts: Array.isArray(toolsBlock.allowedHosts) ? toolsBlock.allowedHosts : parsed.allowedHosts,
|
|
35
|
+
blockedHosts: Array.isArray(toolsBlock.blockedHosts) ? toolsBlock.blockedHosts : parsed.blockedHosts,
|
|
36
|
+
blockedCidrs: Array.isArray(toolsBlock.blockedCidrs) ? toolsBlock.blockedCidrs : parsed.blockedCidrs,
|
|
37
|
+
toolDefaults,
|
|
38
|
+
packageToolDefaults: packageToolDefaults2
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const packageToolDefaults = typeof parsed.packageToolDefaults === "object" && !Array.isArray(parsed.packageToolDefaults) ? parsed.packageToolDefaults : void 0;
|
|
42
|
+
const list = Array.isArray(parsed.tools) && parsed.tools.length > 0 ? parsed.tools : void 0;
|
|
43
|
+
return {
|
|
44
|
+
tools: list ?? (packageToolDefaults ? Object.keys(packageToolDefaults) : void 0),
|
|
45
|
+
sandboxedPath: parsed.sandboxedPath,
|
|
46
|
+
enableSandboxValidation: typeof parsed.enableSandboxValidation === "boolean" ? parsed.enableSandboxValidation : void 0,
|
|
47
|
+
allowedHosts: Array.isArray(parsed.allowedHosts) ? parsed.allowedHosts : void 0,
|
|
48
|
+
blockedHosts: Array.isArray(parsed.blockedHosts) ? parsed.blockedHosts : void 0,
|
|
49
|
+
blockedCidrs: Array.isArray(parsed.blockedCidrs) ? parsed.blockedCidrs : void 0,
|
|
50
|
+
toolDefaults: typeof parsed.toolDefaults === "object" && !Array.isArray(parsed.toolDefaults) ? parsed.toolDefaults : void 0,
|
|
51
|
+
packageToolDefaults
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function resolveSandboxedPath(toolYamlPath, sandboxedPath) {
|
|
55
|
+
const configDir = dirname(resolve(toolYamlPath));
|
|
56
|
+
return resolveConfigPath(sandboxedPath, configDir, {
|
|
57
|
+
expandHome: true
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
var CACHE_SUBDIR = ".agent/cache";
|
|
61
|
+
function getCacheBaseFromToolConfig(toolYamlPath) {
|
|
62
|
+
const config = loadToolConfig(toolYamlPath);
|
|
63
|
+
if (!config.sandboxedPath || typeof config.sandboxedPath !== "string") return void 0;
|
|
64
|
+
const sandboxRoot = resolveSandboxedPath(toolYamlPath, config.sandboxedPath);
|
|
65
|
+
return join(sandboxRoot, CACHE_SUBDIR);
|
|
66
|
+
}
|
|
67
|
+
function findAndLoadToolConfig(dir) {
|
|
68
|
+
const resolvedDir = resolve(dir);
|
|
69
|
+
const candidates = [join(resolvedDir, "tool.yaml"), join(resolvedDir, ".tool.yaml")];
|
|
70
|
+
for (const p of candidates) {
|
|
71
|
+
if (existsSync(p)) {
|
|
72
|
+
const config = loadToolConfig(p);
|
|
73
|
+
return { ...config, configPath: p };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
15
78
|
|
|
79
|
+
// src/tools/util/toolDescriptor.ts
|
|
80
|
+
var TOOL_PATH_REGEX = /^([a-z][a-z0-9-]*):([^/]+)\/([^#]+)(#(.+))?$/;
|
|
81
|
+
function isToolPath(descriptor) {
|
|
82
|
+
return TOOL_PATH_REGEX.test(descriptor.trim());
|
|
83
|
+
}
|
|
84
|
+
function isBarePackageDescriptor(descriptor) {
|
|
85
|
+
const parsed = parseToolPath(descriptor.trim());
|
|
86
|
+
return parsed !== null && parsed.toolName === "";
|
|
87
|
+
}
|
|
88
|
+
function parseToolPath(descriptor) {
|
|
89
|
+
const s = descriptor.trim();
|
|
90
|
+
const m = s.match(TOOL_PATH_REGEX);
|
|
91
|
+
if (!m || m[1] === void 0 || m[2] === void 0 || m[3] === void 0) return null;
|
|
92
|
+
return {
|
|
93
|
+
protocol: m[1],
|
|
94
|
+
scope: m[2],
|
|
95
|
+
packageWithVersion: m[3],
|
|
96
|
+
toolName: m[5] ?? ""
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function npmDescriptorToRegistryPrefix(descriptor, resolvedVersion) {
|
|
100
|
+
const s = descriptor.trim();
|
|
101
|
+
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
102
|
+
const rest = s.slice(4).trim();
|
|
103
|
+
const hashIdx = rest.indexOf("#");
|
|
104
|
+
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
105
|
+
const lastAt = beforeHash.lastIndexOf("@");
|
|
106
|
+
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
107
|
+
let version = lastAt <= 0 ? "latest" : beforeHash.slice(lastAt + 1).trim() || "latest";
|
|
108
|
+
if (version === "latest" || !version) {
|
|
109
|
+
const resolved = (resolvedVersion ?? "").trim();
|
|
110
|
+
if (resolved !== "" && resolved.toLowerCase() !== "latest") {
|
|
111
|
+
version = resolved;
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Registry prefix requires a concrete version when descriptor uses latest (${descriptor}). Resolve version from registry (e.g. resolveLatestVersionFromRegistry) and pass as resolvedVersion.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!version || version.toLowerCase() === "latest") {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Registry never uses "latest"; pass resolved concrete version for npm descriptor: ${descriptor}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const slashIdx = scopeAndPackage.indexOf("/");
|
|
124
|
+
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
125
|
+
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
126
|
+
const segment = [scope, pkg, version].filter(Boolean).join(".");
|
|
127
|
+
const normalized = normalizeToolName(segment);
|
|
128
|
+
if (!normalized) return "";
|
|
129
|
+
return "npm." + normalized + ".";
|
|
130
|
+
}
|
|
131
|
+
function npmDescriptorToPackagePrefix(descriptor) {
|
|
132
|
+
const s = descriptor.trim();
|
|
133
|
+
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
134
|
+
const rest = s.slice(4).trim();
|
|
135
|
+
const hashIdx = rest.indexOf("#");
|
|
136
|
+
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
137
|
+
const lastAt = beforeHash.lastIndexOf("@");
|
|
138
|
+
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
139
|
+
const slashIdx = scopeAndPackage.indexOf("/");
|
|
140
|
+
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
141
|
+
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
142
|
+
const segment = [scope, pkg].filter(Boolean).join(".");
|
|
143
|
+
const normalized = normalizeToolName(segment);
|
|
144
|
+
if (!normalized) return "";
|
|
145
|
+
return "npm." + normalized;
|
|
146
|
+
}
|
|
147
|
+
function npmDescriptorToPackagePrefixWithVersion(descriptor) {
|
|
148
|
+
const s = descriptor.trim();
|
|
149
|
+
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
150
|
+
const rest = s.slice(4).trim();
|
|
151
|
+
const hashIdx = rest.indexOf("#");
|
|
152
|
+
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
153
|
+
const lastAt = beforeHash.lastIndexOf("@");
|
|
154
|
+
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
155
|
+
const version = lastAt <= 0 ? "" : beforeHash.slice(lastAt + 1).trim();
|
|
156
|
+
const slashIdx = scopeAndPackage.indexOf("/");
|
|
157
|
+
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
158
|
+
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
159
|
+
const segment = [scope, pkg, version].filter(Boolean).join(".");
|
|
160
|
+
const normalized = normalizeToolName(segment);
|
|
161
|
+
if (!normalized) return "";
|
|
162
|
+
return "npm." + normalized;
|
|
163
|
+
}
|
|
164
|
+
function getDisplayScope(registryName, _kind, _toolVersion) {
|
|
165
|
+
const i = registryName.indexOf(".");
|
|
166
|
+
return i < 0 ? registryName : registryName.slice(0, i);
|
|
167
|
+
}
|
|
168
|
+
function expandToolDescriptorsToRegistryNames(descriptors, registryNames) {
|
|
169
|
+
const out = [];
|
|
170
|
+
const seen = /* @__PURE__ */ new Set();
|
|
171
|
+
function add(name) {
|
|
172
|
+
const key = normalizeToolName(name);
|
|
173
|
+
if (registryNames.includes(key) && !seen.has(key)) {
|
|
174
|
+
seen.add(key);
|
|
175
|
+
out.push(key);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const matched = registryNames.filter((r) => r === key || r.endsWith("." + key));
|
|
179
|
+
for (const m of matched) {
|
|
180
|
+
if (!seen.has(m)) {
|
|
181
|
+
seen.add(m);
|
|
182
|
+
out.push(m);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
for (const d of descriptors) {
|
|
187
|
+
const s = d.trim();
|
|
188
|
+
if (!s) continue;
|
|
189
|
+
if (isToolPath(s)) {
|
|
190
|
+
if (registryNames.includes(s) && !seen.has(s)) {
|
|
191
|
+
seen.add(s);
|
|
192
|
+
out.push(s);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const path = parseToolPath(s);
|
|
196
|
+
if (path) {
|
|
197
|
+
const packagePrefix = path.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
|
|
198
|
+
const prefixWithDot = packagePrefix ? packagePrefix + "." : "";
|
|
199
|
+
if (prefixWithDot) {
|
|
200
|
+
if (path.toolName) {
|
|
201
|
+
const suffix = "." + path.toolName;
|
|
202
|
+
for (const r of registryNames) {
|
|
203
|
+
if (r.startsWith(prefixWithDot) && r.endsWith(suffix) && !seen.has(r)) {
|
|
204
|
+
seen.add(r);
|
|
205
|
+
out.push(r);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
for (const r of registryNames) {
|
|
210
|
+
if (r.startsWith(prefixWithDot) && !seen.has(r)) {
|
|
211
|
+
seen.add(r);
|
|
212
|
+
out.push(r);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const name = normalizeToolName(s);
|
|
221
|
+
add(name);
|
|
222
|
+
}
|
|
223
|
+
return out;
|
|
224
|
+
}
|
|
225
|
+
function resolveToolDescriptor(descriptor) {
|
|
226
|
+
const s = descriptor.trim();
|
|
227
|
+
return s;
|
|
228
|
+
}
|
|
229
|
+
function fileDescriptorToPackagePrefix(descriptor) {
|
|
230
|
+
const path = parseToolPath(descriptor.trim());
|
|
231
|
+
if (!path || path.protocol !== "file") return "";
|
|
232
|
+
const pathPart = `${path.scope}/${path.packageWithVersion}`;
|
|
233
|
+
const normalized = normalizeToolName(pathPart);
|
|
234
|
+
if (!normalized) return "";
|
|
235
|
+
return "file." + normalized;
|
|
236
|
+
}
|
|
237
|
+
function fileDescriptorToRegistryPrefix(descriptor) {
|
|
238
|
+
const prefix = fileDescriptorToPackagePrefix(descriptor);
|
|
239
|
+
return prefix ? prefix + "." : "";
|
|
240
|
+
}
|
|
16
241
|
var SchemaValidator = class {
|
|
17
242
|
ajv;
|
|
18
243
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -1482,7 +1707,7 @@ var sandboxValidationEnabled = false;
|
|
|
1482
1707
|
function setSandboxValidationEnabled(enabled) {
|
|
1483
1708
|
sandboxValidationEnabled = enabled;
|
|
1484
1709
|
}
|
|
1485
|
-
async function
|
|
1710
|
+
async function resolveSandboxedPath2(inputPath, sandboxRoot) {
|
|
1486
1711
|
let normalizedRoot;
|
|
1487
1712
|
try {
|
|
1488
1713
|
normalizedRoot = await realpath(resolve(sandboxRoot));
|
|
@@ -1520,278 +1745,30 @@ function isWithinRoot(path, root) {
|
|
|
1520
1745
|
return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + "/");
|
|
1521
1746
|
}
|
|
1522
1747
|
|
|
1523
|
-
// src/
|
|
1524
|
-
var
|
|
1525
|
-
function
|
|
1526
|
-
|
|
1748
|
+
// src/api/runtimeFromConfig.ts
|
|
1749
|
+
var requireFromPackage = createRequire(import.meta.url);
|
|
1750
|
+
function getProjectRequire() {
|
|
1751
|
+
const cwd = process.cwd();
|
|
1752
|
+
if (existsSync(join(cwd, "package.json"))) return createRequire(join(cwd, "package.json"));
|
|
1753
|
+
if (existsSync(join(cwd, "tool.yaml"))) return createRequire(join(cwd, "tool.yaml"));
|
|
1754
|
+
return null;
|
|
1527
1755
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
const s = descriptor.trim();
|
|
1545
|
-
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
1546
|
-
const rest = s.slice(4).trim();
|
|
1547
|
-
const hashIdx = rest.indexOf("#");
|
|
1548
|
-
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
1549
|
-
const lastAt = beforeHash.lastIndexOf("@");
|
|
1550
|
-
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
1551
|
-
let version = lastAt <= 0 ? "latest" : beforeHash.slice(lastAt + 1).trim() || "latest";
|
|
1552
|
-
if (version === "latest" || !version) {
|
|
1553
|
-
const resolved = (resolvedVersion ?? "").trim();
|
|
1554
|
-
if (resolved !== "" && resolved.toLowerCase() !== "latest") {
|
|
1555
|
-
version = resolved;
|
|
1556
|
-
} else {
|
|
1557
|
-
throw new Error(
|
|
1558
|
-
`Registry prefix requires a concrete version when descriptor uses latest (${descriptor}). Resolve version from registry (e.g. resolveLatestVersionFromRegistry) and pass as resolvedVersion.`
|
|
1559
|
-
);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
if (!version || version.toLowerCase() === "latest") {
|
|
1563
|
-
throw new Error(
|
|
1564
|
-
`Registry never uses "latest"; pass resolved concrete version for npm descriptor: ${descriptor}`
|
|
1565
|
-
);
|
|
1566
|
-
}
|
|
1567
|
-
const slashIdx = scopeAndPackage.indexOf("/");
|
|
1568
|
-
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
1569
|
-
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
1570
|
-
const segment = [scope, pkg, version].filter(Boolean).join(".");
|
|
1571
|
-
const normalized = normalizeToolName(segment);
|
|
1572
|
-
if (!normalized) return "";
|
|
1573
|
-
return "npm." + normalized + ".";
|
|
1574
|
-
}
|
|
1575
|
-
function npmDescriptorToPackagePrefix(descriptor) {
|
|
1576
|
-
const s = descriptor.trim();
|
|
1577
|
-
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
1578
|
-
const rest = s.slice(4).trim();
|
|
1579
|
-
const hashIdx = rest.indexOf("#");
|
|
1580
|
-
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
1581
|
-
const lastAt = beforeHash.lastIndexOf("@");
|
|
1582
|
-
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
1583
|
-
const slashIdx = scopeAndPackage.indexOf("/");
|
|
1584
|
-
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
1585
|
-
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
1586
|
-
const segment = [scope, pkg].filter(Boolean).join(".");
|
|
1587
|
-
const normalized = normalizeToolName(segment);
|
|
1588
|
-
if (!normalized) return "";
|
|
1589
|
-
return "npm." + normalized;
|
|
1590
|
-
}
|
|
1591
|
-
function npmDescriptorToPackagePrefixWithVersion(descriptor) {
|
|
1592
|
-
const s = descriptor.trim();
|
|
1593
|
-
if (typeof s !== "string" || !s.startsWith("npm:")) return "";
|
|
1594
|
-
const rest = s.slice(4).trim();
|
|
1595
|
-
const hashIdx = rest.indexOf("#");
|
|
1596
|
-
const beforeHash = hashIdx < 0 ? rest : rest.slice(0, hashIdx);
|
|
1597
|
-
const lastAt = beforeHash.lastIndexOf("@");
|
|
1598
|
-
const scopeAndPackage = lastAt <= 0 ? beforeHash : beforeHash.slice(0, lastAt);
|
|
1599
|
-
const version = lastAt <= 0 ? "" : beforeHash.slice(lastAt + 1).trim();
|
|
1600
|
-
const slashIdx = scopeAndPackage.indexOf("/");
|
|
1601
|
-
const scope = slashIdx < 0 ? scopeAndPackage : scopeAndPackage.slice(0, slashIdx).replace(/^@/, "");
|
|
1602
|
-
const pkg = slashIdx < 0 ? "" : scopeAndPackage.slice(slashIdx + 1);
|
|
1603
|
-
const segment = [scope, pkg, version].filter(Boolean).join(".");
|
|
1604
|
-
const normalized = normalizeToolName(segment);
|
|
1605
|
-
if (!normalized) return "";
|
|
1606
|
-
return "npm." + normalized;
|
|
1607
|
-
}
|
|
1608
|
-
function isNpmToolDescriptor(descriptor) {
|
|
1609
|
-
return isToolPath(descriptor) && parseToolPath(descriptor)?.protocol === "npm";
|
|
1610
|
-
}
|
|
1611
|
-
function parseNpmToolDescriptor(descriptor) {
|
|
1612
|
-
const parsed = parseToolPath(descriptor);
|
|
1613
|
-
if (!parsed || parsed.protocol !== "npm") return null;
|
|
1614
|
-
return {
|
|
1615
|
-
fullPackage: `${parsed.scope}/${parsed.packageWithVersion}`,
|
|
1616
|
-
toolPath: parsed.toolName
|
|
1617
|
-
};
|
|
1618
|
-
}
|
|
1619
|
-
function getDisplayScope(registryName, _kind, _toolVersion) {
|
|
1620
|
-
const i = registryName.indexOf(".");
|
|
1621
|
-
return i < 0 ? registryName : registryName.slice(0, i);
|
|
1622
|
-
}
|
|
1623
|
-
function resolveNpmToolDescriptor(descriptor) {
|
|
1624
|
-
return null;
|
|
1625
|
-
}
|
|
1626
|
-
function expandToolDescriptorsToRegistryNames(descriptors, registryNames) {
|
|
1627
|
-
const out = [];
|
|
1628
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1629
|
-
function add(name) {
|
|
1630
|
-
const key = normalizeToolName(name);
|
|
1631
|
-
if (registryNames.includes(key) && !seen.has(key)) {
|
|
1632
|
-
seen.add(key);
|
|
1633
|
-
out.push(key);
|
|
1634
|
-
return;
|
|
1635
|
-
}
|
|
1636
|
-
const matched = registryNames.filter((r) => r === key || r.endsWith("." + key));
|
|
1637
|
-
for (const m of matched) {
|
|
1638
|
-
if (!seen.has(m)) {
|
|
1639
|
-
seen.add(m);
|
|
1640
|
-
out.push(m);
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
for (const d of descriptors) {
|
|
1645
|
-
const s = d.trim();
|
|
1646
|
-
if (!s) continue;
|
|
1647
|
-
if (isToolPath(s)) {
|
|
1648
|
-
if (registryNames.includes(s) && !seen.has(s)) {
|
|
1649
|
-
seen.add(s);
|
|
1650
|
-
out.push(s);
|
|
1651
|
-
continue;
|
|
1652
|
-
}
|
|
1653
|
-
const path = parseToolPath(s);
|
|
1654
|
-
if (path) {
|
|
1655
|
-
const packagePrefix = path.protocol === "npm" ? npmDescriptorToPackagePrefix(s) : path.protocol === "file" ? fileDescriptorToPackagePrefix(s) : "";
|
|
1656
|
-
const prefixWithDot = packagePrefix ? packagePrefix + "." : "";
|
|
1657
|
-
if (prefixWithDot) {
|
|
1658
|
-
if (path.toolName) {
|
|
1659
|
-
const suffix = "." + path.toolName;
|
|
1660
|
-
for (const r of registryNames) {
|
|
1661
|
-
if (r.startsWith(prefixWithDot) && r.endsWith(suffix) && !seen.has(r)) {
|
|
1662
|
-
seen.add(r);
|
|
1663
|
-
out.push(r);
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
} else {
|
|
1667
|
-
for (const r of registryNames) {
|
|
1668
|
-
if (r.startsWith(prefixWithDot) && !seen.has(r)) {
|
|
1669
|
-
seen.add(r);
|
|
1670
|
-
out.push(r);
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
continue;
|
|
1677
|
-
}
|
|
1678
|
-
const name = normalizeToolName(s);
|
|
1679
|
-
add(name);
|
|
1680
|
-
}
|
|
1681
|
-
return out;
|
|
1682
|
-
}
|
|
1683
|
-
function resolveToolDescriptor(descriptor) {
|
|
1684
|
-
const s = descriptor.trim();
|
|
1685
|
-
return s;
|
|
1686
|
-
}
|
|
1687
|
-
function normalizeToolList(descriptors) {
|
|
1688
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1689
|
-
const out = [];
|
|
1690
|
-
for (const d of descriptors) {
|
|
1691
|
-
if (typeof d !== "string" || !d.trim()) continue;
|
|
1692
|
-
const name = resolveToolDescriptor(d);
|
|
1693
|
-
if (!seen.has(name)) {
|
|
1694
|
-
seen.add(name);
|
|
1695
|
-
out.push(name);
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
return out;
|
|
1699
|
-
}
|
|
1700
|
-
function fileDescriptorToPackagePrefix(descriptor) {
|
|
1701
|
-
const path = parseToolPath(descriptor.trim());
|
|
1702
|
-
if (!path || path.protocol !== "file") return "";
|
|
1703
|
-
const pathPart = `${path.scope}/${path.packageWithVersion}`;
|
|
1704
|
-
const normalized = normalizeToolName(pathPart);
|
|
1705
|
-
if (!normalized) return "";
|
|
1706
|
-
return "file." + normalized;
|
|
1707
|
-
}
|
|
1708
|
-
function fileDescriptorToRegistryPrefix(descriptor) {
|
|
1709
|
-
const prefix = fileDescriptorToPackagePrefix(descriptor);
|
|
1710
|
-
return prefix ? prefix + "." : "";
|
|
1711
|
-
}
|
|
1712
|
-
function loadToolConfig(toolYamlPath) {
|
|
1713
|
-
const abs = resolve(toolYamlPath);
|
|
1714
|
-
const raw = readFileSync(abs, "utf8");
|
|
1715
|
-
const parsed = parseYamlContent(raw, {
|
|
1716
|
-
substituteEnv: false
|
|
1717
|
-
});
|
|
1718
|
-
if (!parsed || typeof parsed !== "object") return {};
|
|
1719
|
-
const toolsBlock = parsed.tools;
|
|
1720
|
-
if (toolsBlock != null && typeof toolsBlock === "object" && !Array.isArray(toolsBlock)) {
|
|
1721
|
-
const toolDefaults = toolsBlock.defaults != null && typeof toolsBlock.defaults === "object" && !Array.isArray(toolsBlock.defaults) ? toolsBlock.defaults : void 0;
|
|
1722
|
-
const packageToolDefaults2 = toolsBlock.packages != null && typeof toolsBlock.packages === "object" && !Array.isArray(toolsBlock.packages) ? toolsBlock.packages : void 0;
|
|
1723
|
-
const list2 = Array.isArray(toolsBlock.list) && toolsBlock.list.length > 0 ? toolsBlock.list : void 0;
|
|
1724
|
-
return {
|
|
1725
|
-
tools: list2 ?? (packageToolDefaults2 ? Object.keys(packageToolDefaults2) : void 0),
|
|
1726
|
-
sandboxedPath: typeof toolsBlock.sandboxedPath === "string" ? toolsBlock.sandboxedPath : parsed.sandboxedPath,
|
|
1727
|
-
enableSandboxValidation: typeof toolsBlock.enableSandboxValidation === "boolean" ? toolsBlock.enableSandboxValidation : parsed.enableSandboxValidation,
|
|
1728
|
-
allowedHosts: Array.isArray(toolsBlock.allowedHosts) ? toolsBlock.allowedHosts : parsed.allowedHosts,
|
|
1729
|
-
blockedHosts: Array.isArray(toolsBlock.blockedHosts) ? toolsBlock.blockedHosts : parsed.blockedHosts,
|
|
1730
|
-
blockedCidrs: Array.isArray(toolsBlock.blockedCidrs) ? toolsBlock.blockedCidrs : parsed.blockedCidrs,
|
|
1731
|
-
toolDefaults,
|
|
1732
|
-
packageToolDefaults: packageToolDefaults2
|
|
1733
|
-
};
|
|
1734
|
-
}
|
|
1735
|
-
const packageToolDefaults = typeof parsed.packageToolDefaults === "object" && !Array.isArray(parsed.packageToolDefaults) ? parsed.packageToolDefaults : void 0;
|
|
1736
|
-
const list = Array.isArray(parsed.tools) && parsed.tools.length > 0 ? parsed.tools : void 0;
|
|
1737
|
-
return {
|
|
1738
|
-
tools: list ?? (packageToolDefaults ? Object.keys(packageToolDefaults) : void 0),
|
|
1739
|
-
sandboxedPath: parsed.sandboxedPath,
|
|
1740
|
-
enableSandboxValidation: typeof parsed.enableSandboxValidation === "boolean" ? parsed.enableSandboxValidation : void 0,
|
|
1741
|
-
allowedHosts: Array.isArray(parsed.allowedHosts) ? parsed.allowedHosts : void 0,
|
|
1742
|
-
blockedHosts: Array.isArray(parsed.blockedHosts) ? parsed.blockedHosts : void 0,
|
|
1743
|
-
blockedCidrs: Array.isArray(parsed.blockedCidrs) ? parsed.blockedCidrs : void 0,
|
|
1744
|
-
toolDefaults: typeof parsed.toolDefaults === "object" && !Array.isArray(parsed.toolDefaults) ? parsed.toolDefaults : void 0,
|
|
1745
|
-
packageToolDefaults
|
|
1746
|
-
};
|
|
1747
|
-
}
|
|
1748
|
-
function resolveSandboxedPath2(toolYamlPath, sandboxedPath) {
|
|
1749
|
-
const configDir = dirname(resolve(toolYamlPath));
|
|
1750
|
-
return resolveConfigPath(sandboxedPath, configDir, {
|
|
1751
|
-
expandHome: true
|
|
1752
|
-
});
|
|
1753
|
-
}
|
|
1754
|
-
var CACHE_SUBDIR = ".agent/cache";
|
|
1755
|
-
function getCacheBaseFromToolConfig(toolYamlPath) {
|
|
1756
|
-
const config = loadToolConfig(toolYamlPath);
|
|
1757
|
-
if (!config.sandboxedPath || typeof config.sandboxedPath !== "string") return void 0;
|
|
1758
|
-
const sandboxRoot = resolveSandboxedPath2(toolYamlPath, config.sandboxedPath);
|
|
1759
|
-
return join(sandboxRoot, CACHE_SUBDIR);
|
|
1760
|
-
}
|
|
1761
|
-
function findAndLoadToolConfig(dir) {
|
|
1762
|
-
const resolvedDir = resolve(dir);
|
|
1763
|
-
const candidates = [join(resolvedDir, "tool.yaml"), join(resolvedDir, ".tool.yaml")];
|
|
1764
|
-
for (const p of candidates) {
|
|
1765
|
-
if (existsSync(p)) {
|
|
1766
|
-
const config = loadToolConfig(p);
|
|
1767
|
-
return { ...config, configPath: p };
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
return {};
|
|
1771
|
-
}
|
|
1772
|
-
var requireFromPackage = createRequire(import.meta.url);
|
|
1773
|
-
function getProjectRequire() {
|
|
1774
|
-
const cwd = process.cwd();
|
|
1775
|
-
if (existsSync(join(cwd, "package.json"))) return createRequire(join(cwd, "package.json"));
|
|
1776
|
-
if (existsSync(join(cwd, "tool.yaml"))) return createRequire(join(cwd, "tool.yaml"));
|
|
1777
|
-
return null;
|
|
1778
|
-
}
|
|
1779
|
-
var DEFAULT_EXTENSION_PACKAGES = [];
|
|
1780
|
-
function getInstalledPackageVersion(packageName) {
|
|
1781
|
-
const projectRequire = getProjectRequire();
|
|
1782
|
-
const requirers = [requireFromPackage];
|
|
1783
|
-
if (projectRequire) requirers.push(projectRequire);
|
|
1784
|
-
for (const req of requirers) {
|
|
1785
|
-
try {
|
|
1786
|
-
const pkgJsonPath = req.resolve(`${packageName}/package.json`);
|
|
1787
|
-
const json = readFileSync(pkgJsonPath, "utf-8");
|
|
1788
|
-
const pkg = JSON.parse(json);
|
|
1789
|
-
return pkg.version ?? null;
|
|
1790
|
-
} catch {
|
|
1791
|
-
continue;
|
|
1792
|
-
}
|
|
1793
|
-
}
|
|
1794
|
-
return null;
|
|
1756
|
+
var DEFAULT_EXTENSION_PACKAGES = [];
|
|
1757
|
+
function getInstalledPackageVersion(packageName) {
|
|
1758
|
+
const projectRequire = getProjectRequire();
|
|
1759
|
+
const requirers = [requireFromPackage];
|
|
1760
|
+
if (projectRequire) requirers.push(projectRequire);
|
|
1761
|
+
for (const req of requirers) {
|
|
1762
|
+
try {
|
|
1763
|
+
const pkgJsonPath = req.resolve(`${packageName}/package.json`);
|
|
1764
|
+
const json = readFileSync(pkgJsonPath, "utf-8");
|
|
1765
|
+
const pkg = JSON.parse(json);
|
|
1766
|
+
return pkg.version ?? null;
|
|
1767
|
+
} catch {
|
|
1768
|
+
continue;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
return null;
|
|
1795
1772
|
}
|
|
1796
1773
|
function getRegisterFn(mod) {
|
|
1797
1774
|
return mod?.register ?? mod?.registerCoreTools;
|
|
@@ -2060,13 +2037,479 @@ async function createRuntimeFromConfig(options = {}) {
|
|
|
2060
2037
|
return createRuntimeFromConfigSync(options);
|
|
2061
2038
|
}
|
|
2062
2039
|
|
|
2040
|
+
// src/api/expose/openapi.ts
|
|
2041
|
+
function toolNameToSlug(name) {
|
|
2042
|
+
return name.replace(/\./g, "~");
|
|
2043
|
+
}
|
|
2044
|
+
function slugToToolName(slug) {
|
|
2045
|
+
return slug.replace(/~/g, ".");
|
|
2046
|
+
}
|
|
2047
|
+
function toolSchemaKey(name) {
|
|
2048
|
+
return `Tool_${name.replace(/[^a-zA-Z0-9_]/g, "_")}`;
|
|
2049
|
+
}
|
|
2050
|
+
var resultSchema = {
|
|
2051
|
+
type: "object",
|
|
2052
|
+
properties: {
|
|
2053
|
+
result: { description: "Tool return value", additionalProperties: true }
|
|
2054
|
+
}
|
|
2055
|
+
};
|
|
2056
|
+
var errorSchema = {
|
|
2057
|
+
type: "object",
|
|
2058
|
+
properties: {
|
|
2059
|
+
error: { type: "string" },
|
|
2060
|
+
kind: { type: "string" },
|
|
2061
|
+
details: { type: "object", additionalProperties: true }
|
|
2062
|
+
}
|
|
2063
|
+
};
|
|
2064
|
+
function toolsToOpenAPISpec(registry, options = {}) {
|
|
2065
|
+
const title = options.title ?? "Tool API";
|
|
2066
|
+
const version = options.version ?? "1.0.0";
|
|
2067
|
+
const basePath = (options.basePath ?? "").replace(/\/$/, "");
|
|
2068
|
+
const specs = registry.snapshot().map(enrichSpecWithCanonicalSchema);
|
|
2069
|
+
const toolNamesSchema = {
|
|
2070
|
+
type: "object",
|
|
2071
|
+
required: ["tools"],
|
|
2072
|
+
properties: {
|
|
2073
|
+
tools: {
|
|
2074
|
+
type: "array",
|
|
2075
|
+
items: {
|
|
2076
|
+
type: "object",
|
|
2077
|
+
properties: {
|
|
2078
|
+
name: { type: "string" },
|
|
2079
|
+
description: { type: "string" },
|
|
2080
|
+
kind: { type: "string" }
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
};
|
|
2086
|
+
const invokeRequestBody = {
|
|
2087
|
+
type: "object",
|
|
2088
|
+
required: ["tool", "args"],
|
|
2089
|
+
properties: {
|
|
2090
|
+
tool: { type: "string", description: "Tool name (e.g. from GET /tools)" },
|
|
2091
|
+
args: {
|
|
2092
|
+
type: "object",
|
|
2093
|
+
description: "Tool arguments (schema per tool; use per-tool paths for typed schema)",
|
|
2094
|
+
additionalProperties: true
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
};
|
|
2098
|
+
const prefix = basePath ? `${basePath}/` : "/";
|
|
2099
|
+
const paths = {
|
|
2100
|
+
[`${prefix}tools`]: {
|
|
2101
|
+
get: {
|
|
2102
|
+
summary: "List tools",
|
|
2103
|
+
description: "Returns all registered tool names and descriptions.",
|
|
2104
|
+
operationId: "listTools",
|
|
2105
|
+
responses: {
|
|
2106
|
+
"200": {
|
|
2107
|
+
description: "List of tools",
|
|
2108
|
+
content: {
|
|
2109
|
+
"application/json": {
|
|
2110
|
+
schema: toolNamesSchema
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
},
|
|
2117
|
+
[`${prefix}invoke`]: {
|
|
2118
|
+
post: {
|
|
2119
|
+
summary: "Invoke a tool (generic)",
|
|
2120
|
+
description: "Call any tool by name with body { tool, args }. For typed schemas use POST /invoke/{toolSlug}.",
|
|
2121
|
+
operationId: "invokeTool",
|
|
2122
|
+
requestBody: {
|
|
2123
|
+
required: true,
|
|
2124
|
+
content: {
|
|
2125
|
+
"application/json": {
|
|
2126
|
+
schema: invokeRequestBody
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
},
|
|
2130
|
+
responses: {
|
|
2131
|
+
"200": {
|
|
2132
|
+
description: "Tool result",
|
|
2133
|
+
content: { "application/json": { schema: resultSchema } }
|
|
2134
|
+
},
|
|
2135
|
+
"400": {
|
|
2136
|
+
description: "Bad request",
|
|
2137
|
+
content: { "application/json": { schema: errorSchema } }
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
const schemaEntries = [];
|
|
2144
|
+
for (const s of specs) {
|
|
2145
|
+
const key = toolSchemaKey(s.name);
|
|
2146
|
+
schemaEntries.push([key, s.inputSchema]);
|
|
2147
|
+
const slug = toolNameToSlug(s.name);
|
|
2148
|
+
paths[`${prefix}invoke/${slug}`] = {
|
|
2149
|
+
post: {
|
|
2150
|
+
summary: s.description ?? s.name,
|
|
2151
|
+
description: `Invoke tool \`${s.name}\`. Request body is the tool's arguments (JSON Schema below).`,
|
|
2152
|
+
operationId: `invoke_${key}`,
|
|
2153
|
+
requestBody: {
|
|
2154
|
+
required: true,
|
|
2155
|
+
content: {
|
|
2156
|
+
"application/json": {
|
|
2157
|
+
schema: { $ref: `#/components/schemas/${key}` }
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
},
|
|
2161
|
+
responses: {
|
|
2162
|
+
"200": {
|
|
2163
|
+
description: "Tool result",
|
|
2164
|
+
content: { "application/json": { schema: resultSchema } }
|
|
2165
|
+
},
|
|
2166
|
+
"400": {
|
|
2167
|
+
description: "Bad request (invalid args or tool error)",
|
|
2168
|
+
content: { "application/json": { schema: errorSchema } }
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
return {
|
|
2175
|
+
openapi: "3.0.3",
|
|
2176
|
+
info: { title, version },
|
|
2177
|
+
paths,
|
|
2178
|
+
components: {
|
|
2179
|
+
schemas: Object.fromEntries(schemaEntries)
|
|
2180
|
+
}
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
// src/api/expose/openapiHttp.ts
|
|
2185
|
+
var DEFAULT_CTX = {
|
|
2186
|
+
requestId: `http-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
2187
|
+
taskId: `task-${Date.now()}`,
|
|
2188
|
+
permissions: [
|
|
2189
|
+
"read:web",
|
|
2190
|
+
"read:fs",
|
|
2191
|
+
"write:fs",
|
|
2192
|
+
"read:db",
|
|
2193
|
+
"write:db",
|
|
2194
|
+
"network",
|
|
2195
|
+
"workflow",
|
|
2196
|
+
"danger:destructive"
|
|
2197
|
+
]
|
|
2198
|
+
};
|
|
2199
|
+
function parseBody(req) {
|
|
2200
|
+
return new Promise((resolve4, reject) => {
|
|
2201
|
+
const chunks = [];
|
|
2202
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
2203
|
+
req.on("end", () => {
|
|
2204
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
2205
|
+
if (!raw.trim()) {
|
|
2206
|
+
resolve4({});
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
try {
|
|
2210
|
+
resolve4(JSON.parse(raw));
|
|
2211
|
+
} catch {
|
|
2212
|
+
reject(new Error("Invalid JSON body"));
|
|
2213
|
+
}
|
|
2214
|
+
});
|
|
2215
|
+
req.on("error", reject);
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
function sendJson(res, status, data) {
|
|
2219
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
2220
|
+
res.end(JSON.stringify(data));
|
|
2221
|
+
}
|
|
2222
|
+
function swaggerUiHtml(specUrl) {
|
|
2223
|
+
const specUrlEscaped = specUrl.replace(/"/g, """);
|
|
2224
|
+
return `<!DOCTYPE html>
|
|
2225
|
+
<html lang="en">
|
|
2226
|
+
<head>
|
|
2227
|
+
<meta charset="UTF-8">
|
|
2228
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
2229
|
+
<title>Tool API \u2013 Swagger UI</title>
|
|
2230
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
|
2231
|
+
</head>
|
|
2232
|
+
<body>
|
|
2233
|
+
<div id="swagger-ui"></div>
|
|
2234
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js" crossorigin></script>
|
|
2235
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-standalone-preset.js" crossorigin></script>
|
|
2236
|
+
<script>
|
|
2237
|
+
window.onload = function() {
|
|
2238
|
+
window.ui = SwaggerUIBundle({
|
|
2239
|
+
url: "${specUrlEscaped}",
|
|
2240
|
+
dom_id: "#swagger-ui",
|
|
2241
|
+
deepLinking: true,
|
|
2242
|
+
presets: [
|
|
2243
|
+
SwaggerUIBundle.presets.apis,
|
|
2244
|
+
SwaggerUIStandalonePreset
|
|
2245
|
+
],
|
|
2246
|
+
layout: "StandaloneLayout"
|
|
2247
|
+
});
|
|
2248
|
+
};
|
|
2249
|
+
</script>
|
|
2250
|
+
</body>
|
|
2251
|
+
</html>`;
|
|
2252
|
+
}
|
|
2253
|
+
function createOpenAPIHttpServer(runtime, options = {}) {
|
|
2254
|
+
const basePath = (options.basePath ?? "").replace(/\/$/, "");
|
|
2255
|
+
const ctxFactory = options.execContextFactory ?? (() => ({ ...DEFAULT_CTX }));
|
|
2256
|
+
const server = createServer(async (req, res) => {
|
|
2257
|
+
const url = req.url ?? "/";
|
|
2258
|
+
const path = url.split("?")[0] ?? "/";
|
|
2259
|
+
const norm = basePath ? path === basePath ? "" : path.replace(basePath, "") || "/" : path;
|
|
2260
|
+
try {
|
|
2261
|
+
if (req.method === "GET" && (norm === "/" || norm === "/swagger")) {
|
|
2262
|
+
const specPath = basePath ? `${basePath}/openapi.json` : "/openapi.json";
|
|
2263
|
+
const html = swaggerUiHtml(specPath);
|
|
2264
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
2265
|
+
res.end(html);
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
if (req.method === "GET" && (norm === "/openapi.json" || norm === "/spec")) {
|
|
2269
|
+
const spec = toolsToOpenAPISpec(runtime.getRegistry(), {
|
|
2270
|
+
title: "Tool API",
|
|
2271
|
+
version: "1.0.0",
|
|
2272
|
+
basePath: basePath || void 0
|
|
2273
|
+
});
|
|
2274
|
+
sendJson(res, 200, spec);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
if (req.method === "GET" && norm === "/tools") {
|
|
2278
|
+
const { enrichSpecWithCanonicalSchema: enrichSpecWithCanonicalSchema2 } = await import('./canonicalCoreSchemas-PHGTNPN5.js');
|
|
2279
|
+
const specs = runtime.getRegistry().snapshot().map(enrichSpecWithCanonicalSchema2);
|
|
2280
|
+
const tools = specs.map((s) => ({
|
|
2281
|
+
name: s.name,
|
|
2282
|
+
description: s.description,
|
|
2283
|
+
kind: s.kind,
|
|
2284
|
+
inputSchema: s.inputSchema
|
|
2285
|
+
}));
|
|
2286
|
+
sendJson(res, 200, { tools });
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
if (req.method === "POST" && norm === "/invoke") {
|
|
2290
|
+
const body = await parseBody(req);
|
|
2291
|
+
const tool = body?.tool;
|
|
2292
|
+
const args = body?.args ?? {};
|
|
2293
|
+
if (typeof tool !== "string" || !tool.trim()) {
|
|
2294
|
+
sendJson(res, 400, { error: "Missing or invalid 'tool' in body", kind: "BAD_REQUEST" });
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
const ctx = ctxFactory(req);
|
|
2298
|
+
const result = await runtime.invoke(
|
|
2299
|
+
{ tool: tool.trim(), args, purpose: "openapi" },
|
|
2300
|
+
ctx
|
|
2301
|
+
);
|
|
2302
|
+
if (result.ok) {
|
|
2303
|
+
sendJson(res, 200, { result: result.result });
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
sendJson(res, 400, {
|
|
2307
|
+
error: result.error?.message ?? "Tool failed",
|
|
2308
|
+
kind: result.error?.kind,
|
|
2309
|
+
details: result.error?.details
|
|
2310
|
+
});
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
if (req.method === "POST" && norm.startsWith("/invoke/") && norm.length > "/invoke/".length) {
|
|
2314
|
+
const slug = norm.slice("/invoke/".length);
|
|
2315
|
+
const toolName = slugToToolName(slug);
|
|
2316
|
+
let args;
|
|
2317
|
+
try {
|
|
2318
|
+
args = await parseBody(req);
|
|
2319
|
+
} catch {
|
|
2320
|
+
sendJson(res, 400, { error: "Invalid JSON body", kind: "BAD_REQUEST" });
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
const ctx = ctxFactory(req);
|
|
2324
|
+
const result = await runtime.invoke(
|
|
2325
|
+
{ tool: toolName, args: args ?? {}, purpose: "openapi" },
|
|
2326
|
+
ctx
|
|
2327
|
+
);
|
|
2328
|
+
if (result.ok) {
|
|
2329
|
+
sendJson(res, 200, { result: result.result });
|
|
2330
|
+
return;
|
|
2331
|
+
}
|
|
2332
|
+
sendJson(res, 400, {
|
|
2333
|
+
error: result.error?.message ?? "Tool failed",
|
|
2334
|
+
kind: result.error?.kind,
|
|
2335
|
+
details: result.error?.details
|
|
2336
|
+
});
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2340
|
+
res.end(JSON.stringify({ error: "Not found", path: norm }));
|
|
2341
|
+
} catch (err) {
|
|
2342
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2343
|
+
sendJson(res, 500, { error: message, kind: "INTERNAL_ERROR" });
|
|
2344
|
+
}
|
|
2345
|
+
});
|
|
2346
|
+
return server;
|
|
2347
|
+
}
|
|
2348
|
+
function listenOpenAPIHttpServer(server, options = {}) {
|
|
2349
|
+
return new Promise((resolve4, reject) => {
|
|
2350
|
+
const port = options.port ?? 0;
|
|
2351
|
+
const host = options.host ?? "localhost";
|
|
2352
|
+
server.listen(port, host, () => {
|
|
2353
|
+
const addr = server.address();
|
|
2354
|
+
const actualPort = typeof addr === "object" && addr?.port != null ? addr.port : port;
|
|
2355
|
+
resolve4({ port: actualPort, host });
|
|
2356
|
+
});
|
|
2357
|
+
server.on("error", reject);
|
|
2358
|
+
});
|
|
2359
|
+
}
|
|
2360
|
+
async function createHttpService(runtimeOrConfig, options = {}) {
|
|
2361
|
+
const runtime = "invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function" ? runtimeOrConfig : (await createRuntimeFromConfig(runtimeOrConfig)).runtime;
|
|
2362
|
+
const server = createOpenAPIHttpServer(runtime, options);
|
|
2363
|
+
const openApiSpec = toolsToOpenAPISpec(runtime.getRegistry(), {
|
|
2364
|
+
title: options.title ?? "Tool API",
|
|
2365
|
+
version: options.version ?? "1.0.0",
|
|
2366
|
+
basePath: options.basePath
|
|
2367
|
+
});
|
|
2368
|
+
return {
|
|
2369
|
+
server,
|
|
2370
|
+
openApiSpec,
|
|
2371
|
+
listen: (listenOpts) => listenOpenAPIHttpServer(server, listenOpts)
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2063
2375
|
// src/tools/mcp/types.ts
|
|
2064
2376
|
var MCP_KIND = "mcp";
|
|
2065
2377
|
|
|
2378
|
+
// src/api/expose/mcpServer.ts
|
|
2379
|
+
var DEFAULT_CTX2 = {
|
|
2380
|
+
requestId: `mcp-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
2381
|
+
taskId: `task-${Date.now()}`,
|
|
2382
|
+
permissions: [
|
|
2383
|
+
"read:web",
|
|
2384
|
+
"read:fs",
|
|
2385
|
+
"write:fs",
|
|
2386
|
+
"read:db",
|
|
2387
|
+
"write:db",
|
|
2388
|
+
"network",
|
|
2389
|
+
"workflow",
|
|
2390
|
+
"danger:destructive"
|
|
2391
|
+
]
|
|
2392
|
+
};
|
|
2393
|
+
function toMcpToolName(registryName) {
|
|
2394
|
+
return normalizeToolName(registryName);
|
|
2395
|
+
}
|
|
2396
|
+
async function createMcpServerWithTools(runtime, options) {
|
|
2397
|
+
const { McpServer } = await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
2398
|
+
const name = options.name ?? "agent-tool";
|
|
2399
|
+
const version = options.version ?? "1.0.0";
|
|
2400
|
+
const ctxFactory = options.execContextFactory ?? (() => ({ ...DEFAULT_CTX2 }));
|
|
2401
|
+
const server = new McpServer({ name, version });
|
|
2402
|
+
const registry = runtime.getRegistry();
|
|
2403
|
+
const specs = registry.snapshot();
|
|
2404
|
+
for (const spec of specs) {
|
|
2405
|
+
const mcpName = toMcpToolName(spec.name);
|
|
2406
|
+
server.registerTool(
|
|
2407
|
+
mcpName,
|
|
2408
|
+
{
|
|
2409
|
+
description: spec.description ?? `Tool: ${spec.name}`,
|
|
2410
|
+
inputSchema: spec.inputSchema,
|
|
2411
|
+
_meta: spec._meta
|
|
2412
|
+
},
|
|
2413
|
+
async (args) => {
|
|
2414
|
+
const ctx = ctxFactory();
|
|
2415
|
+
const result = await runtime.invoke(
|
|
2416
|
+
{ tool: spec.name, args: args ?? {}, purpose: MCP_KIND },
|
|
2417
|
+
ctx
|
|
2418
|
+
);
|
|
2419
|
+
if (result.ok) {
|
|
2420
|
+
return { content: [{ type: "text", text: JSON.stringify(result.result) }] };
|
|
2421
|
+
}
|
|
2422
|
+
const err = result.error;
|
|
2423
|
+
return {
|
|
2424
|
+
content: [
|
|
2425
|
+
{
|
|
2426
|
+
type: "text",
|
|
2427
|
+
text: JSON.stringify({ error: err?.message ?? "Tool failed", kind: err?.kind })
|
|
2428
|
+
}
|
|
2429
|
+
],
|
|
2430
|
+
isError: true
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
return { server };
|
|
2436
|
+
}
|
|
2437
|
+
async function createMCPServer(runtimeOrConfig, options = {}) {
|
|
2438
|
+
const runtime = "invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function" ? runtimeOrConfig : (await createRuntimeFromConfig(runtimeOrConfig)).runtime;
|
|
2439
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
2440
|
+
const { server } = await createMcpServerWithTools(runtime, options);
|
|
2441
|
+
return {
|
|
2442
|
+
server,
|
|
2443
|
+
async connectStdio() {
|
|
2444
|
+
const transport = new StdioServerTransport();
|
|
2445
|
+
await server.connect(transport);
|
|
2446
|
+
}
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2449
|
+
function createMCPStreamableHttpHandler(runtimeOrConfig, options = {}) {
|
|
2450
|
+
if ("invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function") {
|
|
2451
|
+
const runtime = runtimeOrConfig;
|
|
2452
|
+
return async function streamableHttpHandler(req, res, parsedBody) {
|
|
2453
|
+
const { StreamableHTTPServerTransport } = await import('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
2454
|
+
const { server } = await createMcpServerWithTools(runtime, options);
|
|
2455
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
2456
|
+
await server.connect(transport);
|
|
2457
|
+
const onClose = () => {
|
|
2458
|
+
transport.close().catch(() => {
|
|
2459
|
+
});
|
|
2460
|
+
server.close().catch(() => {
|
|
2461
|
+
});
|
|
2462
|
+
res.removeListener("close", onClose);
|
|
2463
|
+
res.removeListener("finish", onClose);
|
|
2464
|
+
};
|
|
2465
|
+
res.once("close", onClose);
|
|
2466
|
+
res.once("finish", onClose);
|
|
2467
|
+
await transport.handleRequest(
|
|
2468
|
+
req,
|
|
2469
|
+
res,
|
|
2470
|
+
parsedBody
|
|
2471
|
+
);
|
|
2472
|
+
};
|
|
2473
|
+
}
|
|
2474
|
+
return (async () => {
|
|
2475
|
+
const { runtime } = await createRuntimeFromConfig(runtimeOrConfig);
|
|
2476
|
+
return createMCPStreamableHttpHandler(runtime, options);
|
|
2477
|
+
})();
|
|
2478
|
+
}
|
|
2479
|
+
async function createMCPServerStreamableHttp(runtimeOrConfig, options = {}) {
|
|
2480
|
+
const path = options.path ?? "/mcp";
|
|
2481
|
+
const host = options.host ?? "127.0.0.1";
|
|
2482
|
+
const port = options.port ?? 3e3;
|
|
2483
|
+
const { createMcpExpressApp } = await import('@modelcontextprotocol/sdk/server/express.js');
|
|
2484
|
+
const handler = "invoke" in runtimeOrConfig && typeof runtimeOrConfig.invoke === "function" ? createMCPStreamableHttpHandler(runtimeOrConfig, options) : await createMCPStreamableHttpHandler(runtimeOrConfig, options);
|
|
2485
|
+
const app = createMcpExpressApp({ host });
|
|
2486
|
+
app.post(path, handler);
|
|
2487
|
+
return {
|
|
2488
|
+
app,
|
|
2489
|
+
path,
|
|
2490
|
+
async listen(listenPort, listenHost) {
|
|
2491
|
+
const p = listenPort ?? port;
|
|
2492
|
+
const h = listenHost ?? host;
|
|
2493
|
+
return new Promise((resolve4, reject) => {
|
|
2494
|
+
const server = app.listen(p, h, () => {
|
|
2495
|
+
const addr = server.address();
|
|
2496
|
+
const actualPort = typeof addr === "object" && addr !== null && "port" in addr ? addr.port : p;
|
|
2497
|
+
resolve4({ url: `http://${h}:${actualPort}${path}`, port: actualPort });
|
|
2498
|
+
});
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
async function runMCPServerOverStdio(runtime, options = {}) {
|
|
2504
|
+
const result = await createMCPServer(runtime, options);
|
|
2505
|
+
await result.connectStdio();
|
|
2506
|
+
return result;
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2066
2509
|
// src/tools/langchain/types.ts
|
|
2067
2510
|
var LANGCHAIN_KIND = "langchain";
|
|
2068
2511
|
var LANGCHAIN_DIR_NAME = "langchain";
|
|
2069
2512
|
|
|
2070
|
-
export {
|
|
2071
|
-
//# sourceMappingURL=chunk-
|
|
2072
|
-
//# sourceMappingURL=chunk-
|
|
2513
|
+
export { LANGCHAIN_DIR_NAME, LANGCHAIN_KIND, MCP_KIND, PTCRuntime, createHttpService, createMCPServer, createMCPServerStreamableHttp, createMCPStreamableHttpHandler, createRuntimeFromConfig, createRuntimeFromConfigSync, expandToolDescriptorsToRegistryNames, fileDescriptorToPackagePrefix, findAndLoadToolConfig, getDisplayScope, isBarePackageDescriptor, loadToolConfig, npmDescriptorToPackagePrefixWithVersion, resolveSandboxedPath, resolveSandboxedPath2, resolveToolDescriptor, runMCPServerOverStdio, setSandboxValidationEnabled };
|
|
2514
|
+
//# sourceMappingURL=chunk-2ZPDD7ZO.js.map
|
|
2515
|
+
//# sourceMappingURL=chunk-2ZPDD7ZO.js.map
|