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 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
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { M as Metadata, I as InternalToolDefinition } from '../validate-D5sE9GUm.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-D5sE9GUm.js';
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 = path5.join(projectRoot, "tsconfig.json");
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(path5.join(tmpdir(), "opentool-"));
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 = path5.join(tempBase, "package.json");
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(import.meta.url);
213
+ createRequire(
214
+ typeof __filename !== "undefined" ? __filename : import.meta.url
215
+ );
210
216
  function resolveCompiledPath(outDir, originalFile, extension = ".js") {
211
- const baseName = path5.basename(originalFile).replace(/\.[^.]+$/, "");
212
- return path5.join(outDir, `${baseName}${extension}`);
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 = path5.join(projectRoot, METADATA_ENTRY);
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 = path5.join(projectRoot, ".opentool-temp");
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 = path5.join(projectRoot, "package.json");
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 = path5.basename(projectRoot);
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 = path5.resolve(options.input);
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 = path5.dirname(toolsDir);
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 = path5.resolve(options.input);
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 = path5.dirname(toolsDir);
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(path5.extname(file)));
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 ?? path5.dirname(toolsDir);
1052
- const tempDir = path5.join(toolsDir, ".opentool-temp");
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) => path5.join(toolsDir, 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: path5.join(toolsDir, file),
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 = path5.resolve(options.input);
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 = path5.dirname(toolsDir);
1376
- const outputDir = path5.resolve(options.output);
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 = path5.join(outputDir, "metadata.json");
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 = path5.join(outputDir, "mcp-server.js");
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 = path5.join(config.outputDir, "tools");
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 = path5.basename(tool.sourcePath).replace(/\.[^.]+$/, "");
1454
- const modulePath = path5.join("tools", `${base}.js`);
1455
- if (!fs4.existsSync(path5.join(config.outputDir, modulePath))) {
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 = path5.join(config.projectRoot, "src");
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 = path5.join(config.outputDir, "src");
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 = path5.join(dir, entry.name);
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 = path5.extname(entry.name);
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 = path5.join(options.outputDir, "mcp-server.js");
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 = path5.join(options.outputDir, ".well-known", "opentool");
1615
- const manifestPath = path5.join(manifestDir, "cron.json");
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: ${path5.resolve(options.output)}`);
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 ?? path5.join(options.projectRoot, "workflows");
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 = path5.resolve(
1776
+ const stepsBundlePath2 = path6.resolve(
1755
1777
  this.config.workingDir,
1756
1778
  this.config.stepsBundlePath
1757
1779
  );
1758
- await fs4.promises.mkdir(path5.dirname(stepsBundlePath2), { recursive: true });
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 = path5.resolve(
1791
+ const workflowBundlePath = path6.resolve(
1770
1792
  this.config.workingDir,
1771
1793
  this.config.workflowsBundlePath
1772
1794
  );
1773
- await fs4.promises.mkdir(path5.dirname(workflowBundlePath), {
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 = path5.resolve(
1809
+ const webhookBundlePath2 = path6.resolve(
1788
1810
  this.config.workingDir,
1789
1811
  this.config.webhookBundlePath
1790
1812
  );
1791
- await fs4.promises.mkdir(path5.dirname(webhookBundlePath2), {
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 = path5.resolve(
1822
+ const clientBundlePath2 = path6.resolve(
1801
1823
  this.config.workingDir,
1802
1824
  this.config.clientBundlePath
1803
1825
  );
1804
- await fs4.promises.mkdir(path5.dirname(clientBundlePath2), {
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 = path5.relative(options.projectRoot, workflowsDir) || ".";
1814
- const outputBase = path5.join(
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 = path5.join(outputBase, "step.js");
1821
- const workflowsBundlePath = path5.join(outputBase, "flow.js");
1822
- const webhookBundlePath = path5.join(outputBase, "webhook.js");
1823
- const manifestPath = path5.join(outputBase, "manifest.json");
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(path5.join(directory, entry.name))) {
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 = path5.extname(entry.name).toLowerCase();
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 = path5.dirname(fileURLToPath(import.meta.url));
1911
+ var __dirname2 = path6.dirname(fileURLToPath(import.meta.url));
1890
1912
  var packageJson = JSON.parse(
1891
- fs4.readFileSync(path5.resolve(__dirname2, "../../package.json"), "utf-8")
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 = path5.resolve(options.input);
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 = path5.dirname(toolsDir);
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 = path5.join(toolsDir, ".opentool-temp");
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 ? path5.join(target, filename) : void 0;
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 ? path5.relative(projectRoot, fullPath) || path5.basename(fullPath) : path5.relative(projectRoot, target) || path5.basename(target);
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 = path5.join(projectRoot, file);
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 = path5.resolve(options.input);
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 = path5.dirname(toolsDir);
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 ? path5.resolve(options.output) : path5.join(projectRoot, "metadata.json");
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 = path5__default.dirname(fileURLToPath(import.meta.url));
2281
- return path5__default.resolve(here, "../../templates/base");
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 = path5__default.join(src, entry.name);
2299
- const destPath = path5__default.join(dest, entry.name);
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 = path5__default.join(targetDir, "package.json");
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 = path5__default.join(targetDir, "metadata.ts");
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 = path5__default.resolve(process.cwd(), options.dir || ".");
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 || path5__default.basename(targetDir);
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);