opentool 0.10.5 → 0.12.0
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/dist/adapters/hyperliquid/index.d.ts +1 -1
- package/dist/adapters/polymarket/index.d.ts +319 -0
- package/dist/adapters/polymarket/index.js +831 -0
- package/dist/adapters/polymarket/index.js.map +1 -0
- package/dist/backtest/index.d.ts +58 -0
- package/dist/backtest/index.js +122 -0
- package/dist/backtest/index.js.map +1 -0
- package/dist/cli/index.d.ts +17 -4
- package/dist/{validate-DbhJ_r0Z.d.ts → index-9Z3wo28l.d.ts} +2 -25
- package/dist/index-BnQsRvND.d.ts +13 -0
- package/dist/index.d.ts +8 -376
- package/dist/index.js +29 -1110
- package/dist/index.js.map +1 -1
- package/dist/{payment-orkZA9se.d.ts → payment-BLm1ltur.d.ts} +1 -1
- package/dist/{types-rAQrDrah.d.ts → types-BaTmu0gS.d.ts} +1 -1
- package/dist/validation/index.d.ts +4 -0
- package/dist/validation/index.js +1255 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/wallet/browser.d.ts +1 -1
- package/dist/wallet/index.d.ts +2 -2
- package/dist/x402/index.d.ts +1 -1
- package/package.json +9 -1
- package/templates/base/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
-
import * as
|
|
5
|
-
import * as
|
|
6
|
-
import { fileURLToPath
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
7
|
import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import { zeroAddress, createWalletClient, http, createPublicClient, parseUnits, encodeFunctionData, erc20Abi } from 'viem';
|
|
@@ -15,9 +15,6 @@ import { encode } from '@msgpack/msgpack';
|
|
|
15
15
|
import { keccak_256 } from '@noble/hashes/sha3';
|
|
16
16
|
import { hexToBytes, concatBytes, bytesToHex } from '@noble/hashes/utils';
|
|
17
17
|
import { createHmac, randomBytes } from 'crypto';
|
|
18
|
-
import { tmpdir } from 'os';
|
|
19
|
-
import { build } from 'esbuild';
|
|
20
|
-
import { createRequire } from 'module';
|
|
21
18
|
|
|
22
19
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
23
20
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -699,16 +696,16 @@ function buildAdapters(tools) {
|
|
|
699
696
|
}
|
|
700
697
|
async function loadToolsFromDirectory(metadataMap) {
|
|
701
698
|
const tools = [];
|
|
702
|
-
const toolsDir =
|
|
703
|
-
if (!
|
|
699
|
+
const toolsDir = path.join(process.cwd(), "tools");
|
|
700
|
+
if (!fs.existsSync(toolsDir)) {
|
|
704
701
|
return tools;
|
|
705
702
|
}
|
|
706
|
-
const files =
|
|
703
|
+
const files = fs.readdirSync(toolsDir);
|
|
707
704
|
for (const file of files) {
|
|
708
705
|
if (!isSupportedToolFile(file)) {
|
|
709
706
|
continue;
|
|
710
707
|
}
|
|
711
|
-
const toolPath =
|
|
708
|
+
const toolPath = path.join(toolsDir, file);
|
|
712
709
|
try {
|
|
713
710
|
const exportsObject = __require(toolPath);
|
|
714
711
|
const candidate = resolveModuleCandidate(exportsObject);
|
|
@@ -772,12 +769,12 @@ async function loadToolsFromDirectory(metadataMap) {
|
|
|
772
769
|
return tools;
|
|
773
770
|
}
|
|
774
771
|
function loadMetadata() {
|
|
775
|
-
const metadataPath =
|
|
776
|
-
if (!
|
|
772
|
+
const metadataPath = path.join(process.cwd(), "metadata.json");
|
|
773
|
+
if (!fs.existsSync(metadataPath)) {
|
|
777
774
|
return null;
|
|
778
775
|
}
|
|
779
776
|
try {
|
|
780
|
-
const contents =
|
|
777
|
+
const contents = fs.readFileSync(metadataPath, "utf8");
|
|
781
778
|
return JSON.parse(contents);
|
|
782
779
|
} catch (error) {
|
|
783
780
|
console.warn(`Failed to parse metadata.json: ${error}`);
|
|
@@ -894,7 +891,7 @@ function resolveRuntimePath(value) {
|
|
|
894
891
|
if (value.startsWith("file://")) {
|
|
895
892
|
return fileURLToPath(value);
|
|
896
893
|
}
|
|
897
|
-
return
|
|
894
|
+
return path.resolve(value);
|
|
898
895
|
}
|
|
899
896
|
|
|
900
897
|
// src/types/index.ts
|
|
@@ -1724,8 +1721,8 @@ async function store(input, options) {
|
|
|
1724
1721
|
);
|
|
1725
1722
|
}
|
|
1726
1723
|
const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
|
|
1727
|
-
const
|
|
1728
|
-
const url = `${baseUrl}${
|
|
1724
|
+
const path2 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
|
|
1725
|
+
const url = `${baseUrl}${path2}`;
|
|
1729
1726
|
let response;
|
|
1730
1727
|
try {
|
|
1731
1728
|
response = await fetchFn(url, {
|
|
@@ -1765,8 +1762,8 @@ async function store(input, options) {
|
|
|
1765
1762
|
async function retrieve(params, options) {
|
|
1766
1763
|
const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
|
|
1767
1764
|
const mode = params?.mode ?? "live";
|
|
1768
|
-
const
|
|
1769
|
-
const url = new URL(`${baseUrl}${
|
|
1765
|
+
const path2 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
|
|
1766
|
+
const url = new URL(`${baseUrl}${path2}`);
|
|
1770
1767
|
if (params?.source) url.searchParams.set("source", params.source);
|
|
1771
1768
|
if (params?.walletAddress) url.searchParams.set("walletAddress", params.walletAddress);
|
|
1772
1769
|
if (params?.symbol) url.searchParams.set("symbol", params.symbol);
|
|
@@ -5113,19 +5110,19 @@ function parseOptionalDate(value) {
|
|
|
5113
5110
|
return null;
|
|
5114
5111
|
}
|
|
5115
5112
|
function buildHmacSignature(args) {
|
|
5116
|
-
const
|
|
5113
|
+
const timestamp = args.timestamp.toString();
|
|
5117
5114
|
const method = args.method.toUpperCase();
|
|
5118
|
-
const
|
|
5115
|
+
const path2 = args.path;
|
|
5119
5116
|
const body = args.body == null ? "" : typeof args.body === "string" ? args.body : JSON.stringify(args.body);
|
|
5120
|
-
const payload = `${
|
|
5117
|
+
const payload = `${timestamp}${method}${path2}${body}`;
|
|
5121
5118
|
const key = Buffer.from(args.secret, "base64");
|
|
5122
5119
|
return createHmac("sha256", key).update(payload).digest("hex");
|
|
5123
5120
|
}
|
|
5124
5121
|
function buildL2Headers(args) {
|
|
5125
|
-
const
|
|
5122
|
+
const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
5126
5123
|
const signature = buildHmacSignature({
|
|
5127
5124
|
secret: args.credentials.secret,
|
|
5128
|
-
timestamp
|
|
5125
|
+
timestamp,
|
|
5129
5126
|
method: args.method,
|
|
5130
5127
|
path: args.path,
|
|
5131
5128
|
body: args.body ?? null
|
|
@@ -5134,13 +5131,13 @@ function buildL2Headers(args) {
|
|
|
5134
5131
|
POLY_ADDRESS: args.address,
|
|
5135
5132
|
POLY_API_KEY: args.credentials.apiKey,
|
|
5136
5133
|
POLY_PASSPHRASE: args.credentials.passphrase,
|
|
5137
|
-
POLY_TIMESTAMP:
|
|
5134
|
+
POLY_TIMESTAMP: timestamp.toString(),
|
|
5138
5135
|
POLY_SIGNATURE: signature
|
|
5139
5136
|
};
|
|
5140
5137
|
}
|
|
5141
5138
|
async function buildL1Headers(args) {
|
|
5142
5139
|
assertWalletSigner(args.wallet);
|
|
5143
|
-
const
|
|
5140
|
+
const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
5144
5141
|
const nonce = args.nonce ?? Date.now();
|
|
5145
5142
|
const chainId = POLYMARKET_CHAIN_ID[args.environment ?? "mainnet"];
|
|
5146
5143
|
const address = args.wallet.address;
|
|
@@ -5162,14 +5159,14 @@ async function buildL1Headers(args) {
|
|
|
5162
5159
|
primaryType: "ClobAuth",
|
|
5163
5160
|
message: {
|
|
5164
5161
|
address,
|
|
5165
|
-
timestamp:
|
|
5162
|
+
timestamp: timestamp.toString(),
|
|
5166
5163
|
nonce: BigInt(nonce),
|
|
5167
5164
|
message
|
|
5168
5165
|
}
|
|
5169
5166
|
});
|
|
5170
5167
|
return {
|
|
5171
5168
|
POLY_ADDRESS: address,
|
|
5172
|
-
POLY_TIMESTAMP:
|
|
5169
|
+
POLY_TIMESTAMP: timestamp.toString(),
|
|
5173
5170
|
POLY_NONCE: nonce.toString(),
|
|
5174
5171
|
POLY_SIGNATURE: signature
|
|
5175
5172
|
};
|
|
@@ -6410,8 +6407,8 @@ async function streamText(options, clientConfig = {}) {
|
|
|
6410
6407
|
const handlers = options.handlers ?? {};
|
|
6411
6408
|
let finishedResolve;
|
|
6412
6409
|
let finishedReject;
|
|
6413
|
-
const finished = new Promise((
|
|
6414
|
-
finishedResolve =
|
|
6410
|
+
const finished = new Promise((resolve2, reject) => {
|
|
6411
|
+
finishedResolve = resolve2;
|
|
6415
6412
|
finishedReject = reject;
|
|
6416
6413
|
});
|
|
6417
6414
|
let settled = false;
|
|
@@ -6640,9 +6637,9 @@ function assignIfDefined(target, key, value) {
|
|
|
6640
6637
|
target[key] = value;
|
|
6641
6638
|
}
|
|
6642
6639
|
}
|
|
6643
|
-
function buildUrl(baseUrl,
|
|
6640
|
+
function buildUrl(baseUrl, path2) {
|
|
6644
6641
|
const sanitizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
6645
|
-
return `${sanitizedBase}${
|
|
6642
|
+
return `${sanitizedBase}${path2}`;
|
|
6646
6643
|
}
|
|
6647
6644
|
function createAbortBundle(upstreamSignal, timeoutMs) {
|
|
6648
6645
|
const controller = new AbortController();
|
|
@@ -6846,1085 +6843,7 @@ function buildBacktestDecisionSeriesInput(request) {
|
|
|
6846
6843
|
...accountValueUsd != null ? { accountValueUsd } : {}
|
|
6847
6844
|
};
|
|
6848
6845
|
}
|
|
6849
|
-
var METADATA_SPEC_VERSION = "1.1.0";
|
|
6850
|
-
var McpAnnotationsSchema = z.object({
|
|
6851
|
-
title: z.string().optional(),
|
|
6852
|
-
readOnlyHint: z.boolean().optional(),
|
|
6853
|
-
destructiveHint: z.boolean().optional(),
|
|
6854
|
-
idempotentHint: z.boolean().optional(),
|
|
6855
|
-
openWorldHint: z.boolean().optional(),
|
|
6856
|
-
requiresPayment: z.boolean().optional()
|
|
6857
|
-
}).strict();
|
|
6858
|
-
var X402PaymentSchema = z.object({
|
|
6859
|
-
definition: z.object({
|
|
6860
|
-
amount: z.string(),
|
|
6861
|
-
currency: z.object({
|
|
6862
|
-
code: z.string(),
|
|
6863
|
-
symbol: z.string(),
|
|
6864
|
-
decimals: z.number()
|
|
6865
|
-
}),
|
|
6866
|
-
asset: z.object({
|
|
6867
|
-
symbol: z.string(),
|
|
6868
|
-
network: z.string(),
|
|
6869
|
-
address: z.string(),
|
|
6870
|
-
decimals: z.number()
|
|
6871
|
-
}),
|
|
6872
|
-
payTo: z.string(),
|
|
6873
|
-
resource: z.string().optional(),
|
|
6874
|
-
description: z.string().optional(),
|
|
6875
|
-
scheme: z.string(),
|
|
6876
|
-
network: z.string(),
|
|
6877
|
-
facilitator: z.object({
|
|
6878
|
-
url: z.string(),
|
|
6879
|
-
verifyPath: z.string().optional(),
|
|
6880
|
-
settlePath: z.string().optional(),
|
|
6881
|
-
apiKeyHeader: z.string().optional()
|
|
6882
|
-
}),
|
|
6883
|
-
metadata: z.record(z.string(), z.unknown()).optional()
|
|
6884
|
-
}),
|
|
6885
|
-
metadata: z.record(z.string(), z.unknown()).optional()
|
|
6886
|
-
}).passthrough();
|
|
6887
|
-
var PaymentConfigSchema = z.union([X402PaymentSchema, z.record(z.string(), z.unknown())]);
|
|
6888
|
-
var DiscoveryMetadataSchema = z.object({
|
|
6889
|
-
keywords: z.array(z.string()).optional(),
|
|
6890
|
-
category: z.string().optional(),
|
|
6891
|
-
useCases: z.array(z.string()).optional(),
|
|
6892
|
-
capabilities: z.array(z.string()).optional(),
|
|
6893
|
-
requirements: z.record(z.string(), z.any()).optional(),
|
|
6894
|
-
compatibility: z.record(z.string(), z.any()).optional(),
|
|
6895
|
-
documentation: z.union([z.string(), z.array(z.string())]).optional()
|
|
6896
|
-
}).catchall(z.any());
|
|
6897
|
-
var ToolCategorySchema = z.enum(["strategy", "tracker", "orchestrator"]);
|
|
6898
|
-
var ToolMetadataOverridesSchema = z.object({
|
|
6899
|
-
name: z.string().optional(),
|
|
6900
|
-
description: z.string().optional(),
|
|
6901
|
-
annotations: McpAnnotationsSchema.optional(),
|
|
6902
|
-
payment: PaymentConfigSchema.optional(),
|
|
6903
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6904
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6905
|
-
}).catchall(z.any());
|
|
6906
|
-
var ToolSchema = z.object({
|
|
6907
|
-
name: z.string(),
|
|
6908
|
-
description: z.string(),
|
|
6909
|
-
inputSchema: z.any(),
|
|
6910
|
-
annotations: McpAnnotationsSchema.optional(),
|
|
6911
|
-
payment: PaymentConfigSchema.optional(),
|
|
6912
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6913
|
-
chains: z.array(z.union([z.string(), z.number()])).optional(),
|
|
6914
|
-
notifyEmail: z.boolean().optional(),
|
|
6915
|
-
category: ToolCategorySchema.optional()
|
|
6916
|
-
}).strict();
|
|
6917
|
-
var MetadataSchema = z.object({
|
|
6918
|
-
metadataSpecVersion: z.string().optional(),
|
|
6919
|
-
name: z.string().optional(),
|
|
6920
|
-
displayName: z.string().optional(),
|
|
6921
|
-
version: z.string().optional(),
|
|
6922
|
-
description: z.string().optional(),
|
|
6923
|
-
author: z.string().optional(),
|
|
6924
|
-
repository: z.string().optional(),
|
|
6925
|
-
website: z.string().optional(),
|
|
6926
|
-
category: z.string().optional(),
|
|
6927
|
-
categories: z.array(z.string()).optional(),
|
|
6928
|
-
termsOfService: z.string().optional(),
|
|
6929
|
-
mcpUrl: z.string().optional(),
|
|
6930
|
-
payment: PaymentConfigSchema.optional(),
|
|
6931
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6932
|
-
promptExamples: z.array(z.string()).optional(),
|
|
6933
|
-
iconPath: z.string().optional(),
|
|
6934
|
-
videoPath: z.string().optional(),
|
|
6935
|
-
image: z.string().optional(),
|
|
6936
|
-
animation_url: z.string().optional(),
|
|
6937
|
-
keywords: z.array(z.string()).optional(),
|
|
6938
|
-
useCases: z.array(z.string()).optional(),
|
|
6939
|
-
capabilities: z.array(z.string()).optional(),
|
|
6940
|
-
requirements: z.record(z.string(), z.any()).optional(),
|
|
6941
|
-
compatibility: z.record(z.string(), z.any()).optional(),
|
|
6942
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6943
|
-
}).catchall(z.any());
|
|
6944
|
-
var BuildMetadataSchema = z.object({
|
|
6945
|
-
metadataSpecVersion: z.string().default(METADATA_SPEC_VERSION),
|
|
6946
|
-
name: z.string(),
|
|
6947
|
-
displayName: z.string(),
|
|
6948
|
-
version: z.string(),
|
|
6949
|
-
description: z.string().optional(),
|
|
6950
|
-
author: z.string().optional(),
|
|
6951
|
-
repository: z.string().optional(),
|
|
6952
|
-
website: z.string().optional(),
|
|
6953
|
-
category: z.string(),
|
|
6954
|
-
termsOfService: z.string().optional(),
|
|
6955
|
-
mcpUrl: z.string().optional(),
|
|
6956
|
-
payment: PaymentConfigSchema.optional(),
|
|
6957
|
-
tools: z.array(ToolSchema).min(1),
|
|
6958
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6959
|
-
promptExamples: z.array(z.string()).optional(),
|
|
6960
|
-
iconPath: z.string().optional(),
|
|
6961
|
-
videoPath: z.string().optional(),
|
|
6962
|
-
image: z.string().optional(),
|
|
6963
|
-
animation_url: z.string().optional(),
|
|
6964
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6965
|
-
}).strict();
|
|
6966
|
-
function resolveTsconfig(projectRoot) {
|
|
6967
|
-
const candidate = path5.join(projectRoot, "tsconfig.json");
|
|
6968
|
-
if (fs4.existsSync(candidate)) {
|
|
6969
|
-
return candidate;
|
|
6970
|
-
}
|
|
6971
|
-
return void 0;
|
|
6972
|
-
}
|
|
6973
|
-
async function transpileWithEsbuild(options) {
|
|
6974
|
-
if (options.entryPoints.length === 0) {
|
|
6975
|
-
throw new Error("No entry points provided for esbuild transpilation");
|
|
6976
|
-
}
|
|
6977
|
-
const projectRoot = options.projectRoot;
|
|
6978
|
-
const tempBase = options.outDir ?? fs4.mkdtempSync(path5.join(tmpdir(), "opentool-"));
|
|
6979
|
-
if (!fs4.existsSync(tempBase)) {
|
|
6980
|
-
fs4.mkdirSync(tempBase, { recursive: true });
|
|
6981
|
-
}
|
|
6982
|
-
const tsconfig = resolveTsconfig(projectRoot);
|
|
6983
|
-
const buildOptions = {
|
|
6984
|
-
entryPoints: options.entryPoints,
|
|
6985
|
-
outdir: tempBase,
|
|
6986
|
-
bundle: options.bundle ?? false,
|
|
6987
|
-
format: options.format,
|
|
6988
|
-
platform: "node",
|
|
6989
|
-
target: "node20",
|
|
6990
|
-
logLevel: options.logLevel ?? "warning",
|
|
6991
|
-
sourcesContent: false,
|
|
6992
|
-
sourcemap: false,
|
|
6993
|
-
loader: {
|
|
6994
|
-
".ts": "ts",
|
|
6995
|
-
".tsx": "tsx",
|
|
6996
|
-
".cts": "ts",
|
|
6997
|
-
".mts": "ts",
|
|
6998
|
-
".js": "js",
|
|
6999
|
-
".jsx": "jsx",
|
|
7000
|
-
".mjs": "js",
|
|
7001
|
-
".cjs": "js",
|
|
7002
|
-
".json": "json"
|
|
7003
|
-
},
|
|
7004
|
-
metafile: options.metafile ?? false,
|
|
7005
|
-
allowOverwrite: true,
|
|
7006
|
-
absWorkingDir: projectRoot
|
|
7007
|
-
};
|
|
7008
|
-
if (options.external && options.external.length > 0) {
|
|
7009
|
-
buildOptions.external = options.external;
|
|
7010
|
-
}
|
|
7011
|
-
if (options.nodePaths && options.nodePaths.length > 0) {
|
|
7012
|
-
buildOptions.nodePaths = options.nodePaths;
|
|
7013
|
-
}
|
|
7014
|
-
if (options.outBase) {
|
|
7015
|
-
buildOptions.outbase = options.outBase;
|
|
7016
|
-
}
|
|
7017
|
-
if (!buildOptions.bundle) {
|
|
7018
|
-
buildOptions.packages = "external";
|
|
7019
|
-
}
|
|
7020
|
-
if (tsconfig) {
|
|
7021
|
-
buildOptions.tsconfig = tsconfig;
|
|
7022
|
-
}
|
|
7023
|
-
await build(buildOptions);
|
|
7024
|
-
if (options.format === "esm") {
|
|
7025
|
-
const packageJsonPath = path5.join(tempBase, "package.json");
|
|
7026
|
-
if (!fs4.existsSync(packageJsonPath)) {
|
|
7027
|
-
fs4.writeFileSync(packageJsonPath, JSON.stringify({ type: "module" }), "utf8");
|
|
7028
|
-
}
|
|
7029
|
-
}
|
|
7030
|
-
const cleanup = () => {
|
|
7031
|
-
if (options.outDir) {
|
|
7032
|
-
return;
|
|
7033
|
-
}
|
|
7034
|
-
fs4.rmSync(tempBase, { recursive: true, force: true });
|
|
7035
|
-
};
|
|
7036
|
-
return { outDir: tempBase, cleanup };
|
|
7037
|
-
}
|
|
7038
|
-
createRequire(
|
|
7039
|
-
typeof __filename !== "undefined" ? __filename : import.meta.url
|
|
7040
|
-
);
|
|
7041
|
-
function resolveCompiledPath(outDir, originalFile, extension = ".js") {
|
|
7042
|
-
const baseName = path5.basename(originalFile).replace(/\.[^.]+$/, "");
|
|
7043
|
-
return path5.join(outDir, `${baseName}${extension}`);
|
|
7044
|
-
}
|
|
7045
|
-
async function importFresh(modulePath) {
|
|
7046
|
-
const fileUrl = pathToFileURL(modulePath).href;
|
|
7047
|
-
const cacheBuster = `t=${Date.now()}-${Math.random()}`;
|
|
7048
|
-
const separator = fileUrl.includes("?") ? "&" : "?";
|
|
7049
|
-
return import(`${fileUrl}${separator}${cacheBuster}`);
|
|
7050
|
-
}
|
|
7051
|
-
|
|
7052
|
-
// src/cli/shared/metadata.ts
|
|
7053
|
-
var METADATA_ENTRY = "metadata.ts";
|
|
7054
|
-
async function loadMetadata2(projectRoot) {
|
|
7055
|
-
const absPath = path5.join(projectRoot, METADATA_ENTRY);
|
|
7056
|
-
if (!fs4.existsSync(absPath)) {
|
|
7057
|
-
return {
|
|
7058
|
-
metadata: MetadataSchema.parse({}),
|
|
7059
|
-
sourcePath: "smart defaults (metadata.ts missing)"
|
|
7060
|
-
};
|
|
7061
|
-
}
|
|
7062
|
-
const tempDir = path5.join(projectRoot, ".opentool-temp");
|
|
7063
|
-
if (fs4.existsSync(tempDir)) {
|
|
7064
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7065
|
-
}
|
|
7066
|
-
const { outDir, cleanup } = await transpileWithEsbuild({
|
|
7067
|
-
entryPoints: [absPath],
|
|
7068
|
-
projectRoot,
|
|
7069
|
-
format: "esm",
|
|
7070
|
-
outDir: tempDir
|
|
7071
|
-
});
|
|
7072
|
-
try {
|
|
7073
|
-
const compiledPath = resolveCompiledPath(outDir, METADATA_ENTRY);
|
|
7074
|
-
const moduleExports = await importFresh(compiledPath);
|
|
7075
|
-
const metadataExport = extractMetadataExport(moduleExports);
|
|
7076
|
-
const parsed = MetadataSchema.parse(metadataExport);
|
|
7077
|
-
return { metadata: parsed, sourcePath: absPath };
|
|
7078
|
-
} finally {
|
|
7079
|
-
cleanup();
|
|
7080
|
-
if (fs4.existsSync(tempDir)) {
|
|
7081
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7082
|
-
}
|
|
7083
|
-
}
|
|
7084
|
-
}
|
|
7085
|
-
function extractMetadataExport(moduleExports) {
|
|
7086
|
-
if (!moduleExports || typeof moduleExports !== "object") {
|
|
7087
|
-
throw new Error("metadata.ts must export a metadata object");
|
|
7088
|
-
}
|
|
7089
|
-
const exportsObject = moduleExports;
|
|
7090
|
-
if (exportsObject.metadata) {
|
|
7091
|
-
return exportsObject.metadata;
|
|
7092
|
-
}
|
|
7093
|
-
if (exportsObject.default && typeof exportsObject.default === "object") {
|
|
7094
|
-
const defaultExport = exportsObject.default;
|
|
7095
|
-
if (defaultExport.metadata) {
|
|
7096
|
-
return defaultExport.metadata;
|
|
7097
|
-
}
|
|
7098
|
-
return defaultExport;
|
|
7099
|
-
}
|
|
7100
|
-
return moduleExports;
|
|
7101
|
-
}
|
|
7102
|
-
function readPackageJson(projectRoot) {
|
|
7103
|
-
const packagePath = path5.join(projectRoot, "package.json");
|
|
7104
|
-
if (!fs4.existsSync(packagePath)) {
|
|
7105
|
-
return {};
|
|
7106
|
-
}
|
|
7107
|
-
try {
|
|
7108
|
-
const content = fs4.readFileSync(packagePath, "utf8");
|
|
7109
|
-
return JSON.parse(content);
|
|
7110
|
-
} catch (error) {
|
|
7111
|
-
throw new Error(`Failed to read package.json: ${error}`);
|
|
7112
|
-
}
|
|
7113
|
-
}
|
|
7114
|
-
async function buildMetadataArtifact(options) {
|
|
7115
|
-
const projectRoot = options.projectRoot;
|
|
7116
|
-
const packageInfo = readPackageJson(projectRoot);
|
|
7117
|
-
const { metadata: authored, sourcePath } = await loadMetadata2(projectRoot);
|
|
7118
|
-
const defaultsApplied = [];
|
|
7119
|
-
const folderName = path5.basename(projectRoot);
|
|
7120
|
-
const name = resolveField(
|
|
7121
|
-
"name",
|
|
7122
|
-
authored.name,
|
|
7123
|
-
() => packageInfo.name ?? folderName,
|
|
7124
|
-
defaultsApplied,
|
|
7125
|
-
"package.json name"
|
|
7126
|
-
);
|
|
7127
|
-
const displayName = resolveField(
|
|
7128
|
-
"displayName",
|
|
7129
|
-
authored.displayName,
|
|
7130
|
-
() => {
|
|
7131
|
-
const source = packageInfo.name ?? folderName;
|
|
7132
|
-
return source.split(/[-_]/).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
7133
|
-
},
|
|
7134
|
-
defaultsApplied,
|
|
7135
|
-
"package.json name"
|
|
7136
|
-
);
|
|
7137
|
-
const versionRaw = resolveField(
|
|
7138
|
-
"version",
|
|
7139
|
-
authored.version,
|
|
7140
|
-
() => packageInfo.version ?? "0.1.0",
|
|
7141
|
-
defaultsApplied,
|
|
7142
|
-
"package.json version"
|
|
7143
|
-
);
|
|
7144
|
-
const version = typeof versionRaw === "number" ? String(versionRaw) : versionRaw;
|
|
7145
|
-
const category = determineCategory(authored, defaultsApplied);
|
|
7146
|
-
const description = authored.description ?? packageInfo.description;
|
|
7147
|
-
if (!authored.description && packageInfo.description) {
|
|
7148
|
-
defaultsApplied.push("description \u2192 package.json description");
|
|
7149
|
-
}
|
|
7150
|
-
const author = authored.author ?? packageInfo.author;
|
|
7151
|
-
if (!authored.author && packageInfo.author) {
|
|
7152
|
-
defaultsApplied.push("author \u2192 package.json author");
|
|
7153
|
-
}
|
|
7154
|
-
const repository = authored.repository ?? extractRepository(packageInfo.repository);
|
|
7155
|
-
if (!authored.repository && repository) {
|
|
7156
|
-
defaultsApplied.push("repository \u2192 package.json repository");
|
|
7157
|
-
}
|
|
7158
|
-
const website = authored.website ?? packageInfo.homepage;
|
|
7159
|
-
if (!authored.website && packageInfo.homepage) {
|
|
7160
|
-
defaultsApplied.push("website \u2192 package.json homepage");
|
|
7161
|
-
}
|
|
7162
|
-
const payment = resolvePayment(authored);
|
|
7163
|
-
const baseImage = authored.image ?? authored.iconPath;
|
|
7164
|
-
const animation = authored.animation_url ?? authored.videoPath;
|
|
7165
|
-
const discovery = buildDiscovery(authored);
|
|
7166
|
-
const metadataTools = options.tools.map((tool) => {
|
|
7167
|
-
const overrides = tool.metadata ? ToolMetadataOverridesSchema.parse(tool.metadata) : {};
|
|
7168
|
-
const toolName = overrides.name ?? tool.filename;
|
|
7169
|
-
const toolDescription = overrides.description ?? `${toolName} tool`;
|
|
7170
|
-
const toolPayment = overrides.payment ?? payment ?? void 0;
|
|
7171
|
-
if (!overrides.payment && toolPayment && payment && toolPayment === payment) {
|
|
7172
|
-
defaultsApplied.push(`tool ${toolName} payment \u2192 agent payment`);
|
|
7173
|
-
}
|
|
7174
|
-
const toolDiscovery = overrides.discovery ?? void 0;
|
|
7175
|
-
const toolChains = overrides.chains ?? authored.chains ?? void 0;
|
|
7176
|
-
const toolCategory = tool.profileCategory ?? "tracker";
|
|
7177
|
-
if (!tool.profileCategory) {
|
|
7178
|
-
defaultsApplied.push(`tool ${toolName} category \u2192 tracker (default)`);
|
|
7179
|
-
}
|
|
7180
|
-
const toolDefinition = {
|
|
7181
|
-
name: toolName,
|
|
7182
|
-
description: toolDescription,
|
|
7183
|
-
inputSchema: tool.inputSchema
|
|
7184
|
-
};
|
|
7185
|
-
if (overrides.annotations) {
|
|
7186
|
-
toolDefinition.annotations = overrides.annotations;
|
|
7187
|
-
}
|
|
7188
|
-
if (toolPayment) {
|
|
7189
|
-
toolDefinition.payment = toolPayment;
|
|
7190
|
-
}
|
|
7191
|
-
if (toolDiscovery) {
|
|
7192
|
-
toolDefinition.discovery = toolDiscovery;
|
|
7193
|
-
}
|
|
7194
|
-
if (toolChains) {
|
|
7195
|
-
toolDefinition.chains = toolChains;
|
|
7196
|
-
}
|
|
7197
|
-
toolDefinition.category = toolCategory;
|
|
7198
|
-
const notifyEmail = tool.notifyEmail ?? tool.schedule?.notifyEmail;
|
|
7199
|
-
if (notifyEmail !== void 0) {
|
|
7200
|
-
toolDefinition.notifyEmail = notifyEmail;
|
|
7201
|
-
}
|
|
7202
|
-
if (tool.profileCategory) {
|
|
7203
|
-
toolDefinition.category = tool.profileCategory;
|
|
7204
|
-
}
|
|
7205
|
-
return toolDefinition;
|
|
7206
|
-
});
|
|
7207
|
-
const metadata = BuildMetadataSchema.parse({
|
|
7208
|
-
metadataSpecVersion: authored.metadataSpecVersion ?? METADATA_SPEC_VERSION,
|
|
7209
|
-
name,
|
|
7210
|
-
displayName,
|
|
7211
|
-
version,
|
|
7212
|
-
description,
|
|
7213
|
-
author,
|
|
7214
|
-
repository,
|
|
7215
|
-
website,
|
|
7216
|
-
category,
|
|
7217
|
-
termsOfService: authored.termsOfService,
|
|
7218
|
-
mcpUrl: authored.mcpUrl,
|
|
7219
|
-
payment: payment ?? void 0,
|
|
7220
|
-
tools: metadataTools,
|
|
7221
|
-
discovery,
|
|
7222
|
-
promptExamples: authored.promptExamples,
|
|
7223
|
-
iconPath: authored.iconPath,
|
|
7224
|
-
videoPath: authored.videoPath,
|
|
7225
|
-
image: baseImage,
|
|
7226
|
-
animation_url: animation,
|
|
7227
|
-
chains: authored.chains
|
|
7228
|
-
});
|
|
7229
|
-
return {
|
|
7230
|
-
metadata,
|
|
7231
|
-
defaultsApplied,
|
|
7232
|
-
sourceMetadataPath: sourcePath
|
|
7233
|
-
};
|
|
7234
|
-
}
|
|
7235
|
-
function resolveField(field, value, fallback, defaultsApplied, fallbackLabel) {
|
|
7236
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
7237
|
-
return value;
|
|
7238
|
-
}
|
|
7239
|
-
const resolved = fallback();
|
|
7240
|
-
defaultsApplied.push(`${field} \u2192 ${fallbackLabel}`);
|
|
7241
|
-
return resolved;
|
|
7242
|
-
}
|
|
7243
|
-
function determineCategory(authored, defaultsApplied) {
|
|
7244
|
-
if (authored.category) {
|
|
7245
|
-
return authored.category;
|
|
7246
|
-
}
|
|
7247
|
-
if (Array.isArray(authored.categories) && authored.categories.length > 0) {
|
|
7248
|
-
defaultsApplied.push("category \u2192 metadata.categories[0]");
|
|
7249
|
-
return authored.categories[0];
|
|
7250
|
-
}
|
|
7251
|
-
defaultsApplied.push("category \u2192 default category");
|
|
7252
|
-
return "utility";
|
|
7253
|
-
}
|
|
7254
|
-
function extractRepository(repository) {
|
|
7255
|
-
if (!repository) {
|
|
7256
|
-
return void 0;
|
|
7257
|
-
}
|
|
7258
|
-
if (typeof repository === "string") {
|
|
7259
|
-
return repository;
|
|
7260
|
-
}
|
|
7261
|
-
return repository.url;
|
|
7262
|
-
}
|
|
7263
|
-
function resolvePayment(authored, _defaults) {
|
|
7264
|
-
return authored.payment ?? void 0;
|
|
7265
|
-
}
|
|
7266
|
-
function buildDiscovery(authored) {
|
|
7267
|
-
const legacyDiscovery = {};
|
|
7268
|
-
if (Array.isArray(authored.keywords) && authored.keywords.length > 0) {
|
|
7269
|
-
legacyDiscovery.keywords = authored.keywords;
|
|
7270
|
-
}
|
|
7271
|
-
if (Array.isArray(authored.useCases) && authored.useCases.length > 0) {
|
|
7272
|
-
legacyDiscovery.useCases = authored.useCases;
|
|
7273
|
-
}
|
|
7274
|
-
if (Array.isArray(authored.capabilities) && authored.capabilities.length > 0) {
|
|
7275
|
-
legacyDiscovery.capabilities = authored.capabilities;
|
|
7276
|
-
}
|
|
7277
|
-
if (authored.requirements) {
|
|
7278
|
-
legacyDiscovery.requirements = authored.requirements;
|
|
7279
|
-
}
|
|
7280
|
-
if (authored.compatibility) {
|
|
7281
|
-
legacyDiscovery.compatibility = authored.compatibility;
|
|
7282
|
-
}
|
|
7283
|
-
if (Array.isArray(authored.categories) && authored.categories.length > 0) {
|
|
7284
|
-
legacyDiscovery.category = authored.categories[0];
|
|
7285
|
-
}
|
|
7286
|
-
const merged = {
|
|
7287
|
-
...legacyDiscovery,
|
|
7288
|
-
...authored.discovery
|
|
7289
|
-
};
|
|
7290
|
-
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
7291
|
-
}
|
|
7292
|
-
|
|
7293
|
-
// src/utils/schedule.ts
|
|
7294
|
-
var CRON_WRAPPED_REGEX = /^cron\((.*)\)$/i;
|
|
7295
|
-
var CRON_TOKEN_REGEX = /^[A-Za-z0-9*?/,\-#L]+$/;
|
|
7296
|
-
function normalizeScheduleExpression(raw, context) {
|
|
7297
|
-
const value = raw?.trim();
|
|
7298
|
-
if (!value) {
|
|
7299
|
-
throw new Error(`${context}: profile.schedule.cron must be a non-empty string`);
|
|
7300
|
-
}
|
|
7301
|
-
const cronBody = extractCronBody(value);
|
|
7302
|
-
const cronFields = cronBody.trim().split(/\s+/).filter(Boolean);
|
|
7303
|
-
if (cronFields.length !== 5 && cronFields.length !== 6) {
|
|
7304
|
-
throw new Error(
|
|
7305
|
-
`${context}: cron expression must have 5 or 6 fields (got ${cronFields.length})`
|
|
7306
|
-
);
|
|
7307
|
-
}
|
|
7308
|
-
validateCronTokens(cronFields, context);
|
|
7309
|
-
return {
|
|
7310
|
-
type: "cron",
|
|
7311
|
-
expression: cronFields.join(" ")
|
|
7312
|
-
};
|
|
7313
|
-
}
|
|
7314
|
-
function extractCronBody(value) {
|
|
7315
|
-
const cronMatch = CRON_WRAPPED_REGEX.exec(value);
|
|
7316
|
-
if (cronMatch) {
|
|
7317
|
-
return (cronMatch[1] ?? "").trim();
|
|
7318
|
-
}
|
|
7319
|
-
return value;
|
|
7320
|
-
}
|
|
7321
|
-
function validateCronTokens(fields, context) {
|
|
7322
|
-
fields.forEach((token2, idx) => {
|
|
7323
|
-
if (!CRON_TOKEN_REGEX.test(token2)) {
|
|
7324
|
-
throw new Error(`${context}: invalid cron token "${token2}" at position ${idx + 1}`);
|
|
7325
|
-
}
|
|
7326
|
-
});
|
|
7327
|
-
}
|
|
7328
|
-
|
|
7329
|
-
// src/cli/validate.ts
|
|
7330
|
-
var SUPPORTED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
7331
|
-
var OPENTOOL_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
7332
|
-
var OPENTOOL_NODE_MODULES = path5.join(OPENTOOL_ROOT, "node_modules");
|
|
7333
|
-
var MIN_TEMPLATE_CONFIG_VERSION = 2;
|
|
7334
|
-
var TEMPLATE_PREVIEW_TITLE_MAX = 80;
|
|
7335
|
-
var TEMPLATE_PREVIEW_SUBTITLE_MAX = 120;
|
|
7336
|
-
var TEMPLATE_PREVIEW_DESCRIPTION_MAX = 1200;
|
|
7337
|
-
var TEMPLATE_PREVIEW_MIN_LINES = 3;
|
|
7338
|
-
var TEMPLATE_PREVIEW_MAX_LINES = 8;
|
|
7339
|
-
function normalizeTemplateConfigVersion(value) {
|
|
7340
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
7341
|
-
return value;
|
|
7342
|
-
}
|
|
7343
|
-
if (typeof value !== "string") {
|
|
7344
|
-
return null;
|
|
7345
|
-
}
|
|
7346
|
-
const trimmed = value.trim();
|
|
7347
|
-
if (!trimmed) {
|
|
7348
|
-
return null;
|
|
7349
|
-
}
|
|
7350
|
-
if (/^\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
7351
|
-
const numeric = Number.parseFloat(trimmed);
|
|
7352
|
-
return Number.isFinite(numeric) ? numeric : null;
|
|
7353
|
-
}
|
|
7354
|
-
const majorMatch = /^v?(\d+)(?:\..*)?$/i.exec(trimmed);
|
|
7355
|
-
if (!majorMatch) {
|
|
7356
|
-
return null;
|
|
7357
|
-
}
|
|
7358
|
-
const major = Number.parseInt(majorMatch[1], 10);
|
|
7359
|
-
return Number.isFinite(major) ? major : null;
|
|
7360
|
-
}
|
|
7361
|
-
function parseNonEmptyString(value, fieldPath, opts = {}) {
|
|
7362
|
-
const { max, required = false } = opts;
|
|
7363
|
-
if (value == null) {
|
|
7364
|
-
if (required) {
|
|
7365
|
-
throw new Error(`${fieldPath} is required and must be a non-empty string.`);
|
|
7366
|
-
}
|
|
7367
|
-
return null;
|
|
7368
|
-
}
|
|
7369
|
-
if (typeof value !== "string") {
|
|
7370
|
-
throw new Error(`${fieldPath} must be a string.`);
|
|
7371
|
-
}
|
|
7372
|
-
const trimmed = value.trim();
|
|
7373
|
-
if (!trimmed) {
|
|
7374
|
-
throw new Error(`${fieldPath} must be a non-empty string.`);
|
|
7375
|
-
}
|
|
7376
|
-
if (typeof max === "number" && trimmed.length > max) {
|
|
7377
|
-
throw new Error(`${fieldPath} must be <= ${max} characters.`);
|
|
7378
|
-
}
|
|
7379
|
-
return trimmed;
|
|
7380
|
-
}
|
|
7381
|
-
function normalizeTemplatePreview(value, file, toolName, requirePreview) {
|
|
7382
|
-
const pathPrefix = `${file}: profile.templatePreview`;
|
|
7383
|
-
if (value == null) {
|
|
7384
|
-
if (requirePreview) {
|
|
7385
|
-
throw new Error(
|
|
7386
|
-
`${pathPrefix} is required for strategy tools and must define subtitle + description.`
|
|
7387
|
-
);
|
|
7388
|
-
}
|
|
7389
|
-
return null;
|
|
7390
|
-
}
|
|
7391
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7392
|
-
throw new Error(`${pathPrefix} must be an object.`);
|
|
7393
|
-
}
|
|
7394
|
-
const record = value;
|
|
7395
|
-
const title = parseNonEmptyString(record.title, `${pathPrefix}.title`, {
|
|
7396
|
-
max: TEMPLATE_PREVIEW_TITLE_MAX
|
|
7397
|
-
}) ?? toolName;
|
|
7398
|
-
const subtitle = parseNonEmptyString(record.subtitle, `${pathPrefix}.subtitle`, {
|
|
7399
|
-
required: true,
|
|
7400
|
-
max: TEMPLATE_PREVIEW_SUBTITLE_MAX
|
|
7401
|
-
});
|
|
7402
|
-
const description = parseNonEmptyString(record.description, `${pathPrefix}.description`, {
|
|
7403
|
-
required: true,
|
|
7404
|
-
max: TEMPLATE_PREVIEW_DESCRIPTION_MAX
|
|
7405
|
-
});
|
|
7406
|
-
const descriptionLineCount = description.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).length;
|
|
7407
|
-
if (descriptionLineCount < TEMPLATE_PREVIEW_MIN_LINES || descriptionLineCount > TEMPLATE_PREVIEW_MAX_LINES) {
|
|
7408
|
-
throw new Error(
|
|
7409
|
-
`${pathPrefix}.description must contain ${TEMPLATE_PREVIEW_MIN_LINES}-${TEMPLATE_PREVIEW_MAX_LINES} non-empty lines (target ~5 lines).`
|
|
7410
|
-
);
|
|
7411
|
-
}
|
|
7412
|
-
return {
|
|
7413
|
-
title,
|
|
7414
|
-
subtitle,
|
|
7415
|
-
description
|
|
7416
|
-
};
|
|
7417
|
-
}
|
|
7418
|
-
async function validateCommand(options) {
|
|
7419
|
-
console.log("\u{1F50D} Validating OpenTool project...");
|
|
7420
|
-
try {
|
|
7421
|
-
const toolsDir = path5.resolve(options.input);
|
|
7422
|
-
if (!fs4.existsSync(toolsDir)) {
|
|
7423
|
-
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
7424
|
-
}
|
|
7425
|
-
const projectRoot = path5.dirname(toolsDir);
|
|
7426
|
-
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
7427
|
-
if (tools.length === 0) {
|
|
7428
|
-
throw new Error("No valid tools found - validation aborted");
|
|
7429
|
-
}
|
|
7430
|
-
const { metadata, defaultsApplied, sourceMetadataPath } = await buildMetadataArtifact({
|
|
7431
|
-
projectRoot,
|
|
7432
|
-
tools
|
|
7433
|
-
});
|
|
7434
|
-
logMetadataSummary(metadata, defaultsApplied, sourceMetadataPath);
|
|
7435
|
-
console.log("\n\u2705 OpenTool validation passed!\n");
|
|
7436
|
-
} catch (error) {
|
|
7437
|
-
console.error("\u274C OpenTool validation failed:", error);
|
|
7438
|
-
process.exit(1);
|
|
7439
|
-
}
|
|
7440
|
-
}
|
|
7441
|
-
async function loadAndValidateTools(toolsDir, options = {}) {
|
|
7442
|
-
const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(path5.extname(file)));
|
|
7443
|
-
if (files.length === 0) {
|
|
7444
|
-
return [];
|
|
7445
|
-
}
|
|
7446
|
-
const projectRoot = options.projectRoot ?? path5.dirname(toolsDir);
|
|
7447
|
-
const tempDir = path5.join(toolsDir, ".opentool-temp");
|
|
7448
|
-
if (fs4.existsSync(tempDir)) {
|
|
7449
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7450
|
-
}
|
|
7451
|
-
const kebabCase = /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z]+$/;
|
|
7452
|
-
for (const f of files) {
|
|
7453
|
-
if (!kebabCase.test(f)) {
|
|
7454
|
-
throw new Error(`Tool filename must be kebab-case: ${f}`);
|
|
7455
|
-
}
|
|
7456
|
-
}
|
|
7457
|
-
const entryPoints = files.map((file) => path5.join(toolsDir, file));
|
|
7458
|
-
const fallbackNodePaths = [OPENTOOL_NODE_MODULES].filter((dir) => fs4.existsSync(dir));
|
|
7459
|
-
const { outDir, cleanup } = await transpileWithEsbuild({
|
|
7460
|
-
entryPoints,
|
|
7461
|
-
projectRoot,
|
|
7462
|
-
format: "esm",
|
|
7463
|
-
outDir: tempDir,
|
|
7464
|
-
bundle: true,
|
|
7465
|
-
external: ["opentool", "opentool/*"],
|
|
7466
|
-
...fallbackNodePaths.length > 0 ? { nodePaths: fallbackNodePaths } : {}
|
|
7467
|
-
});
|
|
7468
|
-
const tools = [];
|
|
7469
|
-
try {
|
|
7470
|
-
ensureLocalRuntimeLinks(tempDir);
|
|
7471
|
-
for (const file of files) {
|
|
7472
|
-
const compiledPath = resolveCompiledPath(outDir, file);
|
|
7473
|
-
if (!fs4.existsSync(compiledPath)) {
|
|
7474
|
-
throw new Error(`Failed to compile ${file}`);
|
|
7475
|
-
}
|
|
7476
|
-
const moduleExports = await importFresh(compiledPath);
|
|
7477
|
-
const toolModule = extractToolModule(moduleExports, file);
|
|
7478
|
-
const schema = ensureZodSchema(toolModule.schema, file);
|
|
7479
|
-
const paymentExport = toolModule.payment;
|
|
7480
|
-
const toolName = toolModule.metadata?.name ?? toolModule.metadata?.title ?? toBaseName(file);
|
|
7481
|
-
const inputSchemaRaw = schema ? toJsonSchema(toolName, schema) : void 0;
|
|
7482
|
-
const inputSchema = normalizeInputSchema2(inputSchemaRaw);
|
|
7483
|
-
const httpHandlersRaw = collectHttpHandlers2(toolModule, file);
|
|
7484
|
-
const hasGET = typeof toolModule.GET === "function";
|
|
7485
|
-
const hasPOST = typeof toolModule.POST === "function";
|
|
7486
|
-
const otherMethods = HTTP_METHODS2.filter((m) => m !== "GET" && m !== "POST").filter(
|
|
7487
|
-
(m) => typeof toolModule[m] === "function"
|
|
7488
|
-
);
|
|
7489
|
-
if (otherMethods.length > 0) {
|
|
7490
|
-
throw new Error(
|
|
7491
|
-
`${file} must not export ${otherMethods.join(", ")}. Only one of GET or POST is allowed.`
|
|
7492
|
-
);
|
|
7493
|
-
}
|
|
7494
|
-
if (hasGET === hasPOST) {
|
|
7495
|
-
throw new Error(`${file}: export exactly one of GET or POST`);
|
|
7496
|
-
}
|
|
7497
|
-
let normalizedSchedule = null;
|
|
7498
|
-
const profileRaw = toolModule?.profile && typeof toolModule.profile === "object" ? toolModule.profile : null;
|
|
7499
|
-
const schedule = profileRaw?.schedule ?? null;
|
|
7500
|
-
const profileNotifyEmail = typeof profileRaw?.notifyEmail === "boolean" ? profileRaw.notifyEmail : void 0;
|
|
7501
|
-
const allowedProfileCategories = ["strategy", "tracker", "orchestrator"];
|
|
7502
|
-
const profileCategoryCandidate = typeof profileRaw?.category === "string" ? profileRaw.category : void 0;
|
|
7503
|
-
let profileCategoryRaw;
|
|
7504
|
-
if (profileCategoryCandidate !== void 0) {
|
|
7505
|
-
const isAllowed = allowedProfileCategories.includes(
|
|
7506
|
-
profileCategoryCandidate
|
|
7507
|
-
);
|
|
7508
|
-
if (!isAllowed) {
|
|
7509
|
-
throw new Error(
|
|
7510
|
-
`${file}: profile.category must be one of ${allowedProfileCategories.join(", ")}`
|
|
7511
|
-
);
|
|
7512
|
-
}
|
|
7513
|
-
profileCategoryRaw = profileCategoryCandidate;
|
|
7514
|
-
}
|
|
7515
|
-
const profileAssetsRaw = profileRaw?.assets;
|
|
7516
|
-
if (profileAssetsRaw !== void 0) {
|
|
7517
|
-
if (!Array.isArray(profileAssetsRaw)) {
|
|
7518
|
-
throw new Error(`${file}: profile.assets must be an array.`);
|
|
7519
|
-
}
|
|
7520
|
-
profileAssetsRaw.forEach((entry, index) => {
|
|
7521
|
-
if (!entry || typeof entry !== "object") {
|
|
7522
|
-
throw new Error(`${file}: profile.assets[${index}] must be an object.`);
|
|
7523
|
-
}
|
|
7524
|
-
const record = entry;
|
|
7525
|
-
const venue = typeof record.venue === "string" ? record.venue.trim() : "";
|
|
7526
|
-
if (!venue) {
|
|
7527
|
-
throw new Error(`${file}: profile.assets[${index}].venue must be a non-empty string.`);
|
|
7528
|
-
}
|
|
7529
|
-
const chain = record.chain;
|
|
7530
|
-
if (typeof chain !== "string" && typeof chain !== "number") {
|
|
7531
|
-
throw new Error(`${file}: profile.assets[${index}].chain must be a string or number.`);
|
|
7532
|
-
}
|
|
7533
|
-
const symbols = record.assetSymbols;
|
|
7534
|
-
if (!Array.isArray(symbols) || symbols.length === 0) {
|
|
7535
|
-
throw new Error(
|
|
7536
|
-
`${file}: profile.assets[${index}].assetSymbols must be a non-empty array.`
|
|
7537
|
-
);
|
|
7538
|
-
}
|
|
7539
|
-
const invalidSymbol = symbols.find(
|
|
7540
|
-
(symbol) => typeof symbol !== "string" || symbol.trim().length === 0
|
|
7541
|
-
);
|
|
7542
|
-
if (invalidSymbol !== void 0) {
|
|
7543
|
-
throw new Error(
|
|
7544
|
-
`${file}: profile.assets[${index}].assetSymbols must be non-empty strings.`
|
|
7545
|
-
);
|
|
7546
|
-
}
|
|
7547
|
-
const walletAddress = record.walletAddress;
|
|
7548
|
-
if (walletAddress !== void 0 && (typeof walletAddress !== "string" || walletAddress.trim().length === 0)) {
|
|
7549
|
-
throw new Error(
|
|
7550
|
-
`${file}: profile.assets[${index}].walletAddress must be a non-empty string when provided.`
|
|
7551
|
-
);
|
|
7552
|
-
}
|
|
7553
|
-
const pair = record.pair;
|
|
7554
|
-
if (pair !== void 0 && (typeof pair !== "string" || pair.trim().length === 0)) {
|
|
7555
|
-
throw new Error(
|
|
7556
|
-
`${file}: profile.assets[${index}].pair must be a non-empty string when provided.`
|
|
7557
|
-
);
|
|
7558
|
-
}
|
|
7559
|
-
const leverage = record.leverage;
|
|
7560
|
-
if (leverage !== void 0 && (typeof leverage !== "number" || !Number.isFinite(leverage) || leverage <= 0)) {
|
|
7561
|
-
throw new Error(
|
|
7562
|
-
`${file}: profile.assets[${index}].leverage must be a positive number when provided.`
|
|
7563
|
-
);
|
|
7564
|
-
}
|
|
7565
|
-
});
|
|
7566
|
-
}
|
|
7567
|
-
const templateConfigRaw = profileRaw?.templateConfig;
|
|
7568
|
-
if (templateConfigRaw !== void 0) {
|
|
7569
|
-
if (!templateConfigRaw || typeof templateConfigRaw !== "object") {
|
|
7570
|
-
throw new Error(`${file}: profile.templateConfig must be an object.`);
|
|
7571
|
-
}
|
|
7572
|
-
const record = templateConfigRaw;
|
|
7573
|
-
const version = record.version;
|
|
7574
|
-
const normalizedTemplateConfigVersion = normalizeTemplateConfigVersion(version);
|
|
7575
|
-
if (normalizedTemplateConfigVersion === null) {
|
|
7576
|
-
throw new Error(
|
|
7577
|
-
`${file}: profile.templateConfig.version must be a numeric string or number.`
|
|
7578
|
-
);
|
|
7579
|
-
}
|
|
7580
|
-
if (normalizedTemplateConfigVersion < MIN_TEMPLATE_CONFIG_VERSION) {
|
|
7581
|
-
throw new Error(
|
|
7582
|
-
`${file}: profile.templateConfig.version must be >= ${MIN_TEMPLATE_CONFIG_VERSION}.`
|
|
7583
|
-
);
|
|
7584
|
-
}
|
|
7585
|
-
const schema2 = record.schema;
|
|
7586
|
-
if (schema2 !== void 0 && (!schema2 || typeof schema2 !== "object" || Array.isArray(schema2))) {
|
|
7587
|
-
throw new Error(
|
|
7588
|
-
`${file}: profile.templateConfig.schema must be an object when provided.`
|
|
7589
|
-
);
|
|
7590
|
-
}
|
|
7591
|
-
const defaults = record.defaults;
|
|
7592
|
-
if (defaults !== void 0 && (!defaults || typeof defaults !== "object" || Array.isArray(defaults))) {
|
|
7593
|
-
throw new Error(
|
|
7594
|
-
`${file}: profile.templateConfig.defaults must be an object when provided.`
|
|
7595
|
-
);
|
|
7596
|
-
}
|
|
7597
|
-
const envVar = record.envVar;
|
|
7598
|
-
if (envVar !== void 0 && (typeof envVar !== "string" || envVar.trim().length === 0)) {
|
|
7599
|
-
throw new Error(
|
|
7600
|
-
`${file}: profile.templateConfig.envVar must be a non-empty string when provided.`
|
|
7601
|
-
);
|
|
7602
|
-
}
|
|
7603
|
-
}
|
|
7604
|
-
const normalizedTemplatePreview = normalizeTemplatePreview(
|
|
7605
|
-
profileRaw?.templatePreview,
|
|
7606
|
-
file,
|
|
7607
|
-
toolName,
|
|
7608
|
-
profileCategoryRaw === "strategy"
|
|
7609
|
-
);
|
|
7610
|
-
const normalizedProfile = profileRaw && normalizedTemplatePreview ? { ...profileRaw, templatePreview: normalizedTemplatePreview } : profileRaw;
|
|
7611
|
-
if (hasGET && schedule && typeof schedule.cron === "string" && schedule.cron.trim().length > 0) {
|
|
7612
|
-
normalizedSchedule = normalizeScheduleExpression(schedule.cron, file);
|
|
7613
|
-
if (typeof schedule.enabled === "boolean") {
|
|
7614
|
-
normalizedSchedule.authoredEnabled = schedule.enabled;
|
|
7615
|
-
}
|
|
7616
|
-
if (typeof schedule.notifyEmail === "boolean") {
|
|
7617
|
-
normalizedSchedule.notifyEmail = schedule.notifyEmail;
|
|
7618
|
-
}
|
|
7619
|
-
}
|
|
7620
|
-
if (hasPOST) {
|
|
7621
|
-
if (!schema) {
|
|
7622
|
-
throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
|
|
7623
|
-
}
|
|
7624
|
-
}
|
|
7625
|
-
const httpHandlers = [...httpHandlersRaw];
|
|
7626
|
-
if (httpHandlers.length === 0) {
|
|
7627
|
-
throw new Error(`${file} must export at least one HTTP handler (e.g. POST)`);
|
|
7628
|
-
}
|
|
7629
|
-
if (paymentExport) {
|
|
7630
|
-
for (let index = 0; index < httpHandlers.length; index += 1) {
|
|
7631
|
-
const entry = httpHandlers[index];
|
|
7632
|
-
httpHandlers[index] = {
|
|
7633
|
-
...entry,
|
|
7634
|
-
handler: withX402Payment(entry.handler, paymentExport)
|
|
7635
|
-
};
|
|
7636
|
-
}
|
|
7637
|
-
}
|
|
7638
|
-
const httpHandlerMap = toHttpHandlerMap2(httpHandlers);
|
|
7639
|
-
const defaultMethod = typeof toolModule.mcp?.defaultMethod === "string" ? toolModule.mcp.defaultMethod : void 0;
|
|
7640
|
-
const adapter = createMcpAdapter({
|
|
7641
|
-
name: toolName,
|
|
7642
|
-
httpHandlers: httpHandlerMap,
|
|
7643
|
-
...defaultMethod ? { defaultMethod } : {},
|
|
7644
|
-
...schema ? { schema } : {}
|
|
7645
|
-
});
|
|
7646
|
-
let metadataOverrides = toolModule.metadata ?? null;
|
|
7647
|
-
if (paymentExport) {
|
|
7648
|
-
if (metadataOverrides) {
|
|
7649
|
-
metadataOverrides = {
|
|
7650
|
-
...metadataOverrides,
|
|
7651
|
-
payment: metadataOverrides.payment ?? paymentExport,
|
|
7652
|
-
annotations: {
|
|
7653
|
-
...metadataOverrides.annotations,
|
|
7654
|
-
requiresPayment: metadataOverrides.annotations?.requiresPayment ?? true
|
|
7655
|
-
}
|
|
7656
|
-
};
|
|
7657
|
-
} else {
|
|
7658
|
-
metadataOverrides = {
|
|
7659
|
-
payment: paymentExport,
|
|
7660
|
-
annotations: { requiresPayment: true }
|
|
7661
|
-
};
|
|
7662
|
-
}
|
|
7663
|
-
}
|
|
7664
|
-
const tool = {
|
|
7665
|
-
schema: schema ?? void 0,
|
|
7666
|
-
inputSchema,
|
|
7667
|
-
metadata: metadataOverrides,
|
|
7668
|
-
httpHandlers,
|
|
7669
|
-
mcpConfig: normalizeMcpConfig(toolModule.mcp, file),
|
|
7670
|
-
filename: toBaseName(file),
|
|
7671
|
-
sourcePath: path5.join(toolsDir, file),
|
|
7672
|
-
handler: async (params) => adapter(params),
|
|
7673
|
-
payment: paymentExport ?? null,
|
|
7674
|
-
schedule: normalizedSchedule,
|
|
7675
|
-
profile: normalizedProfile,
|
|
7676
|
-
...profileNotifyEmail !== void 0 ? { notifyEmail: profileNotifyEmail } : {},
|
|
7677
|
-
profileDescription: typeof profileRaw?.description === "string" ? profileRaw.description : null,
|
|
7678
|
-
...profileCategoryRaw ? { profileCategory: profileCategoryRaw } : {}
|
|
7679
|
-
};
|
|
7680
|
-
tools.push(tool);
|
|
7681
|
-
}
|
|
7682
|
-
} finally {
|
|
7683
|
-
cleanup();
|
|
7684
|
-
if (fs4.existsSync(tempDir)) {
|
|
7685
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7686
|
-
}
|
|
7687
|
-
}
|
|
7688
|
-
return tools;
|
|
7689
|
-
}
|
|
7690
|
-
function ensureLocalRuntimeLinks(tempDir) {
|
|
7691
|
-
const nodeModulesDir = path5.join(tempDir, "node_modules");
|
|
7692
|
-
fs4.mkdirSync(nodeModulesDir, { recursive: true });
|
|
7693
|
-
const packageLinks = [
|
|
7694
|
-
{ name: "opentool", target: OPENTOOL_ROOT },
|
|
7695
|
-
{ name: "zod", target: path5.join(OPENTOOL_NODE_MODULES, "zod") }
|
|
7696
|
-
];
|
|
7697
|
-
for (const { name, target } of packageLinks) {
|
|
7698
|
-
if (!fs4.existsSync(target)) {
|
|
7699
|
-
continue;
|
|
7700
|
-
}
|
|
7701
|
-
const linkPath = path5.join(nodeModulesDir, name);
|
|
7702
|
-
if (fs4.existsSync(linkPath)) {
|
|
7703
|
-
continue;
|
|
7704
|
-
}
|
|
7705
|
-
fs4.symlinkSync(target, linkPath, "junction");
|
|
7706
|
-
}
|
|
7707
|
-
}
|
|
7708
|
-
function extractToolModule(exportsObject, filename) {
|
|
7709
|
-
const candidates = [exportsObject, exportsObject?.default];
|
|
7710
|
-
for (const candidate of candidates) {
|
|
7711
|
-
if (candidate && typeof candidate === "object") {
|
|
7712
|
-
const hasSchema = candidate.schema && typeof candidate.schema === "object";
|
|
7713
|
-
const hasHttp = HTTP_METHODS2.some((method) => typeof candidate[method] === "function");
|
|
7714
|
-
if (hasSchema || hasHttp) {
|
|
7715
|
-
return candidate;
|
|
7716
|
-
}
|
|
7717
|
-
}
|
|
7718
|
-
}
|
|
7719
|
-
throw new Error(
|
|
7720
|
-
`${filename} must export a tool definition. Expected a Zod schema plus HTTP handlers (export async function POST).`
|
|
7721
|
-
);
|
|
7722
|
-
}
|
|
7723
|
-
function toJsonSchema(name, schema) {
|
|
7724
|
-
if (!schema) {
|
|
7725
|
-
return void 0;
|
|
7726
|
-
}
|
|
7727
|
-
try {
|
|
7728
|
-
return zodToJsonSchema(schema, {
|
|
7729
|
-
name: `${name}Schema`,
|
|
7730
|
-
target: "jsonSchema7",
|
|
7731
|
-
$refStrategy: "none"
|
|
7732
|
-
});
|
|
7733
|
-
} catch (error) {
|
|
7734
|
-
throw new Error(`Failed to convert Zod schema for ${name}: ${error}`);
|
|
7735
|
-
}
|
|
7736
|
-
}
|
|
7737
|
-
function toBaseName(file) {
|
|
7738
|
-
return file.replace(/\.[^.]+$/, "");
|
|
7739
|
-
}
|
|
7740
|
-
function ensureZodSchema(schemaCandidate, filename) {
|
|
7741
|
-
if (schemaCandidate == null) {
|
|
7742
|
-
return void 0;
|
|
7743
|
-
}
|
|
7744
|
-
if (schemaCandidate instanceof z.ZodType) {
|
|
7745
|
-
return schemaCandidate;
|
|
7746
|
-
}
|
|
7747
|
-
const schema = schemaCandidate;
|
|
7748
|
-
if (typeof schema?.parse !== "function") {
|
|
7749
|
-
throw new Error(`${filename} schema export must be a Zod schema (missing parse method)`);
|
|
7750
|
-
}
|
|
7751
|
-
return schema;
|
|
7752
|
-
}
|
|
7753
|
-
function collectHttpHandlers2(module, filename) {
|
|
7754
|
-
const handlers = [];
|
|
7755
|
-
for (const method of HTTP_METHODS2) {
|
|
7756
|
-
const handler = module?.[method];
|
|
7757
|
-
if (typeof handler === "function") {
|
|
7758
|
-
handlers.push({
|
|
7759
|
-
method,
|
|
7760
|
-
handler: async (request) => handler.call(module, request)
|
|
7761
|
-
});
|
|
7762
|
-
}
|
|
7763
|
-
}
|
|
7764
|
-
handlers.sort((a, b) => HTTP_METHODS2.indexOf(a.method) - HTTP_METHODS2.indexOf(b.method));
|
|
7765
|
-
const duplicates = findDuplicates(handlers.map((h) => h.method));
|
|
7766
|
-
if (duplicates.length > 0) {
|
|
7767
|
-
throw new Error(
|
|
7768
|
-
`${filename} exports multiple handlers for HTTP method(s): ${duplicates.join(", ")}`
|
|
7769
|
-
);
|
|
7770
|
-
}
|
|
7771
|
-
return handlers;
|
|
7772
|
-
}
|
|
7773
|
-
function toHttpHandlerMap2(handlers) {
|
|
7774
|
-
return handlers.reduce((acc, handler) => {
|
|
7775
|
-
acc[handler.method.toUpperCase()] = handler.handler;
|
|
7776
|
-
return acc;
|
|
7777
|
-
}, {});
|
|
7778
|
-
}
|
|
7779
|
-
function normalizeInputSchema2(schema) {
|
|
7780
|
-
if (!schema || typeof schema !== "object") {
|
|
7781
|
-
return schema;
|
|
7782
|
-
}
|
|
7783
|
-
const clone = JSON.parse(JSON.stringify(schema));
|
|
7784
|
-
if (typeof clone.$ref === "string" && clone.$ref.startsWith("#/definitions/")) {
|
|
7785
|
-
const refName = clone.$ref.replace("#/definitions/", "");
|
|
7786
|
-
const definitions = clone.definitions;
|
|
7787
|
-
if (definitions && typeof definitions[refName] === "object") {
|
|
7788
|
-
return normalizeInputSchema2(definitions[refName]);
|
|
7789
|
-
}
|
|
7790
|
-
}
|
|
7791
|
-
delete clone.$ref;
|
|
7792
|
-
delete clone.definitions;
|
|
7793
|
-
if (!("type" in clone)) {
|
|
7794
|
-
clone.type = "object";
|
|
7795
|
-
}
|
|
7796
|
-
return clone;
|
|
7797
|
-
}
|
|
7798
|
-
function normalizeMcpConfig(rawConfig, filename) {
|
|
7799
|
-
if (rawConfig == null) {
|
|
7800
|
-
return null;
|
|
7801
|
-
}
|
|
7802
|
-
if (rawConfig === false) {
|
|
7803
|
-
return null;
|
|
7804
|
-
}
|
|
7805
|
-
if (rawConfig === true) {
|
|
7806
|
-
return { enabled: true };
|
|
7807
|
-
}
|
|
7808
|
-
if (!isPlainObject2(rawConfig)) {
|
|
7809
|
-
throw new Error(`${filename} export \\"mcp\\" must be an object with an enabled flag`);
|
|
7810
|
-
}
|
|
7811
|
-
const enabledRaw = rawConfig.enabled;
|
|
7812
|
-
if (enabledRaw === false) {
|
|
7813
|
-
return null;
|
|
7814
|
-
}
|
|
7815
|
-
if (enabledRaw !== true) {
|
|
7816
|
-
throw new Error(`${filename} mcp.enabled must be explicitly set to true to opt-in to MCP`);
|
|
7817
|
-
}
|
|
7818
|
-
const modeRaw = rawConfig.mode;
|
|
7819
|
-
let mode;
|
|
7820
|
-
if (typeof modeRaw === "string") {
|
|
7821
|
-
const normalized = modeRaw.toLowerCase();
|
|
7822
|
-
if (["stdio", "lambda", "dual"].includes(normalized)) {
|
|
7823
|
-
mode = normalized;
|
|
7824
|
-
} else {
|
|
7825
|
-
throw new Error(
|
|
7826
|
-
`${filename} mcp.mode must be one of "stdio", "lambda", or "dual" if specified`
|
|
7827
|
-
);
|
|
7828
|
-
}
|
|
7829
|
-
}
|
|
7830
|
-
const defaultMethodRaw = rawConfig.defaultMethod;
|
|
7831
|
-
const defaultMethod = typeof defaultMethodRaw === "string" ? defaultMethodRaw.toUpperCase() : void 0;
|
|
7832
|
-
const overridesRaw = rawConfig.metadataOverrides;
|
|
7833
|
-
const metadataOverrides = isPlainObject2(overridesRaw) ? overridesRaw : void 0;
|
|
7834
|
-
const config = {
|
|
7835
|
-
enabled: true
|
|
7836
|
-
};
|
|
7837
|
-
if (mode) {
|
|
7838
|
-
config.mode = mode;
|
|
7839
|
-
}
|
|
7840
|
-
if (defaultMethod) {
|
|
7841
|
-
config.defaultMethod = defaultMethod;
|
|
7842
|
-
}
|
|
7843
|
-
if (metadataOverrides) {
|
|
7844
|
-
config.metadataOverrides = metadataOverrides;
|
|
7845
|
-
}
|
|
7846
|
-
return config;
|
|
7847
|
-
}
|
|
7848
|
-
function isPlainObject2(value) {
|
|
7849
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7850
|
-
}
|
|
7851
|
-
function findDuplicates(values) {
|
|
7852
|
-
const seen = /* @__PURE__ */ new Map();
|
|
7853
|
-
const duplicates = /* @__PURE__ */ new Set();
|
|
7854
|
-
values.forEach((value) => {
|
|
7855
|
-
const count = seen.get(value) ?? 0;
|
|
7856
|
-
seen.set(value, count + 1);
|
|
7857
|
-
if (count >= 1) {
|
|
7858
|
-
duplicates.add(value);
|
|
7859
|
-
}
|
|
7860
|
-
});
|
|
7861
|
-
return Array.from(duplicates.values());
|
|
7862
|
-
}
|
|
7863
|
-
function logMetadataSummary(metadata, defaultsApplied, sourceMetadataPath) {
|
|
7864
|
-
console.log(`\u{1F4C4} metadata loaded from ${sourceMetadataPath}`);
|
|
7865
|
-
console.log("\n\u{1F4CA} Metadata Summary:");
|
|
7866
|
-
console.log(` \u2022 Name: ${metadata.name}`);
|
|
7867
|
-
console.log(` \u2022 Display Name: ${metadata.displayName}`);
|
|
7868
|
-
console.log(` \u2022 Version: ${metadata.version}`);
|
|
7869
|
-
console.log(` \u2022 Category: ${metadata.category}`);
|
|
7870
|
-
console.log(` \u2022 Tools: ${metadata.tools.length}`);
|
|
7871
|
-
console.log(` \u2022 Spec Version: ${metadata.metadataSpecVersion}`);
|
|
7872
|
-
if (metadata.payment) {
|
|
7873
|
-
console.log(` \u2022 Payment: $${metadata.payment.amountUSDC} USDC`);
|
|
7874
|
-
}
|
|
7875
|
-
if (defaultsApplied.length > 0) {
|
|
7876
|
-
console.log("\nDefaults applied during metadata synthesis:");
|
|
7877
|
-
defaultsApplied.forEach((entry) => console.log(` \u2022 ${entry}`));
|
|
7878
|
-
}
|
|
7879
|
-
}
|
|
7880
|
-
|
|
7881
|
-
// src/cli/generate-metadata.ts
|
|
7882
|
-
async function generateMetadataCommand(options) {
|
|
7883
|
-
const startTimestamp = timestamp();
|
|
7884
|
-
console.log(`[${startTimestamp}] Generating OpenTool metadata...`);
|
|
7885
|
-
try {
|
|
7886
|
-
const result = await generateMetadata(options);
|
|
7887
|
-
const endTimestamp = timestamp();
|
|
7888
|
-
console.log(`[${endTimestamp}] Metadata generation completed successfully!`);
|
|
7889
|
-
console.log(`Output file: ${result.outputPath}`);
|
|
7890
|
-
console.log(`Spec version: ${result.metadata.metadataSpecVersion}`);
|
|
7891
|
-
console.log(`Tools included: ${result.tools.length}`);
|
|
7892
|
-
if (result.defaultsApplied.length > 0) {
|
|
7893
|
-
console.log("Applied defaults:");
|
|
7894
|
-
for (const entry of result.defaultsApplied) {
|
|
7895
|
-
console.log(` \u2022 ${entry}`);
|
|
7896
|
-
}
|
|
7897
|
-
}
|
|
7898
|
-
} catch (error) {
|
|
7899
|
-
const endTimestamp = timestamp();
|
|
7900
|
-
console.error(`[${endTimestamp}] Metadata generation failed:`, error);
|
|
7901
|
-
process.exit(1);
|
|
7902
|
-
}
|
|
7903
|
-
}
|
|
7904
|
-
async function generateMetadata(options) {
|
|
7905
|
-
const toolsDir = path5.resolve(options.input);
|
|
7906
|
-
if (!fs4.existsSync(toolsDir)) {
|
|
7907
|
-
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
7908
|
-
}
|
|
7909
|
-
const projectRoot = path5.dirname(toolsDir);
|
|
7910
|
-
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
7911
|
-
const { metadata, defaultsApplied } = await buildMetadataArtifact({
|
|
7912
|
-
projectRoot,
|
|
7913
|
-
tools
|
|
7914
|
-
});
|
|
7915
|
-
const outputPath = options.output ? path5.resolve(options.output) : path5.join(projectRoot, "metadata.json");
|
|
7916
|
-
fs4.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
|
|
7917
|
-
return {
|
|
7918
|
-
metadata,
|
|
7919
|
-
defaultsApplied,
|
|
7920
|
-
tools,
|
|
7921
|
-
outputPath
|
|
7922
|
-
};
|
|
7923
|
-
}
|
|
7924
|
-
function timestamp() {
|
|
7925
|
-
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
7926
|
-
}
|
|
7927
6846
|
|
|
7928
|
-
export { AIAbortError, AIError, AIFetchError, AIResponseError, BACKTEST_DECISION_MODE, DEFAULT_BASE_URL, DEFAULT_CHAIN, DEFAULT_FACILITATOR, DEFAULT_HYPERLIQUID_CADENCE_CRON, DEFAULT_HYPERLIQUID_MARKET_SLIPPAGE_BPS, DEFAULT_MODEL, DEFAULT_OPENPOND_GATEWAY_URL2 as DEFAULT_OPENPOND_GATEWAY_URL, DEFAULT_TIMEOUT_MS, DEFAULT_TOKENS, HTTP_METHODS2 as HTTP_METHODS, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, NewsSignalClient, PAYMENT_HEADERS, POLYMARKET_CHAIN_ID, POLYMARKET_CLOB_AUTH_DOMAIN, POLYMARKET_CLOB_DOMAIN, POLYMARKET_ENDPOINTS, POLYMARKET_EXCHANGE_ADDRESSES, PolymarketApiError, PolymarketAuthError, PolymarketExchangeClient, PolymarketInfoClient, SUPPORTED_CURRENCIES, StoreError, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, X402BrowserClient, X402Client, X402PaymentRequiredError, __hyperliquidInternals, __hyperliquidMarketDataInternals, approveHyperliquidBuilderFee, backtestDecisionRequestSchema, batchModifyHyperliquidOrders, buildBacktestDecisionSeriesInput, buildHmacSignature, buildHyperliquidMarketIdentity, buildHyperliquidProfileAssets, buildHyperliquidSpotUsdPriceMap, buildL1Headers, buildL2Headers, buildPolymarketOrderAmounts, buildSignedOrderPayload, cancelAllHyperliquidOrders, cancelAllPolymarketOrders, cancelHyperliquidOrders, cancelHyperliquidOrdersByCloid, cancelHyperliquidTwapOrder, cancelMarketPolymarketOrders, cancelPolymarketOrder, cancelPolymarketOrders, chains, clampHyperliquidAbs, clampHyperliquidFloat, clampHyperliquidInt, computeHyperliquidMarketIocLimitPrice, createAIClient, createDevServer, createHyperliquidSubAccount, createMcpAdapter, createMonotonicNonceFactory, createPolymarketApiKey, createStdioServer, defineX402Payment, depositToHyperliquidBridge, derivePolymarketApiKey, ensureTextContent, estimateCountBack, evaluateNewsContinuationGate, executeTool, extractHyperliquidDex, extractHyperliquidOrderIds, fetchHyperliquidAllMids, fetchHyperliquidAssetCtxs, fetchHyperliquidBars, fetchHyperliquidClearinghouseState, fetchHyperliquidFrontendOpenOrders, fetchHyperliquidHistoricalOrders, fetchHyperliquidMeta, fetchHyperliquidMetaAndAssetCtxs, fetchHyperliquidOpenOrders, fetchHyperliquidOrderStatus, fetchHyperliquidPerpMarketInfo, fetchHyperliquidPreTransferCheck, fetchHyperliquidSizeDecimals, fetchHyperliquidSpotAccountValue, fetchHyperliquidSpotAssetCtxs, fetchHyperliquidSpotClearinghouseState, fetchHyperliquidSpotMarketInfo, fetchHyperliquidSpotMeta, fetchHyperliquidSpotMetaAndAssetCtxs, fetchHyperliquidSpotTickSize, fetchHyperliquidSpotUsdPriceMap, fetchHyperliquidTickSize, fetchHyperliquidUserFills, fetchHyperliquidUserFillsByTime, fetchHyperliquidUserRateLimit, fetchNewsEventSignal, fetchNewsPropositionSignal, fetchPolymarketMarket, fetchPolymarketMarkets, fetchPolymarketMidpoint, fetchPolymarketOrderbook, fetchPolymarketPrice, fetchPolymarketPriceHistory, flattenMessageContent, formatHyperliquidMarketablePrice, formatHyperliquidOrderSize, formatHyperliquidPrice, formatHyperliquidSize,
|
|
6847
|
+
export { AIAbortError, AIError, AIFetchError, AIResponseError, BACKTEST_DECISION_MODE, DEFAULT_BASE_URL, DEFAULT_CHAIN, DEFAULT_FACILITATOR, DEFAULT_HYPERLIQUID_CADENCE_CRON, DEFAULT_HYPERLIQUID_MARKET_SLIPPAGE_BPS, DEFAULT_MODEL, DEFAULT_OPENPOND_GATEWAY_URL2 as DEFAULT_OPENPOND_GATEWAY_URL, DEFAULT_TIMEOUT_MS, DEFAULT_TOKENS, HTTP_METHODS2 as HTTP_METHODS, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, NewsSignalClient, PAYMENT_HEADERS, POLYMARKET_CHAIN_ID, POLYMARKET_CLOB_AUTH_DOMAIN, POLYMARKET_CLOB_DOMAIN, POLYMARKET_ENDPOINTS, POLYMARKET_EXCHANGE_ADDRESSES, PolymarketApiError, PolymarketAuthError, PolymarketExchangeClient, PolymarketInfoClient, SUPPORTED_CURRENCIES, StoreError, WEBSEARCH_TOOL_DEFINITION, WEBSEARCH_TOOL_NAME, X402BrowserClient, X402Client, X402PaymentRequiredError, __hyperliquidInternals, __hyperliquidMarketDataInternals, approveHyperliquidBuilderFee, backtestDecisionRequestSchema, batchModifyHyperliquidOrders, buildBacktestDecisionSeriesInput, buildHmacSignature, buildHyperliquidMarketIdentity, buildHyperliquidProfileAssets, buildHyperliquidSpotUsdPriceMap, buildL1Headers, buildL2Headers, buildPolymarketOrderAmounts, buildSignedOrderPayload, cancelAllHyperliquidOrders, cancelAllPolymarketOrders, cancelHyperliquidOrders, cancelHyperliquidOrdersByCloid, cancelHyperliquidTwapOrder, cancelMarketPolymarketOrders, cancelPolymarketOrder, cancelPolymarketOrders, chains, clampHyperliquidAbs, clampHyperliquidFloat, clampHyperliquidInt, computeHyperliquidMarketIocLimitPrice, createAIClient, createDevServer, createHyperliquidSubAccount, createMcpAdapter, createMonotonicNonceFactory, createPolymarketApiKey, createStdioServer, defineX402Payment, depositToHyperliquidBridge, derivePolymarketApiKey, ensureTextContent, estimateCountBack, evaluateNewsContinuationGate, executeTool, extractHyperliquidDex, extractHyperliquidOrderIds, fetchHyperliquidAllMids, fetchHyperliquidAssetCtxs, fetchHyperliquidBars, fetchHyperliquidClearinghouseState, fetchHyperliquidFrontendOpenOrders, fetchHyperliquidHistoricalOrders, fetchHyperliquidMeta, fetchHyperliquidMetaAndAssetCtxs, fetchHyperliquidOpenOrders, fetchHyperliquidOrderStatus, fetchHyperliquidPerpMarketInfo, fetchHyperliquidPreTransferCheck, fetchHyperliquidSizeDecimals, fetchHyperliquidSpotAccountValue, fetchHyperliquidSpotAssetCtxs, fetchHyperliquidSpotClearinghouseState, fetchHyperliquidSpotMarketInfo, fetchHyperliquidSpotMeta, fetchHyperliquidSpotMetaAndAssetCtxs, fetchHyperliquidSpotTickSize, fetchHyperliquidSpotUsdPriceMap, fetchHyperliquidTickSize, fetchHyperliquidUserFills, fetchHyperliquidUserFillsByTime, fetchHyperliquidUserRateLimit, fetchNewsEventSignal, fetchNewsPropositionSignal, fetchPolymarketMarket, fetchPolymarketMarkets, fetchPolymarketMidpoint, fetchPolymarketOrderbook, fetchPolymarketPrice, fetchPolymarketPriceHistory, flattenMessageContent, formatHyperliquidMarketablePrice, formatHyperliquidOrderSize, formatHyperliquidPrice, formatHyperliquidSize, generateText, getHyperliquidMaxBuilderFee, getModelConfig, getMyPerformance, getMyTools, getRpcUrl, getX402PaymentContext, isHyperliquidSpotSymbol, isStreamingSupported, isToolCallingSupported, listModels, modifyHyperliquidOrder, normalizeHyperliquidBaseSymbol, normalizeHyperliquidDcaEntries, normalizeHyperliquidIndicatorBars, normalizeHyperliquidMetaSymbol, normalizeModelName, normalizeNumberArrayish, normalizeSpotTokenName2 as normalizeSpotTokenName, normalizeStringArrayish, parseHyperliquidJson, parseSpotPairSymbol, parseTimeToSeconds, payX402, payX402WithWallet, placeHyperliquidOrder, placeHyperliquidTwapOrder, placePolymarketOrder, planHyperliquidTrade, postAgentDigest, readHyperliquidAccountValue, readHyperliquidNumber, readHyperliquidPerpPosition, readHyperliquidPerpPositionSize, readHyperliquidSpotAccountValue, readHyperliquidSpotBalance, readHyperliquidSpotBalanceSize, recordHyperliquidBuilderApproval, recordHyperliquidTermsAcceptance, registry, requireX402Payment, reserveHyperliquidRequestWeight, resolutionToSeconds, resolveBacktestAccountValueUsd, resolveBacktestMode, resolveBacktestWindow, resolveConfig2 as resolveConfig, resolveExchangeAddress, resolveHyperliquidAbstractionFromMode, resolveHyperliquidBudgetUsd, resolveHyperliquidCadenceCron, resolveHyperliquidCadenceFromResolution, resolveHyperliquidChain, resolveHyperliquidChainConfig, resolveHyperliquidDcaSymbolEntries, resolveHyperliquidErrorDetail, resolveHyperliquidHourlyInterval, resolveHyperliquidIntervalCron, resolveHyperliquidLeverageMode, resolveHyperliquidMaxPerRunUsd, resolveHyperliquidOrderRef, resolveHyperliquidOrderSymbol, resolveHyperliquidPair, resolveHyperliquidPerpSymbol, resolveHyperliquidProfileChain, resolveHyperliquidRpcEnvVar, resolveHyperliquidScheduleEvery, resolveHyperliquidScheduleUnit, resolveHyperliquidSpotSymbol, resolveHyperliquidStoreNetwork, resolveHyperliquidSymbol, resolveHyperliquidTargetSize, resolveNewsGatewayBase, resolvePolymarketBaseUrl, resolveRuntimePath, resolveSpotMidCandidates, resolveSpotTokenCandidates, resolveToolset, responseToToolResponse, retrieve, roundHyperliquidPriceToTick, scheduleHyperliquidCancel, sendHyperliquidSpot, setHyperliquidAccountAbstractionMode, setHyperliquidDexAbstraction, setHyperliquidPortfolioMargin, store, streamText, tokens, transferHyperliquidSubAccount, updateHyperliquidIsolatedMargin, updateHyperliquidLeverage, wallet, walletToolkit, withX402Payment, withdrawFromHyperliquid };
|
|
7929
6848
|
//# sourceMappingURL=index.js.map
|
|
7930
6849
|
//# sourceMappingURL=index.js.map
|