opentool 0.10.4 → 0.11.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 +7 -3
- package/dist/adapters/hyperliquid/index.js +66 -8
- package/dist/adapters/hyperliquid/index.js.map +1 -1
- package/dist/adapters/news/index.d.ts +176 -0
- package/dist/adapters/news/index.js +173 -0
- package/dist/adapters/news/index.js.map +1 -0
- 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 +26 -4
- package/dist/{validate-DbhJ_r0Z.d.ts → index-9Z3wo28l.d.ts} +2 -25
- package/dist/index.d.ts +10 -377
- package/dist/index.js +280 -1141
- package/dist/index.js.map +1 -1
- package/dist/{payment-orkZA9se.d.ts → payment-BLm1ltur.d.ts} +1 -1
- package/dist/{types-3w880w_t.d.ts → types-BaTmu0gS.d.ts} +3 -2
- package/dist/wallet/browser.d.ts +33 -0
- package/dist/wallet/browser.js +271 -0
- package/dist/wallet/browser.js.map +1 -0
- package/dist/wallet/index.d.ts +2 -2
- package/dist/wallet/index.js +15 -23
- package/dist/wallet/index.js.map +1 -1
- package/dist/x402/index.d.ts +1 -1
- package/package.json +13 -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
|
|
@@ -1299,15 +1296,9 @@ var registry = {
|
|
|
1299
1296
|
chains,
|
|
1300
1297
|
tokens
|
|
1301
1298
|
};
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
if (!/^0x[0-9a-fA-F]{64}$/.test(withPrefix)) {
|
|
1306
|
-
throw new Error("wallet() privateKey must be a 32-byte hex string");
|
|
1307
|
-
}
|
|
1308
|
-
return withPrefix;
|
|
1309
|
-
}
|
|
1310
|
-
function createNonceSource(start = Date.now()) {
|
|
1299
|
+
|
|
1300
|
+
// src/wallet/nonces.ts
|
|
1301
|
+
function createMonotonicNonceSource(start = Date.now()) {
|
|
1311
1302
|
let last = start;
|
|
1312
1303
|
return () => {
|
|
1313
1304
|
const now = Date.now();
|
|
@@ -1319,6 +1310,16 @@ function createNonceSource(start = Date.now()) {
|
|
|
1319
1310
|
return last;
|
|
1320
1311
|
};
|
|
1321
1312
|
}
|
|
1313
|
+
|
|
1314
|
+
// src/wallet/providers/private-key.ts
|
|
1315
|
+
function normalizePrivateKey(raw) {
|
|
1316
|
+
const trimmed = raw.trim();
|
|
1317
|
+
const withPrefix = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
|
|
1318
|
+
if (!/^0x[0-9a-fA-F]{64}$/.test(withPrefix)) {
|
|
1319
|
+
throw new Error("wallet() privateKey must be a 32-byte hex string");
|
|
1320
|
+
}
|
|
1321
|
+
return withPrefix;
|
|
1322
|
+
}
|
|
1322
1323
|
function createPrivateKeyProvider(config) {
|
|
1323
1324
|
const privateKey = normalizePrivateKey(config.privateKey);
|
|
1324
1325
|
const account = privateKeyToAccount(privateKey);
|
|
@@ -1365,19 +1366,7 @@ function createPrivateKeyProvider(config) {
|
|
|
1365
1366
|
sendTransaction,
|
|
1366
1367
|
getNativeBalance,
|
|
1367
1368
|
transfer,
|
|
1368
|
-
nonceSource:
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
function createNonceSource2(start = Date.now()) {
|
|
1372
|
-
let last = start;
|
|
1373
|
-
return () => {
|
|
1374
|
-
const now = Date.now();
|
|
1375
|
-
if (now > last) {
|
|
1376
|
-
last = now;
|
|
1377
|
-
} else {
|
|
1378
|
-
last += 1;
|
|
1379
|
-
}
|
|
1380
|
-
return last;
|
|
1369
|
+
nonceSource: createMonotonicNonceSource()
|
|
1381
1370
|
};
|
|
1382
1371
|
}
|
|
1383
1372
|
async function createTurnkeyProvider(config) {
|
|
@@ -1436,7 +1425,7 @@ async function createTurnkeyProvider(config) {
|
|
|
1436
1425
|
sendTransaction,
|
|
1437
1426
|
getNativeBalance,
|
|
1438
1427
|
transfer,
|
|
1439
|
-
nonceSource:
|
|
1428
|
+
nonceSource: createMonotonicNonceSource()
|
|
1440
1429
|
};
|
|
1441
1430
|
}
|
|
1442
1431
|
|
|
@@ -1732,8 +1721,8 @@ async function store(input, options) {
|
|
|
1732
1721
|
);
|
|
1733
1722
|
}
|
|
1734
1723
|
const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
|
|
1735
|
-
const
|
|
1736
|
-
const url = `${baseUrl}${
|
|
1724
|
+
const path2 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
|
|
1725
|
+
const url = `${baseUrl}${path2}`;
|
|
1737
1726
|
let response;
|
|
1738
1727
|
try {
|
|
1739
1728
|
response = await fetchFn(url, {
|
|
@@ -1773,8 +1762,8 @@ async function store(input, options) {
|
|
|
1773
1762
|
async function retrieve(params, options) {
|
|
1774
1763
|
const { baseUrl, apiKey, fetchFn } = resolveConfig(options);
|
|
1775
1764
|
const mode = params?.mode ?? "live";
|
|
1776
|
-
const
|
|
1777
|
-
const url = new URL(`${baseUrl}${
|
|
1765
|
+
const path2 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
|
|
1766
|
+
const url = new URL(`${baseUrl}${path2}`);
|
|
1778
1767
|
if (params?.source) url.searchParams.set("source", params.source);
|
|
1779
1768
|
if (params?.walletAddress) url.searchParams.set("walletAddress", params.walletAddress);
|
|
1780
1769
|
if (params?.symbol) url.searchParams.set("symbol", params.symbol);
|
|
@@ -2703,6 +2692,16 @@ async function fetchHyperliquidSpotClearinghouseState(params) {
|
|
|
2703
2692
|
}
|
|
2704
2693
|
|
|
2705
2694
|
// src/adapters/hyperliquid/exchange.ts
|
|
2695
|
+
function resolveRequiredExchangeNonce(options) {
|
|
2696
|
+
if (typeof options.nonce === "number") {
|
|
2697
|
+
return options.nonce;
|
|
2698
|
+
}
|
|
2699
|
+
const resolved = options.walletNonceProvider?.() ?? options.wallet.nonceSource?.() ?? options.nonceSource?.();
|
|
2700
|
+
if (resolved === void 0) {
|
|
2701
|
+
throw new Error(`${options.action} requires an explicit nonce or wallet nonce source.`);
|
|
2702
|
+
}
|
|
2703
|
+
return resolved;
|
|
2704
|
+
}
|
|
2706
2705
|
var HyperliquidExchangeClient = class {
|
|
2707
2706
|
constructor(args) {
|
|
2708
2707
|
this.wallet = args.wallet;
|
|
@@ -2873,7 +2872,13 @@ async function setHyperliquidPortfolioMargin(options) {
|
|
|
2873
2872
|
if (!options.wallet?.account || !options.wallet.walletClient) {
|
|
2874
2873
|
throw new Error("Wallet with signing capability is required for portfolio margin.");
|
|
2875
2874
|
}
|
|
2876
|
-
const nonce =
|
|
2875
|
+
const nonce = resolveRequiredExchangeNonce({
|
|
2876
|
+
nonce: options.nonce,
|
|
2877
|
+
nonceSource: options.nonceSource,
|
|
2878
|
+
walletNonceProvider: options.walletNonceProvider,
|
|
2879
|
+
wallet: options.wallet,
|
|
2880
|
+
action: "Hyperliquid portfolio margin"
|
|
2881
|
+
});
|
|
2877
2882
|
const signatureChainId = getSignatureChainId(env);
|
|
2878
2883
|
const hyperliquidChain = HL_CHAIN_LABEL[env];
|
|
2879
2884
|
const user = normalizeAddress(options.user ?? options.wallet.address);
|
|
@@ -2907,7 +2912,13 @@ async function setHyperliquidDexAbstraction(options) {
|
|
|
2907
2912
|
if (!options.wallet?.account || !options.wallet.walletClient) {
|
|
2908
2913
|
throw new Error("Wallet with signing capability is required for dex abstraction.");
|
|
2909
2914
|
}
|
|
2910
|
-
const nonce =
|
|
2915
|
+
const nonce = resolveRequiredExchangeNonce({
|
|
2916
|
+
nonce: options.nonce,
|
|
2917
|
+
nonceSource: options.nonceSource,
|
|
2918
|
+
walletNonceProvider: options.walletNonceProvider,
|
|
2919
|
+
wallet: options.wallet,
|
|
2920
|
+
action: "Hyperliquid dex abstraction"
|
|
2921
|
+
});
|
|
2911
2922
|
const signatureChainId = getSignatureChainId(env);
|
|
2912
2923
|
const hyperliquidChain = HL_CHAIN_LABEL[env];
|
|
2913
2924
|
const user = normalizeAddress(options.user ?? options.wallet.address);
|
|
@@ -2941,7 +2952,13 @@ async function setHyperliquidAccountAbstractionMode(options) {
|
|
|
2941
2952
|
if (!options.wallet?.account || !options.wallet.walletClient) {
|
|
2942
2953
|
throw new Error("Wallet with signing capability is required for account abstraction mode.");
|
|
2943
2954
|
}
|
|
2944
|
-
const nonce =
|
|
2955
|
+
const nonce = resolveRequiredExchangeNonce({
|
|
2956
|
+
nonce: options.nonce,
|
|
2957
|
+
nonceSource: options.nonceSource,
|
|
2958
|
+
walletNonceProvider: options.walletNonceProvider,
|
|
2959
|
+
wallet: options.wallet,
|
|
2960
|
+
action: "Hyperliquid account abstraction mode"
|
|
2961
|
+
});
|
|
2945
2962
|
const signatureChainId = getSignatureChainId(env);
|
|
2946
2963
|
const hyperliquidChain = HL_CHAIN_LABEL[env];
|
|
2947
2964
|
const user = normalizeAddress(options.user ?? options.wallet.address);
|
|
@@ -3141,7 +3158,12 @@ async function sendHyperliquidSpot(options) {
|
|
|
3141
3158
|
assertPositiveDecimal(options.amount, "amount");
|
|
3142
3159
|
const signatureChainId = getSignatureChainId(env);
|
|
3143
3160
|
const hyperliquidChain = HL_CHAIN_LABEL[env];
|
|
3144
|
-
const nonce =
|
|
3161
|
+
const nonce = resolveRequiredExchangeNonce({
|
|
3162
|
+
nonce: options.nonce,
|
|
3163
|
+
nonceSource: options.nonceSource,
|
|
3164
|
+
wallet: options.wallet,
|
|
3165
|
+
action: "Hyperliquid spot send"
|
|
3166
|
+
});
|
|
3145
3167
|
const time = BigInt(nonce);
|
|
3146
3168
|
const signature = await signSpotSend({
|
|
3147
3169
|
wallet: options.wallet,
|
|
@@ -4515,6 +4537,16 @@ function resolveHyperliquidCadenceFromResolution(resolution) {
|
|
|
4515
4537
|
}
|
|
4516
4538
|
|
|
4517
4539
|
// src/adapters/hyperliquid/index.ts
|
|
4540
|
+
function resolveRequiredNonce(params) {
|
|
4541
|
+
if (typeof params.nonce === "number") {
|
|
4542
|
+
return params.nonce;
|
|
4543
|
+
}
|
|
4544
|
+
const resolved = params.nonceSource?.() ?? params.wallet?.nonceSource?.();
|
|
4545
|
+
if (resolved === void 0) {
|
|
4546
|
+
throw new Error(`${params.action} requires an explicit nonce or wallet nonce source.`);
|
|
4547
|
+
}
|
|
4548
|
+
return resolved;
|
|
4549
|
+
}
|
|
4518
4550
|
function assertPositiveDecimalInput(value, label) {
|
|
4519
4551
|
if (typeof value === "number") {
|
|
4520
4552
|
if (!Number.isFinite(value) || value <= 0) {
|
|
@@ -4623,7 +4655,12 @@ async function placeHyperliquidOrder(options) {
|
|
|
4623
4655
|
f: effectiveBuilder.fee
|
|
4624
4656
|
};
|
|
4625
4657
|
}
|
|
4626
|
-
const effectiveNonce =
|
|
4658
|
+
const effectiveNonce = resolveRequiredNonce({
|
|
4659
|
+
nonce,
|
|
4660
|
+
nonceSource: options.nonceSource,
|
|
4661
|
+
wallet: wallet2,
|
|
4662
|
+
action: "Hyperliquid order submission"
|
|
4663
|
+
});
|
|
4627
4664
|
const signature = await signL1Action({
|
|
4628
4665
|
wallet: wallet2,
|
|
4629
4666
|
action,
|
|
@@ -4739,8 +4776,13 @@ async function withdrawFromHyperliquid(options) {
|
|
|
4739
4776
|
chainId: Number.parseInt(signatureChainId, 16),
|
|
4740
4777
|
verifyingContract: ZERO_ADDRESS
|
|
4741
4778
|
};
|
|
4742
|
-
const
|
|
4743
|
-
|
|
4779
|
+
const nonce = resolveRequiredNonce({
|
|
4780
|
+
nonce: options.nonce,
|
|
4781
|
+
nonceSource: options.nonceSource,
|
|
4782
|
+
wallet: wallet2,
|
|
4783
|
+
action: "Hyperliquid withdraw"
|
|
4784
|
+
});
|
|
4785
|
+
const time = BigInt(nonce);
|
|
4744
4786
|
const normalizedDestination = normalizeAddress(destination);
|
|
4745
4787
|
const message = {
|
|
4746
4788
|
hyperliquidChain,
|
|
@@ -4820,7 +4862,12 @@ async function approveHyperliquidBuilderFee(options) {
|
|
|
4820
4862
|
const inferredEnvironment = environment ?? "mainnet";
|
|
4821
4863
|
const resolvedBaseUrl = API_BASES[inferredEnvironment];
|
|
4822
4864
|
const maxFeeRate = formattedPercent;
|
|
4823
|
-
const effectiveNonce =
|
|
4865
|
+
const effectiveNonce = resolveRequiredNonce({
|
|
4866
|
+
nonce,
|
|
4867
|
+
nonceSource: options.nonceSource,
|
|
4868
|
+
wallet: wallet2,
|
|
4869
|
+
action: "Hyperliquid builder approval"
|
|
4870
|
+
});
|
|
4824
4871
|
const signatureNonce = BigInt(effectiveNonce);
|
|
4825
4872
|
const signatureChainHex = signatureChainId ?? getSignatureChainId(inferredEnvironment);
|
|
4826
4873
|
const approvalSignature = await signApproveBuilderFee({
|
|
@@ -5063,19 +5110,19 @@ function parseOptionalDate(value) {
|
|
|
5063
5110
|
return null;
|
|
5064
5111
|
}
|
|
5065
5112
|
function buildHmacSignature(args) {
|
|
5066
|
-
const
|
|
5113
|
+
const timestamp = args.timestamp.toString();
|
|
5067
5114
|
const method = args.method.toUpperCase();
|
|
5068
|
-
const
|
|
5115
|
+
const path2 = args.path;
|
|
5069
5116
|
const body = args.body == null ? "" : typeof args.body === "string" ? args.body : JSON.stringify(args.body);
|
|
5070
|
-
const payload = `${
|
|
5117
|
+
const payload = `${timestamp}${method}${path2}${body}`;
|
|
5071
5118
|
const key = Buffer.from(args.secret, "base64");
|
|
5072
5119
|
return createHmac("sha256", key).update(payload).digest("hex");
|
|
5073
5120
|
}
|
|
5074
5121
|
function buildL2Headers(args) {
|
|
5075
|
-
const
|
|
5122
|
+
const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
5076
5123
|
const signature = buildHmacSignature({
|
|
5077
5124
|
secret: args.credentials.secret,
|
|
5078
|
-
timestamp
|
|
5125
|
+
timestamp,
|
|
5079
5126
|
method: args.method,
|
|
5080
5127
|
path: args.path,
|
|
5081
5128
|
body: args.body ?? null
|
|
@@ -5084,13 +5131,13 @@ function buildL2Headers(args) {
|
|
|
5084
5131
|
POLY_ADDRESS: args.address,
|
|
5085
5132
|
POLY_API_KEY: args.credentials.apiKey,
|
|
5086
5133
|
POLY_PASSPHRASE: args.credentials.passphrase,
|
|
5087
|
-
POLY_TIMESTAMP:
|
|
5134
|
+
POLY_TIMESTAMP: timestamp.toString(),
|
|
5088
5135
|
POLY_SIGNATURE: signature
|
|
5089
5136
|
};
|
|
5090
5137
|
}
|
|
5091
5138
|
async function buildL1Headers(args) {
|
|
5092
5139
|
assertWalletSigner(args.wallet);
|
|
5093
|
-
const
|
|
5140
|
+
const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
|
|
5094
5141
|
const nonce = args.nonce ?? Date.now();
|
|
5095
5142
|
const chainId = POLYMARKET_CHAIN_ID[args.environment ?? "mainnet"];
|
|
5096
5143
|
const address = args.wallet.address;
|
|
@@ -5112,14 +5159,14 @@ async function buildL1Headers(args) {
|
|
|
5112
5159
|
primaryType: "ClobAuth",
|
|
5113
5160
|
message: {
|
|
5114
5161
|
address,
|
|
5115
|
-
timestamp:
|
|
5162
|
+
timestamp: timestamp.toString(),
|
|
5116
5163
|
nonce: BigInt(nonce),
|
|
5117
5164
|
message
|
|
5118
5165
|
}
|
|
5119
5166
|
});
|
|
5120
5167
|
return {
|
|
5121
5168
|
POLY_ADDRESS: address,
|
|
5122
|
-
POLY_TIMESTAMP:
|
|
5169
|
+
POLY_TIMESTAMP: timestamp.toString(),
|
|
5123
5170
|
POLY_NONCE: nonce.toString(),
|
|
5124
5171
|
POLY_SIGNATURE: signature
|
|
5125
5172
|
};
|
|
@@ -5761,6 +5808,176 @@ async function fetchPolymarketPriceHistory(params) {
|
|
|
5761
5808
|
})).filter((point) => Number.isFinite(point.t) && Number.isFinite(point.p));
|
|
5762
5809
|
}
|
|
5763
5810
|
|
|
5811
|
+
// src/adapters/news/signals.ts
|
|
5812
|
+
var DEFAULT_OPENPOND_GATEWAY_URL2 = "https://gateway.openpond.dev";
|
|
5813
|
+
function resolveFetchImplementation(override) {
|
|
5814
|
+
const fetchImplementation = override ?? globalThis.fetch;
|
|
5815
|
+
if (!fetchImplementation) {
|
|
5816
|
+
throw new Error(
|
|
5817
|
+
"No fetch implementation available. Provide one via NewsSignalClientConfig.fetchImplementation."
|
|
5818
|
+
);
|
|
5819
|
+
}
|
|
5820
|
+
return fetchImplementation;
|
|
5821
|
+
}
|
|
5822
|
+
function resolveNewsGatewayBase(override) {
|
|
5823
|
+
const value = override ?? process.env.OPENPOND_GATEWAY_URL ?? DEFAULT_OPENPOND_GATEWAY_URL2;
|
|
5824
|
+
if (typeof value !== "string") {
|
|
5825
|
+
throw new Error("OPENPOND_GATEWAY_URL is required.");
|
|
5826
|
+
}
|
|
5827
|
+
const trimmed = value.trim();
|
|
5828
|
+
if (!trimmed) {
|
|
5829
|
+
throw new Error("OPENPOND_GATEWAY_URL is required.");
|
|
5830
|
+
}
|
|
5831
|
+
return trimmed.replace(/\/$/, "");
|
|
5832
|
+
}
|
|
5833
|
+
function normalizeAsOf(value) {
|
|
5834
|
+
if (value == null) return void 0;
|
|
5835
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
5836
|
+
if (Number.isNaN(date.getTime())) {
|
|
5837
|
+
throw new Error("asOf must be a valid ISO-8601 datetime or Date.");
|
|
5838
|
+
}
|
|
5839
|
+
return date.toISOString();
|
|
5840
|
+
}
|
|
5841
|
+
async function postGatewayJson(params) {
|
|
5842
|
+
const gatewayBase = resolveNewsGatewayBase(params.gatewayBase);
|
|
5843
|
+
const fetchImplementation = resolveFetchImplementation(params.fetchImplementation);
|
|
5844
|
+
const response = await fetchImplementation(`${gatewayBase}${params.path}`, {
|
|
5845
|
+
method: "POST",
|
|
5846
|
+
headers: { "content-type": "application/json" },
|
|
5847
|
+
body: JSON.stringify(params.body)
|
|
5848
|
+
});
|
|
5849
|
+
const text = await response.text().catch(() => "");
|
|
5850
|
+
let payload = null;
|
|
5851
|
+
try {
|
|
5852
|
+
payload = text ? JSON.parse(text) : null;
|
|
5853
|
+
} catch {
|
|
5854
|
+
payload = text;
|
|
5855
|
+
}
|
|
5856
|
+
if (!response.ok) {
|
|
5857
|
+
throw new Error(
|
|
5858
|
+
`Gateway request failed (${response.status}) for ${params.path}: ${typeof payload === "string" && payload ? payload : "no_body"}`
|
|
5859
|
+
);
|
|
5860
|
+
}
|
|
5861
|
+
return payload;
|
|
5862
|
+
}
|
|
5863
|
+
async function fetchNewsEventSignal(params) {
|
|
5864
|
+
if (!params.query?.trim() && !params.eventKey?.trim()) {
|
|
5865
|
+
throw new Error("query or eventKey is required.");
|
|
5866
|
+
}
|
|
5867
|
+
return postGatewayJson({
|
|
5868
|
+
path: "/v1/news/event-signal",
|
|
5869
|
+
gatewayBase: params.gatewayBase,
|
|
5870
|
+
fetchImplementation: params.fetchImplementation,
|
|
5871
|
+
body: {
|
|
5872
|
+
...params.query?.trim() ? { query: params.query.trim() } : {},
|
|
5873
|
+
...params.eventKey?.trim() ? { eventKey: params.eventKey.trim() } : {},
|
|
5874
|
+
...normalizeAsOf(params.asOf) ? { asOf: normalizeAsOf(params.asOf) } : {},
|
|
5875
|
+
...typeof params.includePredictionMarkets === "boolean" ? { includePredictionMarkets: params.includePredictionMarkets } : {},
|
|
5876
|
+
...typeof params.ingestOnRequest === "boolean" ? { ingestOnRequest: params.ingestOnRequest } : {},
|
|
5877
|
+
...typeof params.maxAgeHours === "number" ? { maxAgeHours: params.maxAgeHours } : {},
|
|
5878
|
+
policy: {
|
|
5879
|
+
...typeof params.minConfidence === "number" ? { minConfidence: params.minConfidence } : {},
|
|
5880
|
+
...typeof params.minIndependentSources === "number" ? { minIndependentSources: params.minIndependentSources } : {},
|
|
5881
|
+
...typeof params.minTierASources === "number" ? { minTierASources: params.minTierASources } : {}
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
});
|
|
5885
|
+
}
|
|
5886
|
+
async function fetchNewsPropositionSignal(params) {
|
|
5887
|
+
const question = params.question.trim();
|
|
5888
|
+
if (!question) {
|
|
5889
|
+
throw new Error("question is required.");
|
|
5890
|
+
}
|
|
5891
|
+
return postGatewayJson({
|
|
5892
|
+
path: "/v1/news/event-proposition-signal",
|
|
5893
|
+
gatewayBase: params.gatewayBase,
|
|
5894
|
+
fetchImplementation: params.fetchImplementation,
|
|
5895
|
+
body: {
|
|
5896
|
+
question,
|
|
5897
|
+
...params.query?.trim() ? { query: params.query.trim() } : {},
|
|
5898
|
+
...params.eventKey?.trim() ? { eventKey: params.eventKey.trim() } : {},
|
|
5899
|
+
...params.propositionType?.trim() ? { propositionType: params.propositionType.trim() } : {},
|
|
5900
|
+
...normalizeAsOf(params.asOf) ? { asOf: normalizeAsOf(params.asOf) } : {},
|
|
5901
|
+
...typeof params.includePredictionMarkets === "boolean" ? { includePredictionMarkets: params.includePredictionMarkets } : {},
|
|
5902
|
+
...typeof params.ingestOnRequest === "boolean" ? { ingestOnRequest: params.ingestOnRequest } : {},
|
|
5903
|
+
...typeof params.maxAgeHours === "number" ? { maxAgeHours: params.maxAgeHours } : {},
|
|
5904
|
+
...typeof params.candidateLimit === "number" ? { candidateLimit: params.candidateLimit } : {}
|
|
5905
|
+
}
|
|
5906
|
+
});
|
|
5907
|
+
}
|
|
5908
|
+
function evaluateNewsContinuationGate(signal, gate) {
|
|
5909
|
+
const blockedAction = gate.onBlocked ?? "skip";
|
|
5910
|
+
const blockingFactors = [];
|
|
5911
|
+
if (gate.mode === "event") {
|
|
5912
|
+
const eventSignal = signal;
|
|
5913
|
+
if (gate.requireTriggerPassed !== false && !eventSignal.triggerPassed) {
|
|
5914
|
+
blockingFactors.push("trigger_not_passed");
|
|
5915
|
+
}
|
|
5916
|
+
if (typeof gate.minConfidence === "number" && eventSignal.eventConfidence < gate.minConfidence) {
|
|
5917
|
+
blockingFactors.push("confidence_below_threshold");
|
|
5918
|
+
}
|
|
5919
|
+
if (typeof gate.maxDataAgeMs === "number" && typeof eventSignal.dataAgeMs === "number" && eventSignal.dataAgeMs > gate.maxDataAgeMs) {
|
|
5920
|
+
blockingFactors.push("signal_too_stale");
|
|
5921
|
+
}
|
|
5922
|
+
if (typeof gate.minIndependentSources === "number" && eventSignal.supportingSourceCount < gate.minIndependentSources) {
|
|
5923
|
+
blockingFactors.push("insufficient_supporting_sources");
|
|
5924
|
+
}
|
|
5925
|
+
if (typeof gate.minTierASources === "number" && eventSignal.tierASourceCount < gate.minTierASources) {
|
|
5926
|
+
blockingFactors.push("insufficient_tier_a_sources");
|
|
5927
|
+
}
|
|
5928
|
+
} else {
|
|
5929
|
+
const propositionSignal = signal;
|
|
5930
|
+
if (gate.requireResolvedEvent !== false && propositionSignal.propositionStatus === "no_matching_event") {
|
|
5931
|
+
blockingFactors.push("no_matching_event");
|
|
5932
|
+
}
|
|
5933
|
+
if (gate.expectedAnswer && propositionSignal.answer !== gate.expectedAnswer) {
|
|
5934
|
+
blockingFactors.push("unexpected_answer");
|
|
5935
|
+
}
|
|
5936
|
+
if (typeof gate.minConfidence === "number" && propositionSignal.propositionConfidence < gate.minConfidence) {
|
|
5937
|
+
blockingFactors.push("confidence_below_threshold");
|
|
5938
|
+
}
|
|
5939
|
+
if (typeof gate.maxDataAgeMs === "number" && typeof propositionSignal.dataAgeMs === "number" && propositionSignal.dataAgeMs > gate.maxDataAgeMs) {
|
|
5940
|
+
blockingFactors.push("signal_too_stale");
|
|
5941
|
+
}
|
|
5942
|
+
}
|
|
5943
|
+
if (blockingFactors.length === 0) {
|
|
5944
|
+
return {
|
|
5945
|
+
allowed: true,
|
|
5946
|
+
action: "continue",
|
|
5947
|
+
reason: "All continuation gate checks passed.",
|
|
5948
|
+
matchedRule: gate.mode,
|
|
5949
|
+
blockingFactors: []
|
|
5950
|
+
};
|
|
5951
|
+
}
|
|
5952
|
+
return {
|
|
5953
|
+
allowed: false,
|
|
5954
|
+
action: blockedAction,
|
|
5955
|
+
reason: `Blocked by continuation gate: ${blockingFactors.join(", ")}.`,
|
|
5956
|
+
matchedRule: gate.mode,
|
|
5957
|
+
blockingFactors
|
|
5958
|
+
};
|
|
5959
|
+
}
|
|
5960
|
+
var NewsSignalClient = class {
|
|
5961
|
+
constructor(config = {}) {
|
|
5962
|
+
this.gatewayBase = resolveNewsGatewayBase(config.gatewayBase);
|
|
5963
|
+
this.fetchImplementation = resolveFetchImplementation(config.fetchImplementation);
|
|
5964
|
+
}
|
|
5965
|
+
eventSignal(params) {
|
|
5966
|
+
return fetchNewsEventSignal({
|
|
5967
|
+
...params,
|
|
5968
|
+
gatewayBase: this.gatewayBase,
|
|
5969
|
+
fetchImplementation: this.fetchImplementation
|
|
5970
|
+
});
|
|
5971
|
+
}
|
|
5972
|
+
propositionSignal(params) {
|
|
5973
|
+
return fetchNewsPropositionSignal({
|
|
5974
|
+
...params,
|
|
5975
|
+
gatewayBase: this.gatewayBase,
|
|
5976
|
+
fetchImplementation: this.fetchImplementation
|
|
5977
|
+
});
|
|
5978
|
+
}
|
|
5979
|
+
};
|
|
5980
|
+
|
|
5764
5981
|
// src/ai/errors.ts
|
|
5765
5982
|
var AIError = class extends Error {
|
|
5766
5983
|
constructor(message, options) {
|
|
@@ -6190,8 +6407,8 @@ async function streamText(options, clientConfig = {}) {
|
|
|
6190
6407
|
const handlers = options.handlers ?? {};
|
|
6191
6408
|
let finishedResolve;
|
|
6192
6409
|
let finishedReject;
|
|
6193
|
-
const finished = new Promise((
|
|
6194
|
-
finishedResolve =
|
|
6410
|
+
const finished = new Promise((resolve2, reject) => {
|
|
6411
|
+
finishedResolve = resolve2;
|
|
6195
6412
|
finishedReject = reject;
|
|
6196
6413
|
});
|
|
6197
6414
|
let settled = false;
|
|
@@ -6420,9 +6637,9 @@ function assignIfDefined(target, key, value) {
|
|
|
6420
6637
|
target[key] = value;
|
|
6421
6638
|
}
|
|
6422
6639
|
}
|
|
6423
|
-
function buildUrl(baseUrl,
|
|
6640
|
+
function buildUrl(baseUrl, path2) {
|
|
6424
6641
|
const sanitizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
6425
|
-
return `${sanitizedBase}${
|
|
6642
|
+
return `${sanitizedBase}${path2}`;
|
|
6426
6643
|
}
|
|
6427
6644
|
function createAbortBundle(upstreamSignal, timeoutMs) {
|
|
6428
6645
|
const controller = new AbortController();
|
|
@@ -6626,1085 +6843,7 @@ function buildBacktestDecisionSeriesInput(request) {
|
|
|
6626
6843
|
...accountValueUsd != null ? { accountValueUsd } : {}
|
|
6627
6844
|
};
|
|
6628
6845
|
}
|
|
6629
|
-
var METADATA_SPEC_VERSION = "1.1.0";
|
|
6630
|
-
var McpAnnotationsSchema = z.object({
|
|
6631
|
-
title: z.string().optional(),
|
|
6632
|
-
readOnlyHint: z.boolean().optional(),
|
|
6633
|
-
destructiveHint: z.boolean().optional(),
|
|
6634
|
-
idempotentHint: z.boolean().optional(),
|
|
6635
|
-
openWorldHint: z.boolean().optional(),
|
|
6636
|
-
requiresPayment: z.boolean().optional()
|
|
6637
|
-
}).strict();
|
|
6638
|
-
var X402PaymentSchema = z.object({
|
|
6639
|
-
definition: z.object({
|
|
6640
|
-
amount: z.string(),
|
|
6641
|
-
currency: z.object({
|
|
6642
|
-
code: z.string(),
|
|
6643
|
-
symbol: z.string(),
|
|
6644
|
-
decimals: z.number()
|
|
6645
|
-
}),
|
|
6646
|
-
asset: z.object({
|
|
6647
|
-
symbol: z.string(),
|
|
6648
|
-
network: z.string(),
|
|
6649
|
-
address: z.string(),
|
|
6650
|
-
decimals: z.number()
|
|
6651
|
-
}),
|
|
6652
|
-
payTo: z.string(),
|
|
6653
|
-
resource: z.string().optional(),
|
|
6654
|
-
description: z.string().optional(),
|
|
6655
|
-
scheme: z.string(),
|
|
6656
|
-
network: z.string(),
|
|
6657
|
-
facilitator: z.object({
|
|
6658
|
-
url: z.string(),
|
|
6659
|
-
verifyPath: z.string().optional(),
|
|
6660
|
-
settlePath: z.string().optional(),
|
|
6661
|
-
apiKeyHeader: z.string().optional()
|
|
6662
|
-
}),
|
|
6663
|
-
metadata: z.record(z.string(), z.unknown()).optional()
|
|
6664
|
-
}),
|
|
6665
|
-
metadata: z.record(z.string(), z.unknown()).optional()
|
|
6666
|
-
}).passthrough();
|
|
6667
|
-
var PaymentConfigSchema = z.union([X402PaymentSchema, z.record(z.string(), z.unknown())]);
|
|
6668
|
-
var DiscoveryMetadataSchema = z.object({
|
|
6669
|
-
keywords: z.array(z.string()).optional(),
|
|
6670
|
-
category: z.string().optional(),
|
|
6671
|
-
useCases: z.array(z.string()).optional(),
|
|
6672
|
-
capabilities: z.array(z.string()).optional(),
|
|
6673
|
-
requirements: z.record(z.string(), z.any()).optional(),
|
|
6674
|
-
compatibility: z.record(z.string(), z.any()).optional(),
|
|
6675
|
-
documentation: z.union([z.string(), z.array(z.string())]).optional()
|
|
6676
|
-
}).catchall(z.any());
|
|
6677
|
-
var ToolCategorySchema = z.enum(["strategy", "tracker", "orchestrator"]);
|
|
6678
|
-
var ToolMetadataOverridesSchema = z.object({
|
|
6679
|
-
name: z.string().optional(),
|
|
6680
|
-
description: z.string().optional(),
|
|
6681
|
-
annotations: McpAnnotationsSchema.optional(),
|
|
6682
|
-
payment: PaymentConfigSchema.optional(),
|
|
6683
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6684
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6685
|
-
}).catchall(z.any());
|
|
6686
|
-
var ToolSchema = z.object({
|
|
6687
|
-
name: z.string(),
|
|
6688
|
-
description: z.string(),
|
|
6689
|
-
inputSchema: z.any(),
|
|
6690
|
-
annotations: McpAnnotationsSchema.optional(),
|
|
6691
|
-
payment: PaymentConfigSchema.optional(),
|
|
6692
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6693
|
-
chains: z.array(z.union([z.string(), z.number()])).optional(),
|
|
6694
|
-
notifyEmail: z.boolean().optional(),
|
|
6695
|
-
category: ToolCategorySchema.optional()
|
|
6696
|
-
}).strict();
|
|
6697
|
-
var MetadataSchema = z.object({
|
|
6698
|
-
metadataSpecVersion: z.string().optional(),
|
|
6699
|
-
name: z.string().optional(),
|
|
6700
|
-
displayName: z.string().optional(),
|
|
6701
|
-
version: z.string().optional(),
|
|
6702
|
-
description: z.string().optional(),
|
|
6703
|
-
author: z.string().optional(),
|
|
6704
|
-
repository: z.string().optional(),
|
|
6705
|
-
website: z.string().optional(),
|
|
6706
|
-
category: z.string().optional(),
|
|
6707
|
-
categories: z.array(z.string()).optional(),
|
|
6708
|
-
termsOfService: z.string().optional(),
|
|
6709
|
-
mcpUrl: z.string().optional(),
|
|
6710
|
-
payment: PaymentConfigSchema.optional(),
|
|
6711
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6712
|
-
promptExamples: z.array(z.string()).optional(),
|
|
6713
|
-
iconPath: z.string().optional(),
|
|
6714
|
-
videoPath: z.string().optional(),
|
|
6715
|
-
image: z.string().optional(),
|
|
6716
|
-
animation_url: z.string().optional(),
|
|
6717
|
-
keywords: z.array(z.string()).optional(),
|
|
6718
|
-
useCases: z.array(z.string()).optional(),
|
|
6719
|
-
capabilities: z.array(z.string()).optional(),
|
|
6720
|
-
requirements: z.record(z.string(), z.any()).optional(),
|
|
6721
|
-
compatibility: z.record(z.string(), z.any()).optional(),
|
|
6722
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6723
|
-
}).catchall(z.any());
|
|
6724
|
-
var BuildMetadataSchema = z.object({
|
|
6725
|
-
metadataSpecVersion: z.string().default(METADATA_SPEC_VERSION),
|
|
6726
|
-
name: z.string(),
|
|
6727
|
-
displayName: z.string(),
|
|
6728
|
-
version: z.string(),
|
|
6729
|
-
description: z.string().optional(),
|
|
6730
|
-
author: z.string().optional(),
|
|
6731
|
-
repository: z.string().optional(),
|
|
6732
|
-
website: z.string().optional(),
|
|
6733
|
-
category: z.string(),
|
|
6734
|
-
termsOfService: z.string().optional(),
|
|
6735
|
-
mcpUrl: z.string().optional(),
|
|
6736
|
-
payment: PaymentConfigSchema.optional(),
|
|
6737
|
-
tools: z.array(ToolSchema).min(1),
|
|
6738
|
-
discovery: DiscoveryMetadataSchema.optional(),
|
|
6739
|
-
promptExamples: z.array(z.string()).optional(),
|
|
6740
|
-
iconPath: z.string().optional(),
|
|
6741
|
-
videoPath: z.string().optional(),
|
|
6742
|
-
image: z.string().optional(),
|
|
6743
|
-
animation_url: z.string().optional(),
|
|
6744
|
-
chains: z.array(z.union([z.string(), z.number()])).optional()
|
|
6745
|
-
}).strict();
|
|
6746
|
-
function resolveTsconfig(projectRoot) {
|
|
6747
|
-
const candidate = path5.join(projectRoot, "tsconfig.json");
|
|
6748
|
-
if (fs4.existsSync(candidate)) {
|
|
6749
|
-
return candidate;
|
|
6750
|
-
}
|
|
6751
|
-
return void 0;
|
|
6752
|
-
}
|
|
6753
|
-
async function transpileWithEsbuild(options) {
|
|
6754
|
-
if (options.entryPoints.length === 0) {
|
|
6755
|
-
throw new Error("No entry points provided for esbuild transpilation");
|
|
6756
|
-
}
|
|
6757
|
-
const projectRoot = options.projectRoot;
|
|
6758
|
-
const tempBase = options.outDir ?? fs4.mkdtempSync(path5.join(tmpdir(), "opentool-"));
|
|
6759
|
-
if (!fs4.existsSync(tempBase)) {
|
|
6760
|
-
fs4.mkdirSync(tempBase, { recursive: true });
|
|
6761
|
-
}
|
|
6762
|
-
const tsconfig = resolveTsconfig(projectRoot);
|
|
6763
|
-
const buildOptions = {
|
|
6764
|
-
entryPoints: options.entryPoints,
|
|
6765
|
-
outdir: tempBase,
|
|
6766
|
-
bundle: options.bundle ?? false,
|
|
6767
|
-
format: options.format,
|
|
6768
|
-
platform: "node",
|
|
6769
|
-
target: "node20",
|
|
6770
|
-
logLevel: options.logLevel ?? "warning",
|
|
6771
|
-
sourcesContent: false,
|
|
6772
|
-
sourcemap: false,
|
|
6773
|
-
loader: {
|
|
6774
|
-
".ts": "ts",
|
|
6775
|
-
".tsx": "tsx",
|
|
6776
|
-
".cts": "ts",
|
|
6777
|
-
".mts": "ts",
|
|
6778
|
-
".js": "js",
|
|
6779
|
-
".jsx": "jsx",
|
|
6780
|
-
".mjs": "js",
|
|
6781
|
-
".cjs": "js",
|
|
6782
|
-
".json": "json"
|
|
6783
|
-
},
|
|
6784
|
-
metafile: options.metafile ?? false,
|
|
6785
|
-
allowOverwrite: true,
|
|
6786
|
-
absWorkingDir: projectRoot
|
|
6787
|
-
};
|
|
6788
|
-
if (options.external && options.external.length > 0) {
|
|
6789
|
-
buildOptions.external = options.external;
|
|
6790
|
-
}
|
|
6791
|
-
if (options.nodePaths && options.nodePaths.length > 0) {
|
|
6792
|
-
buildOptions.nodePaths = options.nodePaths;
|
|
6793
|
-
}
|
|
6794
|
-
if (options.outBase) {
|
|
6795
|
-
buildOptions.outbase = options.outBase;
|
|
6796
|
-
}
|
|
6797
|
-
if (!buildOptions.bundle) {
|
|
6798
|
-
buildOptions.packages = "external";
|
|
6799
|
-
}
|
|
6800
|
-
if (tsconfig) {
|
|
6801
|
-
buildOptions.tsconfig = tsconfig;
|
|
6802
|
-
}
|
|
6803
|
-
await build(buildOptions);
|
|
6804
|
-
if (options.format === "esm") {
|
|
6805
|
-
const packageJsonPath = path5.join(tempBase, "package.json");
|
|
6806
|
-
if (!fs4.existsSync(packageJsonPath)) {
|
|
6807
|
-
fs4.writeFileSync(packageJsonPath, JSON.stringify({ type: "module" }), "utf8");
|
|
6808
|
-
}
|
|
6809
|
-
}
|
|
6810
|
-
const cleanup = () => {
|
|
6811
|
-
if (options.outDir) {
|
|
6812
|
-
return;
|
|
6813
|
-
}
|
|
6814
|
-
fs4.rmSync(tempBase, { recursive: true, force: true });
|
|
6815
|
-
};
|
|
6816
|
-
return { outDir: tempBase, cleanup };
|
|
6817
|
-
}
|
|
6818
|
-
createRequire(
|
|
6819
|
-
typeof __filename !== "undefined" ? __filename : import.meta.url
|
|
6820
|
-
);
|
|
6821
|
-
function resolveCompiledPath(outDir, originalFile, extension = ".js") {
|
|
6822
|
-
const baseName = path5.basename(originalFile).replace(/\.[^.]+$/, "");
|
|
6823
|
-
return path5.join(outDir, `${baseName}${extension}`);
|
|
6824
|
-
}
|
|
6825
|
-
async function importFresh(modulePath) {
|
|
6826
|
-
const fileUrl = pathToFileURL(modulePath).href;
|
|
6827
|
-
const cacheBuster = `t=${Date.now()}-${Math.random()}`;
|
|
6828
|
-
const separator = fileUrl.includes("?") ? "&" : "?";
|
|
6829
|
-
return import(`${fileUrl}${separator}${cacheBuster}`);
|
|
6830
|
-
}
|
|
6831
|
-
|
|
6832
|
-
// src/cli/shared/metadata.ts
|
|
6833
|
-
var METADATA_ENTRY = "metadata.ts";
|
|
6834
|
-
async function loadMetadata2(projectRoot) {
|
|
6835
|
-
const absPath = path5.join(projectRoot, METADATA_ENTRY);
|
|
6836
|
-
if (!fs4.existsSync(absPath)) {
|
|
6837
|
-
return {
|
|
6838
|
-
metadata: MetadataSchema.parse({}),
|
|
6839
|
-
sourcePath: "smart defaults (metadata.ts missing)"
|
|
6840
|
-
};
|
|
6841
|
-
}
|
|
6842
|
-
const tempDir = path5.join(projectRoot, ".opentool-temp");
|
|
6843
|
-
if (fs4.existsSync(tempDir)) {
|
|
6844
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
6845
|
-
}
|
|
6846
|
-
const { outDir, cleanup } = await transpileWithEsbuild({
|
|
6847
|
-
entryPoints: [absPath],
|
|
6848
|
-
projectRoot,
|
|
6849
|
-
format: "esm",
|
|
6850
|
-
outDir: tempDir
|
|
6851
|
-
});
|
|
6852
|
-
try {
|
|
6853
|
-
const compiledPath = resolveCompiledPath(outDir, METADATA_ENTRY);
|
|
6854
|
-
const moduleExports = await importFresh(compiledPath);
|
|
6855
|
-
const metadataExport = extractMetadataExport(moduleExports);
|
|
6856
|
-
const parsed = MetadataSchema.parse(metadataExport);
|
|
6857
|
-
return { metadata: parsed, sourcePath: absPath };
|
|
6858
|
-
} finally {
|
|
6859
|
-
cleanup();
|
|
6860
|
-
if (fs4.existsSync(tempDir)) {
|
|
6861
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
6862
|
-
}
|
|
6863
|
-
}
|
|
6864
|
-
}
|
|
6865
|
-
function extractMetadataExport(moduleExports) {
|
|
6866
|
-
if (!moduleExports || typeof moduleExports !== "object") {
|
|
6867
|
-
throw new Error("metadata.ts must export a metadata object");
|
|
6868
|
-
}
|
|
6869
|
-
const exportsObject = moduleExports;
|
|
6870
|
-
if (exportsObject.metadata) {
|
|
6871
|
-
return exportsObject.metadata;
|
|
6872
|
-
}
|
|
6873
|
-
if (exportsObject.default && typeof exportsObject.default === "object") {
|
|
6874
|
-
const defaultExport = exportsObject.default;
|
|
6875
|
-
if (defaultExport.metadata) {
|
|
6876
|
-
return defaultExport.metadata;
|
|
6877
|
-
}
|
|
6878
|
-
return defaultExport;
|
|
6879
|
-
}
|
|
6880
|
-
return moduleExports;
|
|
6881
|
-
}
|
|
6882
|
-
function readPackageJson(projectRoot) {
|
|
6883
|
-
const packagePath = path5.join(projectRoot, "package.json");
|
|
6884
|
-
if (!fs4.existsSync(packagePath)) {
|
|
6885
|
-
return {};
|
|
6886
|
-
}
|
|
6887
|
-
try {
|
|
6888
|
-
const content = fs4.readFileSync(packagePath, "utf8");
|
|
6889
|
-
return JSON.parse(content);
|
|
6890
|
-
} catch (error) {
|
|
6891
|
-
throw new Error(`Failed to read package.json: ${error}`);
|
|
6892
|
-
}
|
|
6893
|
-
}
|
|
6894
|
-
async function buildMetadataArtifact(options) {
|
|
6895
|
-
const projectRoot = options.projectRoot;
|
|
6896
|
-
const packageInfo = readPackageJson(projectRoot);
|
|
6897
|
-
const { metadata: authored, sourcePath } = await loadMetadata2(projectRoot);
|
|
6898
|
-
const defaultsApplied = [];
|
|
6899
|
-
const folderName = path5.basename(projectRoot);
|
|
6900
|
-
const name = resolveField(
|
|
6901
|
-
"name",
|
|
6902
|
-
authored.name,
|
|
6903
|
-
() => packageInfo.name ?? folderName,
|
|
6904
|
-
defaultsApplied,
|
|
6905
|
-
"package.json name"
|
|
6906
|
-
);
|
|
6907
|
-
const displayName = resolveField(
|
|
6908
|
-
"displayName",
|
|
6909
|
-
authored.displayName,
|
|
6910
|
-
() => {
|
|
6911
|
-
const source = packageInfo.name ?? folderName;
|
|
6912
|
-
return source.split(/[-_]/).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
6913
|
-
},
|
|
6914
|
-
defaultsApplied,
|
|
6915
|
-
"package.json name"
|
|
6916
|
-
);
|
|
6917
|
-
const versionRaw = resolveField(
|
|
6918
|
-
"version",
|
|
6919
|
-
authored.version,
|
|
6920
|
-
() => packageInfo.version ?? "0.1.0",
|
|
6921
|
-
defaultsApplied,
|
|
6922
|
-
"package.json version"
|
|
6923
|
-
);
|
|
6924
|
-
const version = typeof versionRaw === "number" ? String(versionRaw) : versionRaw;
|
|
6925
|
-
const category = determineCategory(authored, defaultsApplied);
|
|
6926
|
-
const description = authored.description ?? packageInfo.description;
|
|
6927
|
-
if (!authored.description && packageInfo.description) {
|
|
6928
|
-
defaultsApplied.push("description \u2192 package.json description");
|
|
6929
|
-
}
|
|
6930
|
-
const author = authored.author ?? packageInfo.author;
|
|
6931
|
-
if (!authored.author && packageInfo.author) {
|
|
6932
|
-
defaultsApplied.push("author \u2192 package.json author");
|
|
6933
|
-
}
|
|
6934
|
-
const repository = authored.repository ?? extractRepository(packageInfo.repository);
|
|
6935
|
-
if (!authored.repository && repository) {
|
|
6936
|
-
defaultsApplied.push("repository \u2192 package.json repository");
|
|
6937
|
-
}
|
|
6938
|
-
const website = authored.website ?? packageInfo.homepage;
|
|
6939
|
-
if (!authored.website && packageInfo.homepage) {
|
|
6940
|
-
defaultsApplied.push("website \u2192 package.json homepage");
|
|
6941
|
-
}
|
|
6942
|
-
const payment = resolvePayment(authored);
|
|
6943
|
-
const baseImage = authored.image ?? authored.iconPath;
|
|
6944
|
-
const animation = authored.animation_url ?? authored.videoPath;
|
|
6945
|
-
const discovery = buildDiscovery(authored);
|
|
6946
|
-
const metadataTools = options.tools.map((tool) => {
|
|
6947
|
-
const overrides = tool.metadata ? ToolMetadataOverridesSchema.parse(tool.metadata) : {};
|
|
6948
|
-
const toolName = overrides.name ?? tool.filename;
|
|
6949
|
-
const toolDescription = overrides.description ?? `${toolName} tool`;
|
|
6950
|
-
const toolPayment = overrides.payment ?? payment ?? void 0;
|
|
6951
|
-
if (!overrides.payment && toolPayment && payment && toolPayment === payment) {
|
|
6952
|
-
defaultsApplied.push(`tool ${toolName} payment \u2192 agent payment`);
|
|
6953
|
-
}
|
|
6954
|
-
const toolDiscovery = overrides.discovery ?? void 0;
|
|
6955
|
-
const toolChains = overrides.chains ?? authored.chains ?? void 0;
|
|
6956
|
-
const toolCategory = tool.profileCategory ?? "tracker";
|
|
6957
|
-
if (!tool.profileCategory) {
|
|
6958
|
-
defaultsApplied.push(`tool ${toolName} category \u2192 tracker (default)`);
|
|
6959
|
-
}
|
|
6960
|
-
const toolDefinition = {
|
|
6961
|
-
name: toolName,
|
|
6962
|
-
description: toolDescription,
|
|
6963
|
-
inputSchema: tool.inputSchema
|
|
6964
|
-
};
|
|
6965
|
-
if (overrides.annotations) {
|
|
6966
|
-
toolDefinition.annotations = overrides.annotations;
|
|
6967
|
-
}
|
|
6968
|
-
if (toolPayment) {
|
|
6969
|
-
toolDefinition.payment = toolPayment;
|
|
6970
|
-
}
|
|
6971
|
-
if (toolDiscovery) {
|
|
6972
|
-
toolDefinition.discovery = toolDiscovery;
|
|
6973
|
-
}
|
|
6974
|
-
if (toolChains) {
|
|
6975
|
-
toolDefinition.chains = toolChains;
|
|
6976
|
-
}
|
|
6977
|
-
toolDefinition.category = toolCategory;
|
|
6978
|
-
const notifyEmail = tool.notifyEmail ?? tool.schedule?.notifyEmail;
|
|
6979
|
-
if (notifyEmail !== void 0) {
|
|
6980
|
-
toolDefinition.notifyEmail = notifyEmail;
|
|
6981
|
-
}
|
|
6982
|
-
if (tool.profileCategory) {
|
|
6983
|
-
toolDefinition.category = tool.profileCategory;
|
|
6984
|
-
}
|
|
6985
|
-
return toolDefinition;
|
|
6986
|
-
});
|
|
6987
|
-
const metadata = BuildMetadataSchema.parse({
|
|
6988
|
-
metadataSpecVersion: authored.metadataSpecVersion ?? METADATA_SPEC_VERSION,
|
|
6989
|
-
name,
|
|
6990
|
-
displayName,
|
|
6991
|
-
version,
|
|
6992
|
-
description,
|
|
6993
|
-
author,
|
|
6994
|
-
repository,
|
|
6995
|
-
website,
|
|
6996
|
-
category,
|
|
6997
|
-
termsOfService: authored.termsOfService,
|
|
6998
|
-
mcpUrl: authored.mcpUrl,
|
|
6999
|
-
payment: payment ?? void 0,
|
|
7000
|
-
tools: metadataTools,
|
|
7001
|
-
discovery,
|
|
7002
|
-
promptExamples: authored.promptExamples,
|
|
7003
|
-
iconPath: authored.iconPath,
|
|
7004
|
-
videoPath: authored.videoPath,
|
|
7005
|
-
image: baseImage,
|
|
7006
|
-
animation_url: animation,
|
|
7007
|
-
chains: authored.chains
|
|
7008
|
-
});
|
|
7009
|
-
return {
|
|
7010
|
-
metadata,
|
|
7011
|
-
defaultsApplied,
|
|
7012
|
-
sourceMetadataPath: sourcePath
|
|
7013
|
-
};
|
|
7014
|
-
}
|
|
7015
|
-
function resolveField(field, value, fallback, defaultsApplied, fallbackLabel) {
|
|
7016
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
7017
|
-
return value;
|
|
7018
|
-
}
|
|
7019
|
-
const resolved = fallback();
|
|
7020
|
-
defaultsApplied.push(`${field} \u2192 ${fallbackLabel}`);
|
|
7021
|
-
return resolved;
|
|
7022
|
-
}
|
|
7023
|
-
function determineCategory(authored, defaultsApplied) {
|
|
7024
|
-
if (authored.category) {
|
|
7025
|
-
return authored.category;
|
|
7026
|
-
}
|
|
7027
|
-
if (Array.isArray(authored.categories) && authored.categories.length > 0) {
|
|
7028
|
-
defaultsApplied.push("category \u2192 metadata.categories[0]");
|
|
7029
|
-
return authored.categories[0];
|
|
7030
|
-
}
|
|
7031
|
-
defaultsApplied.push("category \u2192 default category");
|
|
7032
|
-
return "utility";
|
|
7033
|
-
}
|
|
7034
|
-
function extractRepository(repository) {
|
|
7035
|
-
if (!repository) {
|
|
7036
|
-
return void 0;
|
|
7037
|
-
}
|
|
7038
|
-
if (typeof repository === "string") {
|
|
7039
|
-
return repository;
|
|
7040
|
-
}
|
|
7041
|
-
return repository.url;
|
|
7042
|
-
}
|
|
7043
|
-
function resolvePayment(authored, _defaults) {
|
|
7044
|
-
return authored.payment ?? void 0;
|
|
7045
|
-
}
|
|
7046
|
-
function buildDiscovery(authored) {
|
|
7047
|
-
const legacyDiscovery = {};
|
|
7048
|
-
if (Array.isArray(authored.keywords) && authored.keywords.length > 0) {
|
|
7049
|
-
legacyDiscovery.keywords = authored.keywords;
|
|
7050
|
-
}
|
|
7051
|
-
if (Array.isArray(authored.useCases) && authored.useCases.length > 0) {
|
|
7052
|
-
legacyDiscovery.useCases = authored.useCases;
|
|
7053
|
-
}
|
|
7054
|
-
if (Array.isArray(authored.capabilities) && authored.capabilities.length > 0) {
|
|
7055
|
-
legacyDiscovery.capabilities = authored.capabilities;
|
|
7056
|
-
}
|
|
7057
|
-
if (authored.requirements) {
|
|
7058
|
-
legacyDiscovery.requirements = authored.requirements;
|
|
7059
|
-
}
|
|
7060
|
-
if (authored.compatibility) {
|
|
7061
|
-
legacyDiscovery.compatibility = authored.compatibility;
|
|
7062
|
-
}
|
|
7063
|
-
if (Array.isArray(authored.categories) && authored.categories.length > 0) {
|
|
7064
|
-
legacyDiscovery.category = authored.categories[0];
|
|
7065
|
-
}
|
|
7066
|
-
const merged = {
|
|
7067
|
-
...legacyDiscovery,
|
|
7068
|
-
...authored.discovery
|
|
7069
|
-
};
|
|
7070
|
-
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
7071
|
-
}
|
|
7072
|
-
|
|
7073
|
-
// src/utils/schedule.ts
|
|
7074
|
-
var CRON_WRAPPED_REGEX = /^cron\((.*)\)$/i;
|
|
7075
|
-
var CRON_TOKEN_REGEX = /^[A-Za-z0-9*?/,\-#L]+$/;
|
|
7076
|
-
function normalizeScheduleExpression(raw, context) {
|
|
7077
|
-
const value = raw?.trim();
|
|
7078
|
-
if (!value) {
|
|
7079
|
-
throw new Error(`${context}: profile.schedule.cron must be a non-empty string`);
|
|
7080
|
-
}
|
|
7081
|
-
const cronBody = extractCronBody(value);
|
|
7082
|
-
const cronFields = cronBody.trim().split(/\s+/).filter(Boolean);
|
|
7083
|
-
if (cronFields.length !== 5 && cronFields.length !== 6) {
|
|
7084
|
-
throw new Error(
|
|
7085
|
-
`${context}: cron expression must have 5 or 6 fields (got ${cronFields.length})`
|
|
7086
|
-
);
|
|
7087
|
-
}
|
|
7088
|
-
validateCronTokens(cronFields, context);
|
|
7089
|
-
return {
|
|
7090
|
-
type: "cron",
|
|
7091
|
-
expression: cronFields.join(" ")
|
|
7092
|
-
};
|
|
7093
|
-
}
|
|
7094
|
-
function extractCronBody(value) {
|
|
7095
|
-
const cronMatch = CRON_WRAPPED_REGEX.exec(value);
|
|
7096
|
-
if (cronMatch) {
|
|
7097
|
-
return (cronMatch[1] ?? "").trim();
|
|
7098
|
-
}
|
|
7099
|
-
return value;
|
|
7100
|
-
}
|
|
7101
|
-
function validateCronTokens(fields, context) {
|
|
7102
|
-
fields.forEach((token2, idx) => {
|
|
7103
|
-
if (!CRON_TOKEN_REGEX.test(token2)) {
|
|
7104
|
-
throw new Error(`${context}: invalid cron token "${token2}" at position ${idx + 1}`);
|
|
7105
|
-
}
|
|
7106
|
-
});
|
|
7107
|
-
}
|
|
7108
|
-
|
|
7109
|
-
// src/cli/validate.ts
|
|
7110
|
-
var SUPPORTED_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
7111
|
-
var OPENTOOL_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
7112
|
-
var OPENTOOL_NODE_MODULES = path5.join(OPENTOOL_ROOT, "node_modules");
|
|
7113
|
-
var MIN_TEMPLATE_CONFIG_VERSION = 2;
|
|
7114
|
-
var TEMPLATE_PREVIEW_TITLE_MAX = 80;
|
|
7115
|
-
var TEMPLATE_PREVIEW_SUBTITLE_MAX = 120;
|
|
7116
|
-
var TEMPLATE_PREVIEW_DESCRIPTION_MAX = 1200;
|
|
7117
|
-
var TEMPLATE_PREVIEW_MIN_LINES = 3;
|
|
7118
|
-
var TEMPLATE_PREVIEW_MAX_LINES = 8;
|
|
7119
|
-
function normalizeTemplateConfigVersion(value) {
|
|
7120
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
7121
|
-
return value;
|
|
7122
|
-
}
|
|
7123
|
-
if (typeof value !== "string") {
|
|
7124
|
-
return null;
|
|
7125
|
-
}
|
|
7126
|
-
const trimmed = value.trim();
|
|
7127
|
-
if (!trimmed) {
|
|
7128
|
-
return null;
|
|
7129
|
-
}
|
|
7130
|
-
if (/^\d+(?:\.\d+)?$/.test(trimmed)) {
|
|
7131
|
-
const numeric = Number.parseFloat(trimmed);
|
|
7132
|
-
return Number.isFinite(numeric) ? numeric : null;
|
|
7133
|
-
}
|
|
7134
|
-
const majorMatch = /^v?(\d+)(?:\..*)?$/i.exec(trimmed);
|
|
7135
|
-
if (!majorMatch) {
|
|
7136
|
-
return null;
|
|
7137
|
-
}
|
|
7138
|
-
const major = Number.parseInt(majorMatch[1], 10);
|
|
7139
|
-
return Number.isFinite(major) ? major : null;
|
|
7140
|
-
}
|
|
7141
|
-
function parseNonEmptyString(value, fieldPath, opts = {}) {
|
|
7142
|
-
const { max, required = false } = opts;
|
|
7143
|
-
if (value == null) {
|
|
7144
|
-
if (required) {
|
|
7145
|
-
throw new Error(`${fieldPath} is required and must be a non-empty string.`);
|
|
7146
|
-
}
|
|
7147
|
-
return null;
|
|
7148
|
-
}
|
|
7149
|
-
if (typeof value !== "string") {
|
|
7150
|
-
throw new Error(`${fieldPath} must be a string.`);
|
|
7151
|
-
}
|
|
7152
|
-
const trimmed = value.trim();
|
|
7153
|
-
if (!trimmed) {
|
|
7154
|
-
throw new Error(`${fieldPath} must be a non-empty string.`);
|
|
7155
|
-
}
|
|
7156
|
-
if (typeof max === "number" && trimmed.length > max) {
|
|
7157
|
-
throw new Error(`${fieldPath} must be <= ${max} characters.`);
|
|
7158
|
-
}
|
|
7159
|
-
return trimmed;
|
|
7160
|
-
}
|
|
7161
|
-
function normalizeTemplatePreview(value, file, toolName, requirePreview) {
|
|
7162
|
-
const pathPrefix = `${file}: profile.templatePreview`;
|
|
7163
|
-
if (value == null) {
|
|
7164
|
-
if (requirePreview) {
|
|
7165
|
-
throw new Error(
|
|
7166
|
-
`${pathPrefix} is required for strategy tools and must define subtitle + description.`
|
|
7167
|
-
);
|
|
7168
|
-
}
|
|
7169
|
-
return null;
|
|
7170
|
-
}
|
|
7171
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
7172
|
-
throw new Error(`${pathPrefix} must be an object.`);
|
|
7173
|
-
}
|
|
7174
|
-
const record = value;
|
|
7175
|
-
const title = parseNonEmptyString(record.title, `${pathPrefix}.title`, {
|
|
7176
|
-
max: TEMPLATE_PREVIEW_TITLE_MAX
|
|
7177
|
-
}) ?? toolName;
|
|
7178
|
-
const subtitle = parseNonEmptyString(record.subtitle, `${pathPrefix}.subtitle`, {
|
|
7179
|
-
required: true,
|
|
7180
|
-
max: TEMPLATE_PREVIEW_SUBTITLE_MAX
|
|
7181
|
-
});
|
|
7182
|
-
const description = parseNonEmptyString(record.description, `${pathPrefix}.description`, {
|
|
7183
|
-
required: true,
|
|
7184
|
-
max: TEMPLATE_PREVIEW_DESCRIPTION_MAX
|
|
7185
|
-
});
|
|
7186
|
-
const descriptionLineCount = description.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).length;
|
|
7187
|
-
if (descriptionLineCount < TEMPLATE_PREVIEW_MIN_LINES || descriptionLineCount > TEMPLATE_PREVIEW_MAX_LINES) {
|
|
7188
|
-
throw new Error(
|
|
7189
|
-
`${pathPrefix}.description must contain ${TEMPLATE_PREVIEW_MIN_LINES}-${TEMPLATE_PREVIEW_MAX_LINES} non-empty lines (target ~5 lines).`
|
|
7190
|
-
);
|
|
7191
|
-
}
|
|
7192
|
-
return {
|
|
7193
|
-
title,
|
|
7194
|
-
subtitle,
|
|
7195
|
-
description
|
|
7196
|
-
};
|
|
7197
|
-
}
|
|
7198
|
-
async function validateCommand(options) {
|
|
7199
|
-
console.log("\u{1F50D} Validating OpenTool project...");
|
|
7200
|
-
try {
|
|
7201
|
-
const toolsDir = path5.resolve(options.input);
|
|
7202
|
-
if (!fs4.existsSync(toolsDir)) {
|
|
7203
|
-
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
7204
|
-
}
|
|
7205
|
-
const projectRoot = path5.dirname(toolsDir);
|
|
7206
|
-
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
7207
|
-
if (tools.length === 0) {
|
|
7208
|
-
throw new Error("No valid tools found - validation aborted");
|
|
7209
|
-
}
|
|
7210
|
-
const { metadata, defaultsApplied, sourceMetadataPath } = await buildMetadataArtifact({
|
|
7211
|
-
projectRoot,
|
|
7212
|
-
tools
|
|
7213
|
-
});
|
|
7214
|
-
logMetadataSummary(metadata, defaultsApplied, sourceMetadataPath);
|
|
7215
|
-
console.log("\n\u2705 OpenTool validation passed!\n");
|
|
7216
|
-
} catch (error) {
|
|
7217
|
-
console.error("\u274C OpenTool validation failed:", error);
|
|
7218
|
-
process.exit(1);
|
|
7219
|
-
}
|
|
7220
|
-
}
|
|
7221
|
-
async function loadAndValidateTools(toolsDir, options = {}) {
|
|
7222
|
-
const files = fs4.readdirSync(toolsDir).filter((file) => SUPPORTED_EXTENSIONS.includes(path5.extname(file)));
|
|
7223
|
-
if (files.length === 0) {
|
|
7224
|
-
return [];
|
|
7225
|
-
}
|
|
7226
|
-
const projectRoot = options.projectRoot ?? path5.dirname(toolsDir);
|
|
7227
|
-
const tempDir = path5.join(toolsDir, ".opentool-temp");
|
|
7228
|
-
if (fs4.existsSync(tempDir)) {
|
|
7229
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7230
|
-
}
|
|
7231
|
-
const kebabCase = /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z]+$/;
|
|
7232
|
-
for (const f of files) {
|
|
7233
|
-
if (!kebabCase.test(f)) {
|
|
7234
|
-
throw new Error(`Tool filename must be kebab-case: ${f}`);
|
|
7235
|
-
}
|
|
7236
|
-
}
|
|
7237
|
-
const entryPoints = files.map((file) => path5.join(toolsDir, file));
|
|
7238
|
-
const fallbackNodePaths = [OPENTOOL_NODE_MODULES].filter((dir) => fs4.existsSync(dir));
|
|
7239
|
-
const { outDir, cleanup } = await transpileWithEsbuild({
|
|
7240
|
-
entryPoints,
|
|
7241
|
-
projectRoot,
|
|
7242
|
-
format: "esm",
|
|
7243
|
-
outDir: tempDir,
|
|
7244
|
-
bundle: true,
|
|
7245
|
-
external: ["opentool", "opentool/*"],
|
|
7246
|
-
...fallbackNodePaths.length > 0 ? { nodePaths: fallbackNodePaths } : {}
|
|
7247
|
-
});
|
|
7248
|
-
const tools = [];
|
|
7249
|
-
try {
|
|
7250
|
-
ensureLocalRuntimeLinks(tempDir);
|
|
7251
|
-
for (const file of files) {
|
|
7252
|
-
const compiledPath = resolveCompiledPath(outDir, file);
|
|
7253
|
-
if (!fs4.existsSync(compiledPath)) {
|
|
7254
|
-
throw new Error(`Failed to compile ${file}`);
|
|
7255
|
-
}
|
|
7256
|
-
const moduleExports = await importFresh(compiledPath);
|
|
7257
|
-
const toolModule = extractToolModule(moduleExports, file);
|
|
7258
|
-
const schema = ensureZodSchema(toolModule.schema, file);
|
|
7259
|
-
const paymentExport = toolModule.payment;
|
|
7260
|
-
const toolName = toolModule.metadata?.name ?? toolModule.metadata?.title ?? toBaseName(file);
|
|
7261
|
-
const inputSchemaRaw = schema ? toJsonSchema(toolName, schema) : void 0;
|
|
7262
|
-
const inputSchema = normalizeInputSchema2(inputSchemaRaw);
|
|
7263
|
-
const httpHandlersRaw = collectHttpHandlers2(toolModule, file);
|
|
7264
|
-
const hasGET = typeof toolModule.GET === "function";
|
|
7265
|
-
const hasPOST = typeof toolModule.POST === "function";
|
|
7266
|
-
const otherMethods = HTTP_METHODS2.filter((m) => m !== "GET" && m !== "POST").filter(
|
|
7267
|
-
(m) => typeof toolModule[m] === "function"
|
|
7268
|
-
);
|
|
7269
|
-
if (otherMethods.length > 0) {
|
|
7270
|
-
throw new Error(
|
|
7271
|
-
`${file} must not export ${otherMethods.join(", ")}. Only one of GET or POST is allowed.`
|
|
7272
|
-
);
|
|
7273
|
-
}
|
|
7274
|
-
if (hasGET === hasPOST) {
|
|
7275
|
-
throw new Error(`${file}: export exactly one of GET or POST`);
|
|
7276
|
-
}
|
|
7277
|
-
let normalizedSchedule = null;
|
|
7278
|
-
const profileRaw = toolModule?.profile && typeof toolModule.profile === "object" ? toolModule.profile : null;
|
|
7279
|
-
const schedule = profileRaw?.schedule ?? null;
|
|
7280
|
-
const profileNotifyEmail = typeof profileRaw?.notifyEmail === "boolean" ? profileRaw.notifyEmail : void 0;
|
|
7281
|
-
const allowedProfileCategories = ["strategy", "tracker", "orchestrator"];
|
|
7282
|
-
const profileCategoryCandidate = typeof profileRaw?.category === "string" ? profileRaw.category : void 0;
|
|
7283
|
-
let profileCategoryRaw;
|
|
7284
|
-
if (profileCategoryCandidate !== void 0) {
|
|
7285
|
-
const isAllowed = allowedProfileCategories.includes(
|
|
7286
|
-
profileCategoryCandidate
|
|
7287
|
-
);
|
|
7288
|
-
if (!isAllowed) {
|
|
7289
|
-
throw new Error(
|
|
7290
|
-
`${file}: profile.category must be one of ${allowedProfileCategories.join(", ")}`
|
|
7291
|
-
);
|
|
7292
|
-
}
|
|
7293
|
-
profileCategoryRaw = profileCategoryCandidate;
|
|
7294
|
-
}
|
|
7295
|
-
const profileAssetsRaw = profileRaw?.assets;
|
|
7296
|
-
if (profileAssetsRaw !== void 0) {
|
|
7297
|
-
if (!Array.isArray(profileAssetsRaw)) {
|
|
7298
|
-
throw new Error(`${file}: profile.assets must be an array.`);
|
|
7299
|
-
}
|
|
7300
|
-
profileAssetsRaw.forEach((entry, index) => {
|
|
7301
|
-
if (!entry || typeof entry !== "object") {
|
|
7302
|
-
throw new Error(`${file}: profile.assets[${index}] must be an object.`);
|
|
7303
|
-
}
|
|
7304
|
-
const record = entry;
|
|
7305
|
-
const venue = typeof record.venue === "string" ? record.venue.trim() : "";
|
|
7306
|
-
if (!venue) {
|
|
7307
|
-
throw new Error(`${file}: profile.assets[${index}].venue must be a non-empty string.`);
|
|
7308
|
-
}
|
|
7309
|
-
const chain = record.chain;
|
|
7310
|
-
if (typeof chain !== "string" && typeof chain !== "number") {
|
|
7311
|
-
throw new Error(`${file}: profile.assets[${index}].chain must be a string or number.`);
|
|
7312
|
-
}
|
|
7313
|
-
const symbols = record.assetSymbols;
|
|
7314
|
-
if (!Array.isArray(symbols) || symbols.length === 0) {
|
|
7315
|
-
throw new Error(
|
|
7316
|
-
`${file}: profile.assets[${index}].assetSymbols must be a non-empty array.`
|
|
7317
|
-
);
|
|
7318
|
-
}
|
|
7319
|
-
const invalidSymbol = symbols.find(
|
|
7320
|
-
(symbol) => typeof symbol !== "string" || symbol.trim().length === 0
|
|
7321
|
-
);
|
|
7322
|
-
if (invalidSymbol !== void 0) {
|
|
7323
|
-
throw new Error(
|
|
7324
|
-
`${file}: profile.assets[${index}].assetSymbols must be non-empty strings.`
|
|
7325
|
-
);
|
|
7326
|
-
}
|
|
7327
|
-
const walletAddress = record.walletAddress;
|
|
7328
|
-
if (walletAddress !== void 0 && (typeof walletAddress !== "string" || walletAddress.trim().length === 0)) {
|
|
7329
|
-
throw new Error(
|
|
7330
|
-
`${file}: profile.assets[${index}].walletAddress must be a non-empty string when provided.`
|
|
7331
|
-
);
|
|
7332
|
-
}
|
|
7333
|
-
const pair = record.pair;
|
|
7334
|
-
if (pair !== void 0 && (typeof pair !== "string" || pair.trim().length === 0)) {
|
|
7335
|
-
throw new Error(
|
|
7336
|
-
`${file}: profile.assets[${index}].pair must be a non-empty string when provided.`
|
|
7337
|
-
);
|
|
7338
|
-
}
|
|
7339
|
-
const leverage = record.leverage;
|
|
7340
|
-
if (leverage !== void 0 && (typeof leverage !== "number" || !Number.isFinite(leverage) || leverage <= 0)) {
|
|
7341
|
-
throw new Error(
|
|
7342
|
-
`${file}: profile.assets[${index}].leverage must be a positive number when provided.`
|
|
7343
|
-
);
|
|
7344
|
-
}
|
|
7345
|
-
});
|
|
7346
|
-
}
|
|
7347
|
-
const templateConfigRaw = profileRaw?.templateConfig;
|
|
7348
|
-
if (templateConfigRaw !== void 0) {
|
|
7349
|
-
if (!templateConfigRaw || typeof templateConfigRaw !== "object") {
|
|
7350
|
-
throw new Error(`${file}: profile.templateConfig must be an object.`);
|
|
7351
|
-
}
|
|
7352
|
-
const record = templateConfigRaw;
|
|
7353
|
-
const version = record.version;
|
|
7354
|
-
const normalizedTemplateConfigVersion = normalizeTemplateConfigVersion(version);
|
|
7355
|
-
if (normalizedTemplateConfigVersion === null) {
|
|
7356
|
-
throw new Error(
|
|
7357
|
-
`${file}: profile.templateConfig.version must be a numeric string or number.`
|
|
7358
|
-
);
|
|
7359
|
-
}
|
|
7360
|
-
if (normalizedTemplateConfigVersion < MIN_TEMPLATE_CONFIG_VERSION) {
|
|
7361
|
-
throw new Error(
|
|
7362
|
-
`${file}: profile.templateConfig.version must be >= ${MIN_TEMPLATE_CONFIG_VERSION}.`
|
|
7363
|
-
);
|
|
7364
|
-
}
|
|
7365
|
-
const schema2 = record.schema;
|
|
7366
|
-
if (schema2 !== void 0 && (!schema2 || typeof schema2 !== "object" || Array.isArray(schema2))) {
|
|
7367
|
-
throw new Error(
|
|
7368
|
-
`${file}: profile.templateConfig.schema must be an object when provided.`
|
|
7369
|
-
);
|
|
7370
|
-
}
|
|
7371
|
-
const defaults = record.defaults;
|
|
7372
|
-
if (defaults !== void 0 && (!defaults || typeof defaults !== "object" || Array.isArray(defaults))) {
|
|
7373
|
-
throw new Error(
|
|
7374
|
-
`${file}: profile.templateConfig.defaults must be an object when provided.`
|
|
7375
|
-
);
|
|
7376
|
-
}
|
|
7377
|
-
const envVar = record.envVar;
|
|
7378
|
-
if (envVar !== void 0 && (typeof envVar !== "string" || envVar.trim().length === 0)) {
|
|
7379
|
-
throw new Error(
|
|
7380
|
-
`${file}: profile.templateConfig.envVar must be a non-empty string when provided.`
|
|
7381
|
-
);
|
|
7382
|
-
}
|
|
7383
|
-
}
|
|
7384
|
-
const normalizedTemplatePreview = normalizeTemplatePreview(
|
|
7385
|
-
profileRaw?.templatePreview,
|
|
7386
|
-
file,
|
|
7387
|
-
toolName,
|
|
7388
|
-
profileCategoryRaw === "strategy"
|
|
7389
|
-
);
|
|
7390
|
-
const normalizedProfile = profileRaw && normalizedTemplatePreview ? { ...profileRaw, templatePreview: normalizedTemplatePreview } : profileRaw;
|
|
7391
|
-
if (hasGET && schedule && typeof schedule.cron === "string" && schedule.cron.trim().length > 0) {
|
|
7392
|
-
normalizedSchedule = normalizeScheduleExpression(schedule.cron, file);
|
|
7393
|
-
if (typeof schedule.enabled === "boolean") {
|
|
7394
|
-
normalizedSchedule.authoredEnabled = schedule.enabled;
|
|
7395
|
-
}
|
|
7396
|
-
if (typeof schedule.notifyEmail === "boolean") {
|
|
7397
|
-
normalizedSchedule.notifyEmail = schedule.notifyEmail;
|
|
7398
|
-
}
|
|
7399
|
-
}
|
|
7400
|
-
if (hasPOST) {
|
|
7401
|
-
if (!schema) {
|
|
7402
|
-
throw new Error(`${file}: POST tools must export a Zod schema as 'schema'`);
|
|
7403
|
-
}
|
|
7404
|
-
}
|
|
7405
|
-
const httpHandlers = [...httpHandlersRaw];
|
|
7406
|
-
if (httpHandlers.length === 0) {
|
|
7407
|
-
throw new Error(`${file} must export at least one HTTP handler (e.g. POST)`);
|
|
7408
|
-
}
|
|
7409
|
-
if (paymentExport) {
|
|
7410
|
-
for (let index = 0; index < httpHandlers.length; index += 1) {
|
|
7411
|
-
const entry = httpHandlers[index];
|
|
7412
|
-
httpHandlers[index] = {
|
|
7413
|
-
...entry,
|
|
7414
|
-
handler: withX402Payment(entry.handler, paymentExport)
|
|
7415
|
-
};
|
|
7416
|
-
}
|
|
7417
|
-
}
|
|
7418
|
-
const httpHandlerMap = toHttpHandlerMap2(httpHandlers);
|
|
7419
|
-
const defaultMethod = typeof toolModule.mcp?.defaultMethod === "string" ? toolModule.mcp.defaultMethod : void 0;
|
|
7420
|
-
const adapter = createMcpAdapter({
|
|
7421
|
-
name: toolName,
|
|
7422
|
-
httpHandlers: httpHandlerMap,
|
|
7423
|
-
...defaultMethod ? { defaultMethod } : {},
|
|
7424
|
-
...schema ? { schema } : {}
|
|
7425
|
-
});
|
|
7426
|
-
let metadataOverrides = toolModule.metadata ?? null;
|
|
7427
|
-
if (paymentExport) {
|
|
7428
|
-
if (metadataOverrides) {
|
|
7429
|
-
metadataOverrides = {
|
|
7430
|
-
...metadataOverrides,
|
|
7431
|
-
payment: metadataOverrides.payment ?? paymentExport,
|
|
7432
|
-
annotations: {
|
|
7433
|
-
...metadataOverrides.annotations,
|
|
7434
|
-
requiresPayment: metadataOverrides.annotations?.requiresPayment ?? true
|
|
7435
|
-
}
|
|
7436
|
-
};
|
|
7437
|
-
} else {
|
|
7438
|
-
metadataOverrides = {
|
|
7439
|
-
payment: paymentExport,
|
|
7440
|
-
annotations: { requiresPayment: true }
|
|
7441
|
-
};
|
|
7442
|
-
}
|
|
7443
|
-
}
|
|
7444
|
-
const tool = {
|
|
7445
|
-
schema: schema ?? void 0,
|
|
7446
|
-
inputSchema,
|
|
7447
|
-
metadata: metadataOverrides,
|
|
7448
|
-
httpHandlers,
|
|
7449
|
-
mcpConfig: normalizeMcpConfig(toolModule.mcp, file),
|
|
7450
|
-
filename: toBaseName(file),
|
|
7451
|
-
sourcePath: path5.join(toolsDir, file),
|
|
7452
|
-
handler: async (params) => adapter(params),
|
|
7453
|
-
payment: paymentExport ?? null,
|
|
7454
|
-
schedule: normalizedSchedule,
|
|
7455
|
-
profile: normalizedProfile,
|
|
7456
|
-
...profileNotifyEmail !== void 0 ? { notifyEmail: profileNotifyEmail } : {},
|
|
7457
|
-
profileDescription: typeof profileRaw?.description === "string" ? profileRaw.description : null,
|
|
7458
|
-
...profileCategoryRaw ? { profileCategory: profileCategoryRaw } : {}
|
|
7459
|
-
};
|
|
7460
|
-
tools.push(tool);
|
|
7461
|
-
}
|
|
7462
|
-
} finally {
|
|
7463
|
-
cleanup();
|
|
7464
|
-
if (fs4.existsSync(tempDir)) {
|
|
7465
|
-
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
7466
|
-
}
|
|
7467
|
-
}
|
|
7468
|
-
return tools;
|
|
7469
|
-
}
|
|
7470
|
-
function ensureLocalRuntimeLinks(tempDir) {
|
|
7471
|
-
const nodeModulesDir = path5.join(tempDir, "node_modules");
|
|
7472
|
-
fs4.mkdirSync(nodeModulesDir, { recursive: true });
|
|
7473
|
-
const packageLinks = [
|
|
7474
|
-
{ name: "opentool", target: OPENTOOL_ROOT },
|
|
7475
|
-
{ name: "zod", target: path5.join(OPENTOOL_NODE_MODULES, "zod") }
|
|
7476
|
-
];
|
|
7477
|
-
for (const { name, target } of packageLinks) {
|
|
7478
|
-
if (!fs4.existsSync(target)) {
|
|
7479
|
-
continue;
|
|
7480
|
-
}
|
|
7481
|
-
const linkPath = path5.join(nodeModulesDir, name);
|
|
7482
|
-
if (fs4.existsSync(linkPath)) {
|
|
7483
|
-
continue;
|
|
7484
|
-
}
|
|
7485
|
-
fs4.symlinkSync(target, linkPath, "junction");
|
|
7486
|
-
}
|
|
7487
|
-
}
|
|
7488
|
-
function extractToolModule(exportsObject, filename) {
|
|
7489
|
-
const candidates = [exportsObject, exportsObject?.default];
|
|
7490
|
-
for (const candidate of candidates) {
|
|
7491
|
-
if (candidate && typeof candidate === "object") {
|
|
7492
|
-
const hasSchema = candidate.schema && typeof candidate.schema === "object";
|
|
7493
|
-
const hasHttp = HTTP_METHODS2.some((method) => typeof candidate[method] === "function");
|
|
7494
|
-
if (hasSchema || hasHttp) {
|
|
7495
|
-
return candidate;
|
|
7496
|
-
}
|
|
7497
|
-
}
|
|
7498
|
-
}
|
|
7499
|
-
throw new Error(
|
|
7500
|
-
`${filename} must export a tool definition. Expected a Zod schema plus HTTP handlers (export async function POST).`
|
|
7501
|
-
);
|
|
7502
|
-
}
|
|
7503
|
-
function toJsonSchema(name, schema) {
|
|
7504
|
-
if (!schema) {
|
|
7505
|
-
return void 0;
|
|
7506
|
-
}
|
|
7507
|
-
try {
|
|
7508
|
-
return zodToJsonSchema(schema, {
|
|
7509
|
-
name: `${name}Schema`,
|
|
7510
|
-
target: "jsonSchema7",
|
|
7511
|
-
$refStrategy: "none"
|
|
7512
|
-
});
|
|
7513
|
-
} catch (error) {
|
|
7514
|
-
throw new Error(`Failed to convert Zod schema for ${name}: ${error}`);
|
|
7515
|
-
}
|
|
7516
|
-
}
|
|
7517
|
-
function toBaseName(file) {
|
|
7518
|
-
return file.replace(/\.[^.]+$/, "");
|
|
7519
|
-
}
|
|
7520
|
-
function ensureZodSchema(schemaCandidate, filename) {
|
|
7521
|
-
if (schemaCandidate == null) {
|
|
7522
|
-
return void 0;
|
|
7523
|
-
}
|
|
7524
|
-
if (schemaCandidate instanceof z.ZodType) {
|
|
7525
|
-
return schemaCandidate;
|
|
7526
|
-
}
|
|
7527
|
-
const schema = schemaCandidate;
|
|
7528
|
-
if (typeof schema?.parse !== "function") {
|
|
7529
|
-
throw new Error(`${filename} schema export must be a Zod schema (missing parse method)`);
|
|
7530
|
-
}
|
|
7531
|
-
return schema;
|
|
7532
|
-
}
|
|
7533
|
-
function collectHttpHandlers2(module, filename) {
|
|
7534
|
-
const handlers = [];
|
|
7535
|
-
for (const method of HTTP_METHODS2) {
|
|
7536
|
-
const handler = module?.[method];
|
|
7537
|
-
if (typeof handler === "function") {
|
|
7538
|
-
handlers.push({
|
|
7539
|
-
method,
|
|
7540
|
-
handler: async (request) => handler.call(module, request)
|
|
7541
|
-
});
|
|
7542
|
-
}
|
|
7543
|
-
}
|
|
7544
|
-
handlers.sort((a, b) => HTTP_METHODS2.indexOf(a.method) - HTTP_METHODS2.indexOf(b.method));
|
|
7545
|
-
const duplicates = findDuplicates(handlers.map((h) => h.method));
|
|
7546
|
-
if (duplicates.length > 0) {
|
|
7547
|
-
throw new Error(
|
|
7548
|
-
`${filename} exports multiple handlers for HTTP method(s): ${duplicates.join(", ")}`
|
|
7549
|
-
);
|
|
7550
|
-
}
|
|
7551
|
-
return handlers;
|
|
7552
|
-
}
|
|
7553
|
-
function toHttpHandlerMap2(handlers) {
|
|
7554
|
-
return handlers.reduce((acc, handler) => {
|
|
7555
|
-
acc[handler.method.toUpperCase()] = handler.handler;
|
|
7556
|
-
return acc;
|
|
7557
|
-
}, {});
|
|
7558
|
-
}
|
|
7559
|
-
function normalizeInputSchema2(schema) {
|
|
7560
|
-
if (!schema || typeof schema !== "object") {
|
|
7561
|
-
return schema;
|
|
7562
|
-
}
|
|
7563
|
-
const clone = JSON.parse(JSON.stringify(schema));
|
|
7564
|
-
if (typeof clone.$ref === "string" && clone.$ref.startsWith("#/definitions/")) {
|
|
7565
|
-
const refName = clone.$ref.replace("#/definitions/", "");
|
|
7566
|
-
const definitions = clone.definitions;
|
|
7567
|
-
if (definitions && typeof definitions[refName] === "object") {
|
|
7568
|
-
return normalizeInputSchema2(definitions[refName]);
|
|
7569
|
-
}
|
|
7570
|
-
}
|
|
7571
|
-
delete clone.$ref;
|
|
7572
|
-
delete clone.definitions;
|
|
7573
|
-
if (!("type" in clone)) {
|
|
7574
|
-
clone.type = "object";
|
|
7575
|
-
}
|
|
7576
|
-
return clone;
|
|
7577
|
-
}
|
|
7578
|
-
function normalizeMcpConfig(rawConfig, filename) {
|
|
7579
|
-
if (rawConfig == null) {
|
|
7580
|
-
return null;
|
|
7581
|
-
}
|
|
7582
|
-
if (rawConfig === false) {
|
|
7583
|
-
return null;
|
|
7584
|
-
}
|
|
7585
|
-
if (rawConfig === true) {
|
|
7586
|
-
return { enabled: true };
|
|
7587
|
-
}
|
|
7588
|
-
if (!isPlainObject2(rawConfig)) {
|
|
7589
|
-
throw new Error(`${filename} export \\"mcp\\" must be an object with an enabled flag`);
|
|
7590
|
-
}
|
|
7591
|
-
const enabledRaw = rawConfig.enabled;
|
|
7592
|
-
if (enabledRaw === false) {
|
|
7593
|
-
return null;
|
|
7594
|
-
}
|
|
7595
|
-
if (enabledRaw !== true) {
|
|
7596
|
-
throw new Error(`${filename} mcp.enabled must be explicitly set to true to opt-in to MCP`);
|
|
7597
|
-
}
|
|
7598
|
-
const modeRaw = rawConfig.mode;
|
|
7599
|
-
let mode;
|
|
7600
|
-
if (typeof modeRaw === "string") {
|
|
7601
|
-
const normalized = modeRaw.toLowerCase();
|
|
7602
|
-
if (["stdio", "lambda", "dual"].includes(normalized)) {
|
|
7603
|
-
mode = normalized;
|
|
7604
|
-
} else {
|
|
7605
|
-
throw new Error(
|
|
7606
|
-
`${filename} mcp.mode must be one of "stdio", "lambda", or "dual" if specified`
|
|
7607
|
-
);
|
|
7608
|
-
}
|
|
7609
|
-
}
|
|
7610
|
-
const defaultMethodRaw = rawConfig.defaultMethod;
|
|
7611
|
-
const defaultMethod = typeof defaultMethodRaw === "string" ? defaultMethodRaw.toUpperCase() : void 0;
|
|
7612
|
-
const overridesRaw = rawConfig.metadataOverrides;
|
|
7613
|
-
const metadataOverrides = isPlainObject2(overridesRaw) ? overridesRaw : void 0;
|
|
7614
|
-
const config = {
|
|
7615
|
-
enabled: true
|
|
7616
|
-
};
|
|
7617
|
-
if (mode) {
|
|
7618
|
-
config.mode = mode;
|
|
7619
|
-
}
|
|
7620
|
-
if (defaultMethod) {
|
|
7621
|
-
config.defaultMethod = defaultMethod;
|
|
7622
|
-
}
|
|
7623
|
-
if (metadataOverrides) {
|
|
7624
|
-
config.metadataOverrides = metadataOverrides;
|
|
7625
|
-
}
|
|
7626
|
-
return config;
|
|
7627
|
-
}
|
|
7628
|
-
function isPlainObject2(value) {
|
|
7629
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7630
|
-
}
|
|
7631
|
-
function findDuplicates(values) {
|
|
7632
|
-
const seen = /* @__PURE__ */ new Map();
|
|
7633
|
-
const duplicates = /* @__PURE__ */ new Set();
|
|
7634
|
-
values.forEach((value) => {
|
|
7635
|
-
const count = seen.get(value) ?? 0;
|
|
7636
|
-
seen.set(value, count + 1);
|
|
7637
|
-
if (count >= 1) {
|
|
7638
|
-
duplicates.add(value);
|
|
7639
|
-
}
|
|
7640
|
-
});
|
|
7641
|
-
return Array.from(duplicates.values());
|
|
7642
|
-
}
|
|
7643
|
-
function logMetadataSummary(metadata, defaultsApplied, sourceMetadataPath) {
|
|
7644
|
-
console.log(`\u{1F4C4} metadata loaded from ${sourceMetadataPath}`);
|
|
7645
|
-
console.log("\n\u{1F4CA} Metadata Summary:");
|
|
7646
|
-
console.log(` \u2022 Name: ${metadata.name}`);
|
|
7647
|
-
console.log(` \u2022 Display Name: ${metadata.displayName}`);
|
|
7648
|
-
console.log(` \u2022 Version: ${metadata.version}`);
|
|
7649
|
-
console.log(` \u2022 Category: ${metadata.category}`);
|
|
7650
|
-
console.log(` \u2022 Tools: ${metadata.tools.length}`);
|
|
7651
|
-
console.log(` \u2022 Spec Version: ${metadata.metadataSpecVersion}`);
|
|
7652
|
-
if (metadata.payment) {
|
|
7653
|
-
console.log(` \u2022 Payment: $${metadata.payment.amountUSDC} USDC`);
|
|
7654
|
-
}
|
|
7655
|
-
if (defaultsApplied.length > 0) {
|
|
7656
|
-
console.log("\nDefaults applied during metadata synthesis:");
|
|
7657
|
-
defaultsApplied.forEach((entry) => console.log(` \u2022 ${entry}`));
|
|
7658
|
-
}
|
|
7659
|
-
}
|
|
7660
|
-
|
|
7661
|
-
// src/cli/generate-metadata.ts
|
|
7662
|
-
async function generateMetadataCommand(options) {
|
|
7663
|
-
const startTimestamp = timestamp();
|
|
7664
|
-
console.log(`[${startTimestamp}] Generating OpenTool metadata...`);
|
|
7665
|
-
try {
|
|
7666
|
-
const result = await generateMetadata(options);
|
|
7667
|
-
const endTimestamp = timestamp();
|
|
7668
|
-
console.log(`[${endTimestamp}] Metadata generation completed successfully!`);
|
|
7669
|
-
console.log(`Output file: ${result.outputPath}`);
|
|
7670
|
-
console.log(`Spec version: ${result.metadata.metadataSpecVersion}`);
|
|
7671
|
-
console.log(`Tools included: ${result.tools.length}`);
|
|
7672
|
-
if (result.defaultsApplied.length > 0) {
|
|
7673
|
-
console.log("Applied defaults:");
|
|
7674
|
-
for (const entry of result.defaultsApplied) {
|
|
7675
|
-
console.log(` \u2022 ${entry}`);
|
|
7676
|
-
}
|
|
7677
|
-
}
|
|
7678
|
-
} catch (error) {
|
|
7679
|
-
const endTimestamp = timestamp();
|
|
7680
|
-
console.error(`[${endTimestamp}] Metadata generation failed:`, error);
|
|
7681
|
-
process.exit(1);
|
|
7682
|
-
}
|
|
7683
|
-
}
|
|
7684
|
-
async function generateMetadata(options) {
|
|
7685
|
-
const toolsDir = path5.resolve(options.input);
|
|
7686
|
-
if (!fs4.existsSync(toolsDir)) {
|
|
7687
|
-
throw new Error(`Tools directory not found: ${toolsDir}`);
|
|
7688
|
-
}
|
|
7689
|
-
const projectRoot = path5.dirname(toolsDir);
|
|
7690
|
-
const tools = await loadAndValidateTools(toolsDir, { projectRoot });
|
|
7691
|
-
const { metadata, defaultsApplied } = await buildMetadataArtifact({
|
|
7692
|
-
projectRoot,
|
|
7693
|
-
tools
|
|
7694
|
-
});
|
|
7695
|
-
const outputPath = options.output ? path5.resolve(options.output) : path5.join(projectRoot, "metadata.json");
|
|
7696
|
-
fs4.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
|
|
7697
|
-
return {
|
|
7698
|
-
metadata,
|
|
7699
|
-
defaultsApplied,
|
|
7700
|
-
tools,
|
|
7701
|
-
outputPath
|
|
7702
|
-
};
|
|
7703
|
-
}
|
|
7704
|
-
function timestamp() {
|
|
7705
|
-
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
7706
|
-
}
|
|
7707
6846
|
|
|
7708
|
-
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_TIMEOUT_MS, DEFAULT_TOKENS, HTTP_METHODS2 as HTTP_METHODS, HyperliquidApiError, HyperliquidBuilderApprovalError, HyperliquidExchangeClient, HyperliquidGuardError, HyperliquidInfoClient, HyperliquidTermsError, 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, 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, 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 };
|
|
7709
6848
|
//# sourceMappingURL=index.js.map
|
|
7710
6849
|
//# sourceMappingURL=index.js.map
|