opentool 0.8.6 → 0.8.8
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 +3 -0
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +99 -77
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +4 -42
- package/dist/index.js +54 -32
- package/dist/index.js.map +1 -1
- package/dist/{validate-D5sE9GUm.d.ts → validate-3e5UvzfQ.d.ts} +51 -1
- package/package.json +1 -1
- package/templates/base/package.json +1 -1
- package/templates/base/tools/aave-stake.ts +1 -0
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ For private tools, say for internal trading apps:
|
|
|
73
73
|
|
|
74
74
|
- GET-only (scheduled default profile)
|
|
75
75
|
- POST-only (one-off, parameterized with Zod)
|
|
76
|
+
- `profile.category` defaults to `tracker` if omitted; set to `strategy` for PnL/automation tools.
|
|
76
77
|
|
|
77
78
|
GET-only (scheduled default)
|
|
78
79
|
|
|
@@ -80,6 +81,7 @@ GET-only (scheduled default)
|
|
|
80
81
|
// tools/aave-stake.ts
|
|
81
82
|
export const profile = {
|
|
82
83
|
description: "Stake 100 USDC daily at 12:00 UTC",
|
|
84
|
+
category: "strategy",
|
|
83
85
|
fixedAmount: "100",
|
|
84
86
|
tokenSymbol: "USDC",
|
|
85
87
|
schedule: { cron: "0 12 * * *", enabled: false },
|
|
@@ -105,6 +107,7 @@ import { z } from "zod";
|
|
|
105
107
|
|
|
106
108
|
export const profile = {
|
|
107
109
|
description: "Unstake USDC on demand",
|
|
110
|
+
category: "tracker",
|
|
108
111
|
notifyEmail: true,
|
|
109
112
|
};
|
|
110
113
|
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { M as Metadata, I as InternalToolDefinition } from '../validate-
|
|
3
|
-
export { G as GenerateMetadataOptions, a as GenerateMetadataResult, V as ValidateOptions, b as generateMetadata, g as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, c as validateFullCommand } from '../validate-
|
|
2
|
+
import { M as Metadata, I as InternalToolDefinition } from '../validate-3e5UvzfQ.js';
|
|
3
|
+
export { G as GenerateMetadataOptions, a as GenerateMetadataResult, V as ValidateOptions, b as generateMetadata, g as generateMetadataCommand, l as loadAndValidateTools, v as validateCommand, c as validateFullCommand } from '../validate-3e5UvzfQ.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import '../x402/index.js';
|
|
6
6
|
import 'viem';
|
package/dist/cli/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import * as path6 from 'path';
|
|
3
|
+
import path6__default from 'path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
2
5
|
import { program } from 'commander';
|
|
3
6
|
import * as fs4 from 'fs';
|
|
4
7
|
import { promises } from 'fs';
|
|
5
|
-
import * as path5 from 'path';
|
|
6
|
-
import path5__default from 'path';
|
|
7
8
|
import { tmpdir } from 'os';
|
|
8
9
|
import { build } from 'esbuild';
|
|
9
10
|
import { z } from 'zod';
|
|
10
11
|
import { createRequire } from 'module';
|
|
11
|
-
import { fileURLToPath, pathToFileURL } from 'url';
|
|
12
12
|
import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema';
|
|
13
13
|
import 'viem';
|
|
14
14
|
import 'viem/accounts';
|
|
@@ -19,8 +19,10 @@ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprot
|
|
|
19
19
|
import * as http2 from 'http';
|
|
20
20
|
import dotenv from 'dotenv';
|
|
21
21
|
|
|
22
|
+
var getFilename = () => fileURLToPath(import.meta.url);
|
|
23
|
+
var __filename = /* @__PURE__ */ getFilename();
|
|
22
24
|
function resolveTsconfig(projectRoot) {
|
|
23
|
-
const candidate =
|
|
25
|
+
const candidate = path6.join(projectRoot, "tsconfig.json");
|
|
24
26
|
if (fs4.existsSync(candidate)) {
|
|
25
27
|
return candidate;
|
|
26
28
|
}
|
|
@@ -31,7 +33,7 @@ async function transpileWithEsbuild(options) {
|
|
|
31
33
|
throw new Error("No entry points provided for esbuild transpilation");
|
|
32
34
|
}
|
|
33
35
|
const projectRoot = options.projectRoot;
|
|
34
|
-
const tempBase = options.outDir ?? fs4.mkdtempSync(
|
|
36
|
+
const tempBase = options.outDir ?? fs4.mkdtempSync(path6.join(tmpdir(), "opentool-"));
|
|
35
37
|
if (!fs4.existsSync(tempBase)) {
|
|
36
38
|
fs4.mkdirSync(tempBase, { recursive: true });
|
|
37
39
|
}
|
|
@@ -75,7 +77,7 @@ async function transpileWithEsbuild(options) {
|
|
|
75
77
|
}
|
|
76
78
|
await build(buildOptions);
|
|
77
79
|
if (options.format === "esm") {
|
|
78
|
-
const packageJsonPath =
|
|
80
|
+
const packageJsonPath = path6.join(tempBase, "package.json");
|
|
79
81
|
if (!fs4.existsSync(packageJsonPath)) {
|
|
80
82
|
fs4.writeFileSync(packageJsonPath, JSON.stringify({ type: "module" }), "utf8");
|
|
81
83
|
}
|
|
@@ -139,6 +141,7 @@ var DiscoveryMetadataSchema = z.object({
|
|
|
139
141
|
compatibility: z.record(z.string(), z.any()).optional(),
|
|
140
142
|
documentation: z.union([z.string(), z.array(z.string())]).optional()
|
|
141
143
|
}).catchall(z.any());
|
|
144
|
+
var ToolCategorySchema = z.enum(["strategy", "tracker"]);
|
|
142
145
|
var ToolMetadataOverridesSchema = z.object({
|
|
143
146
|
name: z.string().optional(),
|
|
144
147
|
description: z.string().optional(),
|
|
@@ -155,7 +158,8 @@ var ToolSchema = z.object({
|
|
|
155
158
|
payment: PaymentConfigSchema.optional(),
|
|
156
159
|
discovery: DiscoveryMetadataSchema.optional(),
|
|
157
160
|
chains: z.array(z.union([z.string(), z.number()])).optional(),
|
|
158
|
-
notifyEmail: z.boolean().optional()
|
|
161
|
+
notifyEmail: z.boolean().optional(),
|
|
162
|
+
category: ToolCategorySchema.optional()
|
|
159
163
|
}).strict();
|
|
160
164
|
var MetadataSchema = z.object({
|
|
161
165
|
metadataSpecVersion: z.string().optional(),
|
|
@@ -206,10 +210,12 @@ var BuildMetadataSchema = z.object({
|
|
|
206
210
|
animation_url: z.string().optional(),
|
|
207
211
|
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
208
212
|
}).strict();
|
|
209
|
-
createRequire(
|
|
213
|
+
createRequire(
|
|
214
|
+
typeof __filename !== "undefined" ? __filename : import.meta.url
|
|
215
|
+
);
|
|
210
216
|
function resolveCompiledPath(outDir, originalFile, extension = ".js") {
|
|
211
|
-
const baseName =
|
|
212
|
-
return
|
|
217
|
+
const baseName = path6.basename(originalFile).replace(/\.[^.]+$/, "");
|
|
218
|
+
return path6.join(outDir, `${baseName}${extension}`);
|
|
213
219
|
}
|
|
214
220
|
async function importFresh(modulePath) {
|
|
215
221
|
const fileUrl = pathToFileURL(modulePath).href;
|
|
@@ -221,13 +227,13 @@ async function importFresh(modulePath) {
|
|
|
221
227
|
// src/cli/shared/metadata.ts
|
|
222
228
|
var METADATA_ENTRY = "metadata.ts";
|
|
223
229
|
async function loadMetadata(projectRoot) {
|
|
224
|
-
const absPath =
|
|
230
|
+
const absPath = path6.join(projectRoot, METADATA_ENTRY);
|
|
225
231
|
if (!fs4.existsSync(absPath)) {
|
|
226
232
|
throw new Error(
|
|
227
233
|
`metadata.ts not found in ${projectRoot}. Create metadata.ts to describe your agent.`
|
|
228
234
|
);
|
|
229
235
|
}
|
|
230
|
-
const tempDir =
|
|
236
|
+
const tempDir = path6.join(projectRoot, ".opentool-temp");
|
|
231
237
|
if (fs4.existsSync(tempDir)) {
|
|
232
238
|
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
233
239
|
}
|
|
@@ -268,7 +274,7 @@ function extractMetadataExport(moduleExports) {
|
|
|
268
274
|
return moduleExports;
|
|
269
275
|
}
|
|
270
276
|
function readPackageJson(projectRoot) {
|
|
271
|
-
const packagePath =
|
|
277
|
+
const packagePath = path6.join(projectRoot, "package.json");
|
|
272
278
|
if (!fs4.existsSync(packagePath)) {
|
|
273
279
|
return {};
|
|
274
280
|
}
|
|
@@ -284,7 +290,7 @@ async function buildMetadataArtifact(options) {
|
|
|
284
290
|
const packageInfo = readPackageJson(projectRoot);
|
|
285
291
|
const { metadata: authored, sourcePath } = await loadMetadata(projectRoot);
|
|
286
292
|
const defaultsApplied = [];
|
|
287
|
-
const folderName =
|
|
293
|
+
const folderName = path6.basename(projectRoot);
|
|
288
294
|
const name = resolveField(
|
|
289
295
|
"name",
|
|
290
296
|
authored.name,
|
|
@@ -341,6 +347,10 @@ async function buildMetadataArtifact(options) {
|
|
|
341
347
|
}
|
|
342
348
|
const toolDiscovery = overrides.discovery ?? void 0;
|
|
343
349
|
const toolChains = overrides.chains ?? authored.chains ?? void 0;
|
|
350
|
+
const toolCategory = tool.profileCategory ?? "tracker";
|
|
351
|
+
if (!tool.profileCategory) {
|
|
352
|
+
defaultsApplied.push(`tool ${toolName} category \u2192 tracker (default)`);
|
|
353
|
+
}
|
|
344
354
|
const toolDefinition = {
|
|
345
355
|
name: toolName,
|
|
346
356
|
description: toolDescription,
|
|
@@ -358,10 +368,14 @@ async function buildMetadataArtifact(options) {
|
|
|
358
368
|
if (toolChains) {
|
|
359
369
|
toolDefinition.chains = toolChains;
|
|
360
370
|
}
|
|
371
|
+
toolDefinition.category = toolCategory;
|
|
361
372
|
const notifyEmail = tool.notifyEmail ?? tool.schedule?.notifyEmail;
|
|
362
373
|
if (notifyEmail !== void 0) {
|
|
363
374
|
toolDefinition.notifyEmail = notifyEmail;
|
|
364
375
|
}
|
|
376
|
+
if (tool.profileCategory) {
|
|
377
|
+
toolDefinition.category = tool.profileCategory;
|
|
378
|
+
}
|
|
365
379
|
return toolDefinition;
|
|
366
380
|
});
|
|
367
381
|
const metadata = BuildMetadataSchema.parse({
|
|
@@ -989,11 +1003,11 @@ var SUPPORTED_EXTENSIONS = [
|
|
|
989
1003
|
async function validateCommand(options) {
|
|
990
1004
|
console.log("\u{1F50D} Validating OpenTool metadata...");
|
|
991
1005
|
try {
|
|
992
|
-
const toolsDir =
|
|
1006
|
+
const toolsDir = path6.resolve(options.input);
|
|
993
1007
|
if (!fs4.existsSync(toolsDir)) {
|
|
994
1008
|
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
995
1009
|
}
|
|
996
|
-
const projectRoot =
|
|
1010
|
+
const projectRoot = path6.dirname(toolsDir);
|
|
997
1011
|
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
998
1012
|
if (tools.length === 0) {
|
|
999
1013
|
throw new Error("No valid tools found - metadata validation aborted");
|
|
@@ -1012,11 +1026,11 @@ async function validateCommand(options) {
|
|
|
1012
1026
|
async function validateFullCommand(options) {
|
|
1013
1027
|
console.log("\u{1F50D} Running full OpenTool validation...\n");
|
|
1014
1028
|
try {
|
|
1015
|
-
const toolsDir =
|
|
1029
|
+
const toolsDir = path6.resolve(options.input);
|
|
1016
1030
|
if (!fs4.existsSync(toolsDir)) {
|
|
1017
1031
|
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
1018
1032
|
}
|
|
1019
|
-
const projectRoot =
|
|
1033
|
+
const projectRoot = path6.dirname(toolsDir);
|
|
1020
1034
|
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
1021
1035
|
if (tools.length === 0) {
|
|
1022
1036
|
throw new Error("No tools discovered in the target directory");
|
|
@@ -1044,12 +1058,12 @@ async function validateFullCommand(options) {
|
|
|
1044
1058
|
}
|
|
1045
1059
|
}
|
|
1046
1060
|
async function loadAndValidateTools(toolsDir, options = {}) {
|
|
1047
|
-
const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(
|
|
1061
|
+
const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(path6.extname(file)));
|
|
1048
1062
|
if (files.length === 0) {
|
|
1049
1063
|
return [];
|
|
1050
1064
|
}
|
|
1051
|
-
const projectRoot = options.projectRoot ??
|
|
1052
|
-
const tempDir =
|
|
1065
|
+
const projectRoot = options.projectRoot ?? path6.dirname(toolsDir);
|
|
1066
|
+
const tempDir = path6.join(toolsDir, ".opentool-temp");
|
|
1053
1067
|
if (fs4.existsSync(tempDir)) {
|
|
1054
1068
|
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
1055
1069
|
}
|
|
@@ -1059,7 +1073,7 @@ async function loadAndValidateTools(toolsDir, options = {}) {
|
|
|
1059
1073
|
throw new Error(`Tool filename must be kebab-case: ${f}`);
|
|
1060
1074
|
}
|
|
1061
1075
|
}
|
|
1062
|
-
const entryPoints = files.map((file) =>
|
|
1076
|
+
const entryPoints = files.map((file) => path6.join(toolsDir, file));
|
|
1063
1077
|
const { outDir, cleanup } = await transpileWithEsbuild({
|
|
1064
1078
|
entryPoints,
|
|
1065
1079
|
projectRoot,
|
|
@@ -1099,6 +1113,13 @@ async function loadAndValidateTools(toolsDir, options = {}) {
|
|
|
1099
1113
|
let normalizedSchedule = null;
|
|
1100
1114
|
const schedule = toolModule?.profile?.schedule;
|
|
1101
1115
|
const profileNotifyEmail = typeof toolModule?.profile?.notifyEmail === "boolean" ? toolModule.profile.notifyEmail : void 0;
|
|
1116
|
+
const profileCategoryRaw = typeof toolModule?.profile?.category === "string" ? toolModule.profile.category : void 0;
|
|
1117
|
+
const allowedProfileCategories = /* @__PURE__ */ new Set(["strategy", "tracker"]);
|
|
1118
|
+
if (profileCategoryRaw && !allowedProfileCategories.has(profileCategoryRaw)) {
|
|
1119
|
+
throw new Error(
|
|
1120
|
+
`${file}: profile.category must be one of ${Array.from(allowedProfileCategories).join(", ")}`
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1102
1123
|
if (hasGET && schedule && typeof schedule.cron === "string" && schedule.cron.trim().length > 0) {
|
|
1103
1124
|
normalizedSchedule = normalizeScheduleExpression(schedule.cron, file);
|
|
1104
1125
|
if (typeof schedule.enabled === "boolean") {
|
|
@@ -1164,12 +1185,13 @@ async function loadAndValidateTools(toolsDir, options = {}) {
|
|
|
1164
1185
|
httpHandlers,
|
|
1165
1186
|
mcpConfig: normalizeMcpConfig(toolModule.mcp, file),
|
|
1166
1187
|
filename: toBaseName(file),
|
|
1167
|
-
sourcePath:
|
|
1188
|
+
sourcePath: path6.join(toolsDir, file),
|
|
1168
1189
|
handler: async (params) => adapter(params),
|
|
1169
1190
|
payment: paymentExport ?? null,
|
|
1170
1191
|
schedule: normalizedSchedule,
|
|
1171
1192
|
...profileNotifyEmail !== void 0 ? { notifyEmail: profileNotifyEmail } : {},
|
|
1172
|
-
profileDescription: typeof toolModule?.profile?.description === "string" ? toolModule.profile?.description ?? null : null
|
|
1193
|
+
profileDescription: typeof toolModule?.profile?.description === "string" ? toolModule.profile?.description ?? null : null,
|
|
1194
|
+
...profileCategoryRaw ? { profileCategory: profileCategoryRaw } : {}
|
|
1173
1195
|
};
|
|
1174
1196
|
tools.push(tool);
|
|
1175
1197
|
}
|
|
@@ -1368,12 +1390,12 @@ async function buildCommand(options) {
|
|
|
1368
1390
|
}
|
|
1369
1391
|
}
|
|
1370
1392
|
async function buildProject(options) {
|
|
1371
|
-
const toolsDir =
|
|
1393
|
+
const toolsDir = path6.resolve(options.input);
|
|
1372
1394
|
if (!fs4.existsSync(toolsDir)) {
|
|
1373
1395
|
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
1374
1396
|
}
|
|
1375
|
-
const projectRoot =
|
|
1376
|
-
const outputDir =
|
|
1397
|
+
const projectRoot = path6.dirname(toolsDir);
|
|
1398
|
+
const outputDir = path6.resolve(options.output);
|
|
1377
1399
|
fs4.mkdirSync(outputDir, { recursive: true });
|
|
1378
1400
|
const serverName = options.name ?? "opentool-server";
|
|
1379
1401
|
const serverVersion = options.version ?? "1.0.0";
|
|
@@ -1385,7 +1407,7 @@ async function buildProject(options) {
|
|
|
1385
1407
|
projectRoot,
|
|
1386
1408
|
tools
|
|
1387
1409
|
});
|
|
1388
|
-
const metadataPath =
|
|
1410
|
+
const metadataPath = path6.join(outputDir, "metadata.json");
|
|
1389
1411
|
fs4.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
|
|
1390
1412
|
const compiledTools = await emitTools(tools, {
|
|
1391
1413
|
projectRoot,
|
|
@@ -1412,7 +1434,7 @@ async function buildProject(options) {
|
|
|
1412
1434
|
serverVersion,
|
|
1413
1435
|
compiledTools});
|
|
1414
1436
|
} else {
|
|
1415
|
-
const serverPath =
|
|
1437
|
+
const serverPath = path6.join(outputDir, "mcp-server.js");
|
|
1416
1438
|
if (fs4.existsSync(serverPath)) {
|
|
1417
1439
|
fs4.rmSync(serverPath);
|
|
1418
1440
|
}
|
|
@@ -1428,7 +1450,7 @@ async function buildProject(options) {
|
|
|
1428
1450
|
};
|
|
1429
1451
|
}
|
|
1430
1452
|
async function emitTools(tools, config) {
|
|
1431
|
-
const toolsOutDir =
|
|
1453
|
+
const toolsOutDir = path6.join(config.outputDir, "tools");
|
|
1432
1454
|
if (fs4.existsSync(toolsOutDir)) {
|
|
1433
1455
|
fs4.rmSync(toolsOutDir, { recursive: true, force: true });
|
|
1434
1456
|
}
|
|
@@ -1450,9 +1472,9 @@ async function emitTools(tools, config) {
|
|
|
1450
1472
|
if (!tool.sourcePath) {
|
|
1451
1473
|
throw new Error(`Missing sourcePath for tool ${tool.filename}`);
|
|
1452
1474
|
}
|
|
1453
|
-
const base =
|
|
1454
|
-
const modulePath =
|
|
1455
|
-
if (!fs4.existsSync(
|
|
1475
|
+
const base = path6.basename(tool.sourcePath).replace(/\.[^.]+$/, "");
|
|
1476
|
+
const modulePath = path6.join("tools", `${base}.js`);
|
|
1477
|
+
if (!fs4.existsSync(path6.join(config.outputDir, modulePath))) {
|
|
1456
1478
|
throw new Error(`Expected compiled output missing: ${modulePath}`);
|
|
1457
1479
|
}
|
|
1458
1480
|
const defaultMcpMethod = tool.mcpConfig?.defaultMethod;
|
|
@@ -1469,7 +1491,7 @@ async function emitTools(tools, config) {
|
|
|
1469
1491
|
return compiled;
|
|
1470
1492
|
}
|
|
1471
1493
|
async function emitSharedModules(config) {
|
|
1472
|
-
const srcDir =
|
|
1494
|
+
const srcDir = path6.join(config.projectRoot, "src");
|
|
1473
1495
|
if (!fs4.existsSync(srcDir)) {
|
|
1474
1496
|
return null;
|
|
1475
1497
|
}
|
|
@@ -1477,7 +1499,7 @@ async function emitSharedModules(config) {
|
|
|
1477
1499
|
if (sharedFiles.length === 0) {
|
|
1478
1500
|
return null;
|
|
1479
1501
|
}
|
|
1480
|
-
const sharedOutDir =
|
|
1502
|
+
const sharedOutDir = path6.join(config.outputDir, "src");
|
|
1481
1503
|
await transpileWithEsbuild({
|
|
1482
1504
|
entryPoints: sharedFiles,
|
|
1483
1505
|
projectRoot: config.projectRoot,
|
|
@@ -1495,7 +1517,7 @@ function collectSourceFiles(dir) {
|
|
|
1495
1517
|
const ignoreDirs = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".opentool-temp"]);
|
|
1496
1518
|
const entries = fs4.readdirSync(dir, { withFileTypes: true });
|
|
1497
1519
|
for (const entry of entries) {
|
|
1498
|
-
const fullPath =
|
|
1520
|
+
const fullPath = path6.join(dir, entry.name);
|
|
1499
1521
|
if (entry.isDirectory()) {
|
|
1500
1522
|
if (ignoreDirs.has(entry.name)) {
|
|
1501
1523
|
continue;
|
|
@@ -1503,7 +1525,7 @@ function collectSourceFiles(dir) {
|
|
|
1503
1525
|
results.push(...collectSourceFiles(fullPath));
|
|
1504
1526
|
continue;
|
|
1505
1527
|
}
|
|
1506
|
-
const ext =
|
|
1528
|
+
const ext = path6.extname(entry.name);
|
|
1507
1529
|
if (supported.has(ext) && !entry.name.endsWith(".d.ts")) {
|
|
1508
1530
|
results.push(fullPath);
|
|
1509
1531
|
}
|
|
@@ -1605,14 +1627,14 @@ module.exports = { server };
|
|
|
1605
1627
|
}
|
|
1606
1628
|
async function writeMcpServer(options) {
|
|
1607
1629
|
const serverCode = renderMcpServer(options);
|
|
1608
|
-
const serverPath =
|
|
1630
|
+
const serverPath = path6.join(options.outputDir, "mcp-server.js");
|
|
1609
1631
|
fs4.writeFileSync(serverPath, serverCode);
|
|
1610
1632
|
fs4.chmodSync(serverPath, 493);
|
|
1611
1633
|
}
|
|
1612
1634
|
function writeCronManifest(options) {
|
|
1613
1635
|
const scheduledTools = options.tools.filter((tool) => tool.schedule?.expression);
|
|
1614
|
-
const manifestDir =
|
|
1615
|
-
const manifestPath =
|
|
1636
|
+
const manifestDir = path6.join(options.outputDir, ".well-known", "opentool");
|
|
1637
|
+
const manifestPath = path6.join(manifestDir, "cron.json");
|
|
1616
1638
|
if (scheduledTools.length === 0) {
|
|
1617
1639
|
if (fs4.existsSync(manifestPath)) {
|
|
1618
1640
|
fs4.rmSync(manifestPath);
|
|
@@ -1662,7 +1684,7 @@ function writeCronManifest(options) {
|
|
|
1662
1684
|
function logBuildSummary(artifacts, options) {
|
|
1663
1685
|
const end = timestamp();
|
|
1664
1686
|
console.log(`[${end}] Build completed successfully!`);
|
|
1665
|
-
console.log(`Output directory: ${
|
|
1687
|
+
console.log(`Output directory: ${path6.resolve(options.output)}`);
|
|
1666
1688
|
console.log("Generated files:");
|
|
1667
1689
|
const hasMcp = artifacts.compiledTools.some((tool) => tool.mcpEnabled);
|
|
1668
1690
|
if (hasMcp) {
|
|
@@ -1704,7 +1726,7 @@ function logBuildSummary(artifacts, options) {
|
|
|
1704
1726
|
}
|
|
1705
1727
|
}
|
|
1706
1728
|
async function buildWorkflowsIfPresent(options) {
|
|
1707
|
-
const workflowsDir = options.workflowsDir ??
|
|
1729
|
+
const workflowsDir = options.workflowsDir ?? path6.join(options.projectRoot, "workflows");
|
|
1708
1730
|
if (!fs4.existsSync(workflowsDir)) {
|
|
1709
1731
|
return null;
|
|
1710
1732
|
}
|
|
@@ -1751,11 +1773,11 @@ Reason: ${error.message}` : "";
|
|
|
1751
1773
|
"Creating OpenTool workflow steps bundle at",
|
|
1752
1774
|
this.config.stepsBundlePath
|
|
1753
1775
|
);
|
|
1754
|
-
const stepsBundlePath2 =
|
|
1776
|
+
const stepsBundlePath2 = path6.resolve(
|
|
1755
1777
|
this.config.workingDir,
|
|
1756
1778
|
this.config.stepsBundlePath
|
|
1757
1779
|
);
|
|
1758
|
-
await fs4.promises.mkdir(
|
|
1780
|
+
await fs4.promises.mkdir(path6.dirname(stepsBundlePath2), { recursive: true });
|
|
1759
1781
|
await this.createStepsBundle({
|
|
1760
1782
|
outfile: stepsBundlePath2,
|
|
1761
1783
|
...options2
|
|
@@ -1766,11 +1788,11 @@ Reason: ${error.message}` : "";
|
|
|
1766
1788
|
"Creating OpenTool workflow bundle at",
|
|
1767
1789
|
this.config.workflowsBundlePath
|
|
1768
1790
|
);
|
|
1769
|
-
const workflowBundlePath =
|
|
1791
|
+
const workflowBundlePath = path6.resolve(
|
|
1770
1792
|
this.config.workingDir,
|
|
1771
1793
|
this.config.workflowsBundlePath
|
|
1772
1794
|
);
|
|
1773
|
-
await fs4.promises.mkdir(
|
|
1795
|
+
await fs4.promises.mkdir(path6.dirname(workflowBundlePath), {
|
|
1774
1796
|
recursive: true
|
|
1775
1797
|
});
|
|
1776
1798
|
await this.createWorkflowsBundle({
|
|
@@ -1784,11 +1806,11 @@ Reason: ${error.message}` : "";
|
|
|
1784
1806
|
"Creating OpenTool workflow webhook bundle at",
|
|
1785
1807
|
this.config.webhookBundlePath
|
|
1786
1808
|
);
|
|
1787
|
-
const webhookBundlePath2 =
|
|
1809
|
+
const webhookBundlePath2 = path6.resolve(
|
|
1788
1810
|
this.config.workingDir,
|
|
1789
1811
|
this.config.webhookBundlePath
|
|
1790
1812
|
);
|
|
1791
|
-
await fs4.promises.mkdir(
|
|
1813
|
+
await fs4.promises.mkdir(path6.dirname(webhookBundlePath2), {
|
|
1792
1814
|
recursive: true
|
|
1793
1815
|
});
|
|
1794
1816
|
await this.createWebhookBundle({ outfile: webhookBundlePath2 });
|
|
@@ -1797,11 +1819,11 @@ Reason: ${error.message}` : "";
|
|
|
1797
1819
|
if (!this.config?.clientBundlePath) {
|
|
1798
1820
|
return;
|
|
1799
1821
|
}
|
|
1800
|
-
const clientBundlePath2 =
|
|
1822
|
+
const clientBundlePath2 = path6.resolve(
|
|
1801
1823
|
this.config.workingDir,
|
|
1802
1824
|
this.config.clientBundlePath
|
|
1803
1825
|
);
|
|
1804
|
-
await fs4.promises.mkdir(
|
|
1826
|
+
await fs4.promises.mkdir(path6.dirname(clientBundlePath2), {
|
|
1805
1827
|
recursive: true
|
|
1806
1828
|
});
|
|
1807
1829
|
await this.createWorkflowsBundle({
|
|
@@ -1810,17 +1832,17 @@ Reason: ${error.message}` : "";
|
|
|
1810
1832
|
});
|
|
1811
1833
|
}
|
|
1812
1834
|
}
|
|
1813
|
-
const relativeSourceDir =
|
|
1814
|
-
const outputBase =
|
|
1835
|
+
const relativeSourceDir = path6.relative(options.projectRoot, workflowsDir) || ".";
|
|
1836
|
+
const outputBase = path6.join(
|
|
1815
1837
|
options.outputDir,
|
|
1816
1838
|
".well-known",
|
|
1817
1839
|
"workflow",
|
|
1818
1840
|
"v1"
|
|
1819
1841
|
);
|
|
1820
|
-
const stepsBundlePath =
|
|
1821
|
-
const workflowsBundlePath =
|
|
1822
|
-
const webhookBundlePath =
|
|
1823
|
-
const manifestPath =
|
|
1842
|
+
const stepsBundlePath = path6.join(outputBase, "step.js");
|
|
1843
|
+
const workflowsBundlePath = path6.join(outputBase, "flow.js");
|
|
1844
|
+
const webhookBundlePath = path6.join(outputBase, "webhook.js");
|
|
1845
|
+
const manifestPath = path6.join(outputBase, "manifest.json");
|
|
1824
1846
|
const builder = new OpenToolWorkflowBuilder({
|
|
1825
1847
|
workingDir: options.projectRoot,
|
|
1826
1848
|
dirs: [relativeSourceDir],
|
|
@@ -1856,13 +1878,13 @@ function hasWorkflowSourceFiles(directory) {
|
|
|
1856
1878
|
const entries = fs4.readdirSync(directory, { withFileTypes: true });
|
|
1857
1879
|
for (const entry of entries) {
|
|
1858
1880
|
if (entry.isDirectory()) {
|
|
1859
|
-
if (hasWorkflowSourceFiles(
|
|
1881
|
+
if (hasWorkflowSourceFiles(path6.join(directory, entry.name))) {
|
|
1860
1882
|
return true;
|
|
1861
1883
|
}
|
|
1862
1884
|
continue;
|
|
1863
1885
|
}
|
|
1864
1886
|
if (entry.isFile()) {
|
|
1865
|
-
const extension =
|
|
1887
|
+
const extension = path6.extname(entry.name).toLowerCase();
|
|
1866
1888
|
if (WORKFLOW_SOURCE_EXTENSIONS.has(extension)) {
|
|
1867
1889
|
return true;
|
|
1868
1890
|
}
|
|
@@ -1886,9 +1908,9 @@ function timestamp() {
|
|
|
1886
1908
|
function escapeForJs(value) {
|
|
1887
1909
|
return value.replace(/'/g, "\\'");
|
|
1888
1910
|
}
|
|
1889
|
-
var __dirname2 =
|
|
1911
|
+
var __dirname2 = path6.dirname(fileURLToPath(import.meta.url));
|
|
1890
1912
|
var packageJson = JSON.parse(
|
|
1891
|
-
fs4.readFileSync(
|
|
1913
|
+
fs4.readFileSync(path6.resolve(__dirname2, "../../package.json"), "utf-8")
|
|
1892
1914
|
);
|
|
1893
1915
|
var cyan = "\x1B[36m";
|
|
1894
1916
|
var bold = "\x1B[1m";
|
|
@@ -1901,11 +1923,11 @@ async function devCommand(options) {
|
|
|
1901
1923
|
const log = enableStdio ? (_message) => {
|
|
1902
1924
|
} : (message) => console.log(message);
|
|
1903
1925
|
try {
|
|
1904
|
-
const toolsDir =
|
|
1926
|
+
const toolsDir = path6.resolve(options.input);
|
|
1905
1927
|
if (!fs4.existsSync(toolsDir)) {
|
|
1906
1928
|
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
1907
1929
|
}
|
|
1908
|
-
const projectRoot =
|
|
1930
|
+
const projectRoot = path6.dirname(toolsDir);
|
|
1909
1931
|
loadEnvFiles(projectRoot);
|
|
1910
1932
|
let toolDefinitions = await loadToolDefinitions(toolsDir, projectRoot);
|
|
1911
1933
|
if (toolDefinitions.length === 0) {
|
|
@@ -1915,7 +1937,7 @@ async function devCommand(options) {
|
|
|
1915
1937
|
const stdioController = enableStdio ? await startMcpServer(() => toolDefinitions) : null;
|
|
1916
1938
|
if (watch2) {
|
|
1917
1939
|
const reloadableExtensions = /\.(ts|js|mjs|cjs|tsx|jsx)$/i;
|
|
1918
|
-
const tempDir =
|
|
1940
|
+
const tempDir = path6.join(toolsDir, ".opentool-temp");
|
|
1919
1941
|
const watchTargets = /* @__PURE__ */ new Set([toolsDir]);
|
|
1920
1942
|
if (projectRoot !== toolsDir) {
|
|
1921
1943
|
watchTargets.add(projectRoot);
|
|
@@ -1946,11 +1968,11 @@ Detected change in ${changedPath ?? "tools directory"}, reloading...${reset}`
|
|
|
1946
1968
|
if (filename && !reloadableExtensions.test(filename)) {
|
|
1947
1969
|
return;
|
|
1948
1970
|
}
|
|
1949
|
-
const fullPath = filename ?
|
|
1971
|
+
const fullPath = filename ? path6.join(target, filename) : void 0;
|
|
1950
1972
|
if (fullPath && fullPath.startsWith(tempDir)) {
|
|
1951
1973
|
return;
|
|
1952
1974
|
}
|
|
1953
|
-
const displayPath = fullPath ?
|
|
1975
|
+
const displayPath = fullPath ? path6.relative(projectRoot, fullPath) || path6.basename(fullPath) : path6.relative(projectRoot, target) || path6.basename(target);
|
|
1954
1976
|
await scheduleReload(displayPath);
|
|
1955
1977
|
});
|
|
1956
1978
|
}
|
|
@@ -2183,7 +2205,7 @@ function routeName(tool) {
|
|
|
2183
2205
|
function loadEnvFiles(projectRoot) {
|
|
2184
2206
|
const envFiles = [".env.local", ".env"];
|
|
2185
2207
|
for (const file of envFiles) {
|
|
2186
|
-
const candidate =
|
|
2208
|
+
const candidate = path6.join(projectRoot, file);
|
|
2187
2209
|
if (fs4.existsSync(candidate)) {
|
|
2188
2210
|
dotenv.config({ path: candidate, override: false });
|
|
2189
2211
|
}
|
|
@@ -2254,17 +2276,17 @@ async function generateMetadataCommand(options) {
|
|
|
2254
2276
|
}
|
|
2255
2277
|
}
|
|
2256
2278
|
async function generateMetadata(options) {
|
|
2257
|
-
const toolsDir =
|
|
2279
|
+
const toolsDir = path6.resolve(options.input);
|
|
2258
2280
|
if (!fs4.existsSync(toolsDir)) {
|
|
2259
2281
|
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
2260
2282
|
}
|
|
2261
|
-
const projectRoot =
|
|
2283
|
+
const projectRoot = path6.dirname(toolsDir);
|
|
2262
2284
|
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
2263
2285
|
const { metadata, defaultsApplied } = await buildMetadataArtifact({
|
|
2264
2286
|
projectRoot,
|
|
2265
2287
|
tools
|
|
2266
2288
|
});
|
|
2267
|
-
const outputPath = options.output ?
|
|
2289
|
+
const outputPath = options.output ? path6.resolve(options.output) : path6.join(projectRoot, "metadata.json");
|
|
2268
2290
|
fs4.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
|
|
2269
2291
|
return {
|
|
2270
2292
|
metadata,
|
|
@@ -2277,8 +2299,8 @@ function timestamp2() {
|
|
|
2277
2299
|
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
2278
2300
|
}
|
|
2279
2301
|
function resolveTemplateDir() {
|
|
2280
|
-
const here =
|
|
2281
|
-
return
|
|
2302
|
+
const here = path6__default.dirname(fileURLToPath(import.meta.url));
|
|
2303
|
+
return path6__default.resolve(here, "../../templates/base");
|
|
2282
2304
|
}
|
|
2283
2305
|
async function directoryIsEmpty(targetDir) {
|
|
2284
2306
|
try {
|
|
@@ -2295,8 +2317,8 @@ async function copyDir(src, dest) {
|
|
|
2295
2317
|
await promises.mkdir(dest, { recursive: true });
|
|
2296
2318
|
const entries = await promises.readdir(src, { withFileTypes: true });
|
|
2297
2319
|
for (const entry of entries) {
|
|
2298
|
-
const srcPath =
|
|
2299
|
-
const destPath =
|
|
2320
|
+
const srcPath = path6__default.join(src, entry.name);
|
|
2321
|
+
const destPath = path6__default.join(dest, entry.name);
|
|
2300
2322
|
if (entry.isDirectory()) {
|
|
2301
2323
|
await copyDir(srcPath, destPath);
|
|
2302
2324
|
} else if (entry.isFile()) {
|
|
@@ -2311,7 +2333,7 @@ function toDisplayName(value) {
|
|
|
2311
2333
|
return value.trim().replace(/[-_]+/g, " ").replace(/\b\w/g, (ch) => ch.toUpperCase()) || "OpenTool Project";
|
|
2312
2334
|
}
|
|
2313
2335
|
async function updatePackageJson(targetDir, name, description) {
|
|
2314
|
-
const filePath =
|
|
2336
|
+
const filePath = path6__default.join(targetDir, "package.json");
|
|
2315
2337
|
const raw = await promises.readFile(filePath, "utf-8");
|
|
2316
2338
|
const pkg = JSON.parse(raw);
|
|
2317
2339
|
pkg.name = toPackageName(name);
|
|
@@ -2322,7 +2344,7 @@ async function updatePackageJson(targetDir, name, description) {
|
|
|
2322
2344
|
`, "utf-8");
|
|
2323
2345
|
}
|
|
2324
2346
|
async function updateMetadata(targetDir, name, description) {
|
|
2325
|
-
const filePath =
|
|
2347
|
+
const filePath = path6__default.join(targetDir, "metadata.ts");
|
|
2326
2348
|
const raw = await promises.readFile(filePath, "utf-8");
|
|
2327
2349
|
const displayName = toDisplayName(name);
|
|
2328
2350
|
const resolvedDescription = description || "OpenTool project";
|
|
@@ -2330,7 +2352,7 @@ async function updateMetadata(targetDir, name, description) {
|
|
|
2330
2352
|
await promises.writeFile(filePath, updated, "utf-8");
|
|
2331
2353
|
}
|
|
2332
2354
|
async function initCommand(options) {
|
|
2333
|
-
const targetDir =
|
|
2355
|
+
const targetDir = path6__default.resolve(process.cwd(), options.dir || ".");
|
|
2334
2356
|
const templateDir = resolveTemplateDir();
|
|
2335
2357
|
const empty = await directoryIsEmpty(targetDir);
|
|
2336
2358
|
if (!empty && !options.force) {
|
|
@@ -2339,7 +2361,7 @@ async function initCommand(options) {
|
|
|
2339
2361
|
);
|
|
2340
2362
|
}
|
|
2341
2363
|
await copyDir(templateDir, targetDir);
|
|
2342
|
-
const projectName = options.name ||
|
|
2364
|
+
const projectName = options.name || path6__default.basename(targetDir);
|
|
2343
2365
|
const description = options.description;
|
|
2344
2366
|
await updatePackageJson(targetDir, projectName, description);
|
|
2345
2367
|
await updateMetadata(targetDir, projectName, description);
|