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/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 fs4 from 'fs';
5
- import * as path5 from 'path';
6
- import { fileURLToPath, pathToFileURL } from 'url';
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 = path5.join(process.cwd(), "tools");
703
- if (!fs4.existsSync(toolsDir)) {
699
+ const toolsDir = path.join(process.cwd(), "tools");
700
+ if (!fs.existsSync(toolsDir)) {
704
701
  return tools;
705
702
  }
706
- const files = fs4.readdirSync(toolsDir);
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 = path5.join(toolsDir, file);
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 = path5.join(process.cwd(), "metadata.json");
776
- if (!fs4.existsSync(metadataPath)) {
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 = fs4.readFileSync(metadataPath, "utf8");
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 path5.resolve(value);
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
- function normalizePrivateKey(raw) {
1303
- const trimmed = raw.trim();
1304
- const withPrefix = trimmed.startsWith("0x") ? trimmed : `0x${trimmed}`;
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: createNonceSource()
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: createNonceSource2()
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 path7 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
1736
- const url = `${baseUrl}${path7}`;
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 path7 = mode === "backtest" ? "/apps/backtests/tx" : "/apps/positions/tx";
1777
- const url = new URL(`${baseUrl}${path7}`);
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 = options.nonce ?? options.walletNonceProvider?.() ?? options.wallet.nonceSource?.() ?? options.nonceSource?.() ?? Date.now();
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 = options.nonce ?? options.walletNonceProvider?.() ?? options.wallet.nonceSource?.() ?? options.nonceSource?.() ?? Date.now();
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 = options.nonce ?? options.walletNonceProvider?.() ?? options.wallet.nonceSource?.() ?? options.nonceSource?.() ?? Date.now();
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 = options.nonce ?? options.nonceSource?.() ?? Date.now();
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 = nonce ?? Date.now();
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 time = BigInt(Date.now());
4743
- const nonce = Number(time);
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 = nonce ?? Date.now();
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 timestamp2 = args.timestamp.toString();
5113
+ const timestamp = args.timestamp.toString();
5067
5114
  const method = args.method.toUpperCase();
5068
- const path7 = args.path;
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 = `${timestamp2}${method}${path7}${body}`;
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 timestamp2 = args.timestamp ?? Math.floor(Date.now() / 1e3);
5122
+ const timestamp = args.timestamp ?? Math.floor(Date.now() / 1e3);
5076
5123
  const signature = buildHmacSignature({
5077
5124
  secret: args.credentials.secret,
5078
- timestamp: timestamp2,
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: timestamp2.toString(),
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 timestamp2 = args.timestamp ?? Math.floor(Date.now() / 1e3);
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: timestamp2.toString(),
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: timestamp2.toString(),
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((resolve4, reject) => {
6194
- finishedResolve = resolve4;
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, path7) {
6640
+ function buildUrl(baseUrl, path2) {
6424
6641
  const sanitizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
6425
- return `${sanitizedBase}${path7}`;
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, generateMetadata, generateMetadataCommand, generateText, getHyperliquidMaxBuilderFee, getModelConfig, getMyPerformance, getMyTools, getRpcUrl, getX402PaymentContext, isHyperliquidSpotSymbol, isStreamingSupported, isToolCallingSupported, listModels, loadAndValidateTools, 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, resolvePolymarketBaseUrl, resolveRuntimePath, resolveSpotMidCandidates, resolveSpotTokenCandidates, resolveToolset, responseToToolResponse, retrieve, roundHyperliquidPriceToTick, scheduleHyperliquidCancel, sendHyperliquidSpot, setHyperliquidAccountAbstractionMode, setHyperliquidDexAbstraction, setHyperliquidPortfolioMargin, store, streamText, tokens, transferHyperliquidSubAccount, updateHyperliquidIsolatedMargin, updateHyperliquidLeverage, validateCommand, wallet, walletToolkit, withX402Payment, withdrawFromHyperliquid };
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