@general-liquidity/gordon-cli 0.75.5 → 0.75.7

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.
Files changed (2) hide show
  1. package/dist/gordon.js +1607 -775
  2. package/package.json +1 -1
package/dist/gordon.js CHANGED
@@ -195785,6 +195785,9 @@ var init_hyperliquid3 = __esm(() => {
195785
195785
  });
195786
195786
 
195787
195787
  // src/infra/uniswap/types.ts
195788
+ function isUniswapXRouting(routing) {
195789
+ return ["DUTCH_V2", "DUTCH_V3", "DUTCH_LIMIT", "PRIORITY"].includes(routing);
195790
+ }
195788
195791
  var NATIVE_TOKEN = "0x0000000000000000000000000000000000000000", GAS_BUFFER_PERCENT = 0.15, WRAPPED_NATIVE, USDC_ADDRESSES, SUPPORTED_CHAIN_IDS, CHAIN_NAMES;
195789
195792
  var init_types10 = __esm(() => {
195790
195793
  WRAPPED_NATIVE = {
@@ -195805,13 +195808,14 @@ var init_types10 = __esm(() => {
195805
195808
  42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
195806
195809
  43114: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"
195807
195810
  };
195808
- SUPPORTED_CHAIN_IDS = [1, 10, 56, 130, 137, 196, 324, 480, 1868, 8453, 42161, 42220, 43114, 81457, 7777777];
195811
+ SUPPORTED_CHAIN_IDS = [1, 10, 56, 130, 137, 143, 196, 324, 480, 1868, 8453, 42161, 42220, 43114, 81457, 7777777];
195809
195812
  CHAIN_NAMES = {
195810
195813
  1: "Ethereum",
195811
195814
  10: "Optimism",
195812
195815
  56: "BNB Chain",
195813
195816
  130: "Unichain",
195814
195817
  137: "Polygon",
195818
+ 143: "Monad",
195815
195819
  196: "X Layer",
195816
195820
  324: "zkSync",
195817
195821
  480: "World Chain",
@@ -197148,11 +197152,16 @@ class UniswapAdapter {
197148
197152
  this.localOrders.set(orderId, order);
197149
197153
  const meta3 = {
197150
197154
  _unsignedTx: swapTx.swap,
197151
- _quoteTimestamp: quoteTimestamp
197155
+ _quoteTimestamp: quoteTimestamp,
197156
+ _routing: quote.routing
197152
197157
  };
197153
197158
  if (approvalResult.approval) {
197154
197159
  meta3._approvalTx = approvalResult.approval;
197155
197160
  }
197161
+ if (isUniswapXRouting(quote.routing) && quote.permitData) {
197162
+ meta3._permitData = quote.permitData;
197163
+ meta3._isUniswapX = true;
197164
+ }
197156
197165
  if (swapTx.txFailureReasons?.length) {
197157
197166
  meta3._txFailureReasons = swapTx.txFailureReasons;
197158
197167
  }
@@ -287117,26 +287126,52 @@ async function dexScreenerFetch(path6) {
287117
287126
  }
287118
287127
  return await res.json();
287119
287128
  }
287120
- async function getBasePairs(tokenAddress) {
287121
- const data = await dexScreenerFetch(`/token-pairs/v1/base/${tokenAddress}`);
287122
- return (data.pairs ?? []).filter((p) => p.chainId === "base");
287129
+ async function getDexPairs(chain, tokenAddress) {
287130
+ const data = await dexScreenerFetch(`/token-pairs/v1/${chain}/${tokenAddress}`);
287131
+ return (data.pairs ?? []).filter((p) => p.chainId === chain);
287123
287132
  }
287124
- async function searchBasePairs(query) {
287133
+ async function searchDexPairs(query, chain, dex) {
287125
287134
  const data = await dexScreenerFetch(`/latest/dex/search?q=${encodeURIComponent(query)}`);
287126
- return (data.pairs ?? []).filter((p) => p.chainId === "base");
287127
- }
287128
- async function getBaseTokensBatch(addresses) {
287135
+ let pairs = data.pairs ?? [];
287136
+ if (chain)
287137
+ pairs = pairs.filter((p) => p.chainId === chain);
287138
+ if (dex)
287139
+ pairs = pairs.filter((p) => p.dexId === dex);
287140
+ return pairs;
287141
+ }
287142
+ async function getDexTokensBatch(chain, addresses) {
287129
287143
  if (addresses.length === 0)
287130
287144
  return [];
287131
287145
  const batch = addresses.slice(0, 30).join(",");
287132
- const data = await dexScreenerFetch(`/tokens/v1/base/${batch}`);
287133
- return (data.pairs ?? []).filter((p) => p.chainId === "base");
287146
+ const data = await dexScreenerFetch(`/tokens/v1/${chain}/${batch}`);
287147
+ return (data.pairs ?? []).filter((p) => p.chainId === chain);
287134
287148
  }
287135
- async function getNewBaseTokens() {
287149
+ async function getNewTokens(chain) {
287136
287150
  const data = await dexScreenerFetch(`/token-profiles/latest/v1`);
287137
- return (data ?? []).filter((t2) => t2.chainId === "base");
287151
+ if (!chain)
287152
+ return data ?? [];
287153
+ return (data ?? []).filter((t2) => t2.chainId === chain);
287154
+ }
287155
+ async function getBoostedTokens(chain) {
287156
+ const data = await dexScreenerFetch(`/token-boosts/top/v1`);
287157
+ if (!chain)
287158
+ return data ?? [];
287159
+ return (data ?? []).filter((t2) => t2.chainId === chain);
287160
+ }
287161
+ async function getBasePairs(tokenAddress) {
287162
+ return getDexPairs("base", tokenAddress);
287163
+ }
287164
+ async function searchBasePairs(query) {
287165
+ return searchDexPairs(query, "base");
287166
+ }
287167
+ async function getBaseTokensBatch(addresses) {
287168
+ return getDexTokensBatch("base", addresses);
287169
+ }
287170
+ async function getNewBaseTokens() {
287171
+ return getNewTokens("base");
287138
287172
  }
287139
287173
  var DEXSCREENER_BASE = "https://api.dexscreener.com";
287174
+ var init_dexscreener = () => {};
287140
287175
 
287141
287176
  // src/infra/base/signals.ts
287142
287177
  async function detectWhaleTransfers(opts = {}) {
@@ -287247,6 +287282,7 @@ async function detectNewListings(opts = {}) {
287247
287282
  return signals;
287248
287283
  }
287249
287284
  var init_signals = __esm(() => {
287285
+ init_dexscreener();
287250
287286
  init_types14();
287251
287287
  });
287252
287288
 
@@ -287254,6 +287290,7 @@ var init_signals = __esm(() => {
287254
287290
  var init_base4 = __esm(() => {
287255
287291
  init_registry4();
287256
287292
  init_chain2();
287293
+ init_dexscreener();
287257
287294
  init_signals();
287258
287295
  init_types14();
287259
287296
  });
@@ -1121084,6 +1121121,7 @@ var init_base_signals = __esm(() => {
1121084
1121121
  init_tools();
1121085
1121122
  init_zod();
1121086
1121123
  init_signals();
1121124
+ init_dexscreener();
1121087
1121125
  scanBaseWhaleTransfersTool = createTool({
1121088
1121126
  id: "scan_base_whale_transfers",
1121089
1121127
  description: "Scan for large token transfers (whale movements) on Base L2. " + "Detects big USDC, WETH, and other major token movements. " + "Requires BASESCAN_API_KEY. " + "Use when user asks 'any whale activity on Base', 'large transfers', 'who is moving big money on Base'.",
@@ -1121871,6 +1121909,282 @@ var init_uniswap_data = __esm(() => {
1121871
1121909
  };
1121872
1121910
  });
1121873
1121911
 
1121912
+ // src/infra/agents/tools/dex-search.ts
1121913
+ var searchDexPairsTool, getBoostedTokensTool, dexSearchTools;
1121914
+ var init_dex_search = __esm(() => {
1121915
+ init_tools();
1121916
+ init_zod();
1121917
+ init_dexscreener();
1121918
+ searchDexPairsTool = createTool({
1121919
+ id: "search_dex_pairs",
1121920
+ description: "Search for DEX trading pairs across any chain using DexScreener. " + "Works on Ethereum, Base, Arbitrum, Optimism, Polygon, BSC, Avalanche, and more. " + "Filter by chain and/or DEX. No API key needed. " + "Use when user asks about DEX pairs on chains other than Base, or wants to compare " + "pairs across chains. For Base-only queries, prefer get_base_dex_pairs.",
1121921
+ inputSchema: exports_external.object({
1121922
+ query: exports_external.string().describe("Search term: token symbol (e.g., 'UNI'), pair (e.g., 'WETH/USDC'), or token address (0x...)"),
1121923
+ chain: exports_external.string().optional().describe("DexScreener chain ID: 'ethereum', 'base', 'arbitrum', 'optimism', 'polygon', 'bsc', 'avalanche', 'unichain'. Omit for all chains."),
1121924
+ dex: exports_external.string().optional().describe("DEX filter: 'uniswap', 'sushiswap', 'aerodrome', 'curve', etc. Omit for all DEXs.")
1121925
+ }),
1121926
+ outputSchema: exports_external.object({
1121927
+ pairs: exports_external.array(exports_external.object({
1121928
+ chain: exports_external.string(),
1121929
+ pairAddress: exports_external.string(),
1121930
+ dex: exports_external.string(),
1121931
+ baseToken: exports_external.string(),
1121932
+ quoteToken: exports_external.string(),
1121933
+ priceUsd: exports_external.string(),
1121934
+ volumeH24: exports_external.number(),
1121935
+ liquidityUsd: exports_external.number(),
1121936
+ priceChangeH24: exports_external.number(),
1121937
+ marketCap: exports_external.number().nullable(),
1121938
+ url: exports_external.string()
1121939
+ })).optional(),
1121940
+ count: exports_external.number().optional(),
1121941
+ error: exports_external.string().optional()
1121942
+ }),
1121943
+ execute: async ({ query, chain, dex }) => {
1121944
+ try {
1121945
+ const isAddress4 = /^0x[a-fA-F0-9]{40}$/.test(query);
1121946
+ let pairs;
1121947
+ if (isAddress4 && chain) {
1121948
+ pairs = await getDexPairs(chain, query);
1121949
+ if (dex)
1121950
+ pairs = pairs.filter((p) => p.dexId === dex);
1121951
+ } else {
1121952
+ pairs = await searchDexPairs(query, chain, dex);
1121953
+ }
1121954
+ return {
1121955
+ count: pairs.length,
1121956
+ pairs: pairs.slice(0, 25).map((p) => ({
1121957
+ chain: p.chainId,
1121958
+ pairAddress: p.pairAddress,
1121959
+ dex: p.dexId,
1121960
+ baseToken: `${p.baseToken.symbol} (${p.baseToken.address})`,
1121961
+ quoteToken: `${p.quoteToken.symbol} (${p.quoteToken.address})`,
1121962
+ priceUsd: p.priceUsd,
1121963
+ volumeH24: p.volume?.h24 ?? 0,
1121964
+ liquidityUsd: p.liquidity?.usd ?? 0,
1121965
+ priceChangeH24: p.priceChange?.h24 ?? 0,
1121966
+ marketCap: p.marketCap ?? null,
1121967
+ url: p.url
1121968
+ }))
1121969
+ };
1121970
+ } catch (error48) {
1121971
+ return { error: `Failed to search DEX pairs: ${error48.message}` };
1121972
+ }
1121973
+ }
1121974
+ });
1121975
+ getBoostedTokensTool = createTool({
1121976
+ id: "get_boosted_tokens",
1121977
+ description: "Get currently promoted/boosted tokens from DexScreener across all chains. " + "Shows tokens with active promotions \u2014 can indicate marketing spend or community interest. " + "Optionally filter by chain. No API key needed.",
1121978
+ inputSchema: exports_external.object({
1121979
+ chain: exports_external.string().optional().describe("Filter to a specific chain: 'ethereum', 'base', 'arbitrum', etc. Omit for all chains.")
1121980
+ }),
1121981
+ outputSchema: exports_external.object({
1121982
+ tokens: exports_external.array(exports_external.object({
1121983
+ chain: exports_external.string(),
1121984
+ tokenAddress: exports_external.string(),
1121985
+ url: exports_external.string(),
1121986
+ description: exports_external.string().optional()
1121987
+ })).optional(),
1121988
+ count: exports_external.number().optional(),
1121989
+ error: exports_external.string().optional()
1121990
+ }),
1121991
+ execute: async ({ chain }) => {
1121992
+ try {
1121993
+ const tokens = await getBoostedTokens(chain);
1121994
+ return {
1121995
+ count: tokens.length,
1121996
+ tokens: tokens.slice(0, 30).map((t3) => ({
1121997
+ chain: t3.chainId,
1121998
+ tokenAddress: t3.tokenAddress,
1121999
+ url: t3.url,
1122000
+ description: t3.description
1122001
+ }))
1122002
+ };
1122003
+ } catch (error48) {
1122004
+ return { error: `Failed to get boosted tokens: ${error48.message}` };
1122005
+ }
1122006
+ }
1122007
+ });
1122008
+ dexSearchTools = {
1122009
+ search_dex_pairs: searchDexPairsTool,
1122010
+ get_boosted_tokens: getBoostedTokensTool
1122011
+ };
1122012
+ });
1122013
+
1122014
+ // src/infra/defillama/client.ts
1122015
+ async function llamaFetch(base4, path6) {
1122016
+ const url2 = `${base4}${path6}`;
1122017
+ const res = await fetch(url2, { signal: AbortSignal.timeout(15000) });
1122018
+ if (!res.ok) {
1122019
+ throw new Error(`DefiLlama API error: ${res.status} ${res.statusText}`);
1122020
+ }
1122021
+ return await res.json();
1122022
+ }
1122023
+ async function getAllPools() {
1122024
+ const cached2 = poolsCache.get("all");
1122025
+ if (cached2)
1122026
+ return cached2;
1122027
+ const resp = await llamaFetch(YIELDS_BASE, "/pools");
1122028
+ const pools = resp.data ?? [];
1122029
+ poolsCache.set("all", pools);
1122030
+ return pools;
1122031
+ }
1122032
+ async function getUniswapPoolYields(chain, symbol16) {
1122033
+ const allPools = await getAllPools();
1122034
+ let pools = allPools.filter((p) => p.project === "uniswap-v3" || p.project === "uniswap-v4");
1122035
+ if (chain) {
1122036
+ const defillamaChain = DEFILLAMA_CHAINS[chain.toLowerCase()] ?? chain;
1122037
+ pools = pools.filter((p) => p.chain === defillamaChain);
1122038
+ }
1122039
+ if (symbol16) {
1122040
+ const sym = symbol16.toUpperCase();
1122041
+ pools = pools.filter((p) => p.symbol.toUpperCase().includes(sym));
1122042
+ }
1122043
+ pools.sort((a2, b) => b.tvlUsd - a2.tvlUsd);
1122044
+ return pools;
1122045
+ }
1122046
+ async function getTopYieldPools(chain, limit = 20, minTvl = 1e5) {
1122047
+ const allPools = await getAllPools();
1122048
+ let pools = allPools.filter((p) => p.tvlUsd >= minTvl && p.apy > 0);
1122049
+ if (chain) {
1122050
+ const defillamaChain = DEFILLAMA_CHAINS[chain.toLowerCase()] ?? chain;
1122051
+ pools = pools.filter((p) => p.chain === defillamaChain);
1122052
+ }
1122053
+ pools.sort((a2, b) => b.apy - a2.apy);
1122054
+ return pools.slice(0, limit);
1122055
+ }
1122056
+ var YIELDS_BASE = "https://yields.llama.fi", DEFILLAMA_CHAINS, poolsCache, priceCache;
1122057
+ var init_client11 = __esm(() => {
1122058
+ DEFILLAMA_CHAINS = {
1122059
+ ethereum: "Ethereum",
1122060
+ base: "Base",
1122061
+ arbitrum: "Arbitrum",
1122062
+ optimism: "Optimism",
1122063
+ polygon: "Polygon",
1122064
+ bsc: "BSC",
1122065
+ avalanche: "Avalanche",
1122066
+ celo: "Celo",
1122067
+ blast: "Blast",
1122068
+ unichain: "Unichain"
1122069
+ };
1122070
+ poolsCache = new Cache({ defaultTtl: 5 * 60 * 1000 });
1122071
+ priceCache = new Cache({ defaultTtl: 2 * 60 * 1000 });
1122072
+ });
1122073
+
1122074
+ // src/infra/agents/tools/defillama-yields.ts
1122075
+ var getUniswapYieldsTool, getTopYieldsTool, defillamaYieldTools;
1122076
+ var init_defillama_yields = __esm(() => {
1122077
+ init_tools();
1122078
+ init_zod();
1122079
+ init_client11();
1122080
+ getUniswapYieldsTool = createTool({
1122081
+ id: "get_uniswap_pool_yields",
1122082
+ description: "Get current APY, TVL, and volume data for Uniswap V3/V4 pools from DefiLlama. " + "Shows base APY (fees), reward APY, 7d/30d trends, impermanent loss risk, and pool TVL. " + "Use for yield farming analysis, comparing fee tiers, and LP profitability assessment. " + "Supports all chains: Ethereum, Base, Arbitrum, Optimism, Polygon, etc.",
1122083
+ inputSchema: exports_external.object({
1122084
+ chain: exports_external.string().optional().describe("Chain name (e.g., 'ethereum', 'base', 'arbitrum'). Omit for all chains."),
1122085
+ symbol: exports_external.string().optional().describe("Token pair filter (e.g., 'WETH-USDC', 'USDC'). Partial match."),
1122086
+ limit: exports_external.number().min(1).max(50).default(15).describe("Max pools to return")
1122087
+ }),
1122088
+ outputSchema: exports_external.object({
1122089
+ pools: exports_external.array(exports_external.object({
1122090
+ pool: exports_external.string(),
1122091
+ symbol: exports_external.string(),
1122092
+ chain: exports_external.string(),
1122093
+ tvlUsd: exports_external.number(),
1122094
+ apy: exports_external.number(),
1122095
+ apyBase: exports_external.number().nullable(),
1122096
+ apyReward: exports_external.number().nullable(),
1122097
+ apyPct7D: exports_external.number().nullable(),
1122098
+ apyPct30D: exports_external.number().nullable(),
1122099
+ volumeUsd1d: exports_external.number().nullable(),
1122100
+ volumeUsd7d: exports_external.number().nullable(),
1122101
+ ilRisk: exports_external.string(),
1122102
+ stablecoin: exports_external.boolean(),
1122103
+ poolMeta: exports_external.string().nullable()
1122104
+ })).optional(),
1122105
+ count: exports_external.number().optional(),
1122106
+ error: exports_external.string().optional()
1122107
+ }),
1122108
+ execute: async ({ chain, symbol: symbol16, limit }) => {
1122109
+ try {
1122110
+ const pools = await getUniswapPoolYields(chain, symbol16);
1122111
+ return {
1122112
+ count: Math.min(pools.length, limit),
1122113
+ pools: pools.slice(0, limit).map((p) => ({
1122114
+ pool: p.pool,
1122115
+ symbol: p.symbol,
1122116
+ chain: p.chain,
1122117
+ tvlUsd: Math.round(p.tvlUsd),
1122118
+ apy: Math.round(p.apy * 100) / 100,
1122119
+ apyBase: p.apyBase !== null ? Math.round(p.apyBase * 100) / 100 : null,
1122120
+ apyReward: p.apyReward !== null ? Math.round(p.apyReward * 100) / 100 : null,
1122121
+ apyPct7D: p.apyPct7D !== null ? Math.round(p.apyPct7D * 100) / 100 : null,
1122122
+ apyPct30D: p.apyPct30D !== null ? Math.round(p.apyPct30D * 100) / 100 : null,
1122123
+ volumeUsd1d: p.volumeUsd1d !== null ? Math.round(p.volumeUsd1d) : null,
1122124
+ volumeUsd7d: p.volumeUsd7d !== null ? Math.round(p.volumeUsd7d) : null,
1122125
+ ilRisk: p.ilRisk,
1122126
+ stablecoin: p.stablecoin,
1122127
+ poolMeta: p.poolMeta
1122128
+ }))
1122129
+ };
1122130
+ } catch (error48) {
1122131
+ return { error: `Failed to get Uniswap yields: ${error48.message}` };
1122132
+ }
1122133
+ }
1122134
+ });
1122135
+ getTopYieldsTool = createTool({
1122136
+ id: "get_top_defi_yields",
1122137
+ description: "Get the highest-yielding DeFi pools across all protocols from DefiLlama. " + "Includes Uniswap, Aave, Compound, Aerodrome, Curve, and all tracked protocols. " + "Use for finding the best yield opportunities, comparing protocols, and yield farming research.",
1122138
+ inputSchema: exports_external.object({
1122139
+ chain: exports_external.string().optional().describe("Chain name (e.g., 'ethereum', 'base', 'arbitrum'). Omit for all chains."),
1122140
+ limit: exports_external.number().min(1).max(50).default(20).describe("Max pools to return"),
1122141
+ minTvl: exports_external.number().default(1e5).describe("Minimum TVL in USD (default: 100000)")
1122142
+ }),
1122143
+ outputSchema: exports_external.object({
1122144
+ pools: exports_external.array(exports_external.object({
1122145
+ pool: exports_external.string(),
1122146
+ project: exports_external.string(),
1122147
+ symbol: exports_external.string(),
1122148
+ chain: exports_external.string(),
1122149
+ tvlUsd: exports_external.number(),
1122150
+ apy: exports_external.number(),
1122151
+ apyBase: exports_external.number().nullable(),
1122152
+ apyReward: exports_external.number().nullable(),
1122153
+ stablecoin: exports_external.boolean(),
1122154
+ ilRisk: exports_external.string()
1122155
+ })).optional(),
1122156
+ count: exports_external.number().optional(),
1122157
+ error: exports_external.string().optional()
1122158
+ }),
1122159
+ execute: async ({ chain, limit, minTvl }) => {
1122160
+ try {
1122161
+ const pools = await getTopYieldPools(chain, limit, minTvl);
1122162
+ return {
1122163
+ count: pools.length,
1122164
+ pools: pools.map((p) => ({
1122165
+ pool: p.pool,
1122166
+ project: p.project,
1122167
+ symbol: p.symbol,
1122168
+ chain: p.chain,
1122169
+ tvlUsd: Math.round(p.tvlUsd),
1122170
+ apy: Math.round(p.apy * 100) / 100,
1122171
+ apyBase: p.apyBase !== null ? Math.round(p.apyBase * 100) / 100 : null,
1122172
+ apyReward: p.apyReward !== null ? Math.round(p.apyReward * 100) / 100 : null,
1122173
+ stablecoin: p.stablecoin,
1122174
+ ilRisk: p.ilRisk
1122175
+ }))
1122176
+ };
1122177
+ } catch (error48) {
1122178
+ return { error: `Failed to get top yields: ${error48.message}` };
1122179
+ }
1122180
+ }
1122181
+ });
1122182
+ defillamaYieldTools = {
1122183
+ get_uniswap_pool_yields: getUniswapYieldsTool,
1122184
+ get_top_defi_yields: getTopYieldsTool
1122185
+ };
1122186
+ });
1122187
+
1121874
1122188
  // src/infra/agents/tools/position-tracking.ts
1121875
1122189
  async function getManager() {
1121876
1122190
  return getPositionManager(getEventBus());
@@ -1128231,6 +1128545,8 @@ var init_tools3 = __esm(async () => {
1128231
1128545
  init_base_signals();
1128232
1128546
  init_base_indexers();
1128233
1128547
  init_uniswap_data();
1128548
+ init_dex_search();
1128549
+ init_defillama_yields();
1128234
1128550
  init_position_tracking();
1128235
1128551
  init_risk_gate();
1128236
1128552
  init_memory_tools();
@@ -1128283,6 +1128599,8 @@ var init_tools3 = __esm(async () => {
1128283
1128599
  init_base_signals();
1128284
1128600
  init_base_indexers();
1128285
1128601
  init_uniswap_data();
1128602
+ init_dex_search();
1128603
+ init_defillama_yields();
1128286
1128604
  init_position_tracking();
1128287
1128605
  init_risk_gate();
1128288
1128606
  init_memory_tools();
@@ -1128339,6 +1128657,8 @@ var init_tools3 = __esm(async () => {
1128339
1128657
  ...baseSignalTools,
1128340
1128658
  ...baseIndexerTools,
1128341
1128659
  ...uniswapDataTools,
1128660
+ ...dexSearchTools,
1128661
+ ...defillamaYieldTools,
1128342
1128662
  ...multiModalChartTools,
1128343
1128663
  ...evalTools,
1128344
1128664
  ...positionTrackingTools,
@@ -1128386,6 +1128706,8 @@ var init_tools3 = __esm(async () => {
1128386
1128706
  baseSignals: Object.keys(baseSignalTools).length,
1128387
1128707
  baseIndexers: Object.keys(baseIndexerTools).length,
1128388
1128708
  uniswapData: Object.keys(uniswapDataTools).length,
1128709
+ dexSearch: Object.keys(dexSearchTools).length,
1128710
+ defillamaYields: Object.keys(defillamaYieldTools).length,
1128389
1128711
  multiModalCharts: Object.keys(multiModalChartTools).length,
1128390
1128712
  evals: Object.keys(evalTools).length,
1128391
1128713
  positionTracking: Object.keys(positionTrackingTools).length,
@@ -1142027,7 +1142349,7 @@ class ExperimentalClientTasks {
1142027
1142349
  return this._client.requestStream(request, resultSchema, options);
1142028
1142350
  }
1142029
1142351
  }
1142030
- var init_client11 = __esm(() => {
1142352
+ var init_client12 = __esm(() => {
1142031
1142353
  init_types19();
1142032
1142354
  });
1142033
1142355
 
@@ -1142109,12 +1142431,12 @@ function getSupportedElicitationModes(capabilities) {
1142109
1142431
  return { supportsFormMode, supportsUrlMode };
1142110
1142432
  }
1142111
1142433
  var Client2;
1142112
- var init_client12 = __esm(() => {
1142434
+ var init_client13 = __esm(() => {
1142113
1142435
  init_protocol3();
1142114
1142436
  init_types19();
1142115
1142437
  init_ajv_provider();
1142116
1142438
  init_zod_compat();
1142117
- init_client11();
1142439
+ init_client12();
1142118
1142440
  Client2 = class Client2 extends Protocol {
1142119
1142441
  constructor(_clientInfo, options) {
1142120
1142442
  super(options);
@@ -1149993,7 +1150315,7 @@ var init_dist18 = __esm(() => {
1149993
1150315
  init_error();
1149994
1150316
  init_tools();
1149995
1150317
  init_utils();
1149996
- init_client12();
1150318
+ init_client13();
1149997
1150319
  init_sse();
1149998
1150320
  init_stdio2();
1149999
1150321
  init_streamableHttp();
@@ -1151346,6 +1151668,122 @@ var init_installer = __esm(() => {
1151346
1151668
  pluginInstaller = new PluginInstaller;
1151347
1151669
  });
1151348
1151670
 
1151671
+ // src/infra/skills/manager.ts
1151672
+ import * as fs10 from "fs/promises";
1151673
+ import * as path8 from "path";
1151674
+ async function loadSkillManifest(pluginId) {
1151675
+ const skillPath = path8.join(pluginInstaller.getPluginsDir(), pluginId, "skill.json");
1151676
+ try {
1151677
+ const content = await fs10.readFile(skillPath, "utf-8");
1151678
+ return JSON.parse(content);
1151679
+ } catch {
1151680
+ return null;
1151681
+ }
1151682
+ }
1151683
+ function buildDefaultSkillManifest(pluginId) {
1151684
+ return {
1151685
+ pluginId,
1151686
+ defaultAgent: "Gordon",
1151687
+ alsoOnGordon: true
1151688
+ };
1151689
+ }
1151690
+ function rebuildRoutingTables() {
1151691
+ const mcpTools = getMCPTools();
1151692
+ const mcpToolsByServer = getMCPToolsByServer();
1151693
+ _dynamicToolAgentMap = {};
1151694
+ _toolsByAgent = {};
1151695
+ for (const skill of _resolvedSkills) {
1151696
+ if (!skill.enabled)
1151697
+ continue;
1151698
+ const serverToolNames = mcpToolsByServer[skill.pluginId] ?? [];
1151699
+ const perToolMap = new Map;
1151700
+ if (skill.skillManifest.toolAgentMap) {
1151701
+ for (const mapping of skill.skillManifest.toolAgentMap) {
1151702
+ perToolMap.set(mapping.toolName, mapping.agent);
1151703
+ }
1151704
+ }
1151705
+ let toolCount = 0;
1151706
+ for (const namespacedToolName of serverToolNames) {
1151707
+ const underscoreIdx = namespacedToolName.indexOf("_");
1151708
+ const bareToolName = underscoreIdx > 0 ? namespacedToolName.substring(underscoreIdx + 1) : namespacedToolName;
1151709
+ const agent = perToolMap.get(bareToolName) ?? skill.skillManifest.defaultAgent;
1151710
+ if (agent !== "Gordon") {
1151711
+ _dynamicToolAgentMap[namespacedToolName] = agent;
1151712
+ }
1151713
+ const tool3 = mcpTools[namespacedToolName];
1151714
+ if (tool3) {
1151715
+ toolCount++;
1151716
+ if (!_toolsByAgent[agent])
1151717
+ _toolsByAgent[agent] = {};
1151718
+ _toolsByAgent[agent][namespacedToolName] = tool3;
1151719
+ if (skill.skillManifest.alsoOnGordon && agent !== "Gordon") {
1151720
+ if (!_toolsByAgent["Gordon"])
1151721
+ _toolsByAgent["Gordon"] = {};
1151722
+ _toolsByAgent["Gordon"][namespacedToolName] = tool3;
1151723
+ }
1151724
+ }
1151725
+ }
1151726
+ skill.toolCount = toolCount;
1151727
+ }
1151728
+ }
1151729
+ async function initSkills() {
1151730
+ if (_initialized2)
1151731
+ return;
1151732
+ await pluginInstaller.initialize();
1151733
+ const installed = pluginInstaller.getInstalled().filter((p) => p.enabled);
1151734
+ _resolvedSkills = [];
1151735
+ for (const plugin of installed) {
1151736
+ const skillManifest = await loadSkillManifest(plugin.id) ?? buildDefaultSkillManifest(plugin.id);
1151737
+ _resolvedSkills.push({
1151738
+ pluginId: plugin.id,
1151739
+ skillManifest,
1151740
+ enabled: plugin.enabled,
1151741
+ toolCount: 0
1151742
+ });
1151743
+ }
1151744
+ rebuildRoutingTables();
1151745
+ _initialized2 = true;
1151746
+ const skillCount = _resolvedSkills.length;
1151747
+ const routedCount = Object.keys(_dynamicToolAgentMap).length;
1151748
+ if (skillCount > 0) {
1151749
+ console.log(`[Skills] Loaded ${skillCount} skill(s), ${routedCount} tool(s) routed to sub-agents`);
1151750
+ }
1151751
+ }
1151752
+ function getDynamicToolAgentMap() {
1151753
+ return _dynamicToolAgentMap;
1151754
+ }
1151755
+ function getSkillToolsForAgent(agentName) {
1151756
+ return { ..._toolsByAgent[agentName] ?? {} };
1151757
+ }
1151758
+ async function reloadSkills() {
1151759
+ await reloadMCPTools();
1151760
+ _initialized2 = false;
1151761
+ await initSkills();
1151762
+ resetAgents();
1151763
+ console.log("[Skills] Reloaded \u2014 agents will reconstruct on next access");
1151764
+ }
1151765
+ function getResolvedSkills() {
1151766
+ return [..._resolvedSkills];
1151767
+ }
1151768
+ function isSkillsInitialized() {
1151769
+ return _initialized2;
1151770
+ }
1151771
+ async function writeSkillManifest(manifest) {
1151772
+ const skillPath = path8.join(pluginInstaller.getPluginsDir(), manifest.pluginId, "skill.json");
1151773
+ await fs10.writeFile(skillPath, JSON.stringify(manifest, null, 2));
1151774
+ }
1151775
+ var _resolvedSkills, _dynamicToolAgentMap, _toolsByAgent, _initialized2 = false;
1151776
+ var init_manager4 = __esm(async () => {
1151777
+ init_installer();
1151778
+ await __promiseAll([
1151779
+ init_client14(),
1151780
+ init_agents()
1151781
+ ]);
1151782
+ _resolvedSkills = [];
1151783
+ _dynamicToolAgentMap = {};
1151784
+ _toolsByAgent = {};
1151785
+ });
1151786
+
1151349
1151787
  // src/infra/mcp/credentials.ts
1151350
1151788
  class MCPCredentialManager {
1151351
1151789
  credentials = new Map;
@@ -1151528,6 +1151966,21 @@ async function reloadMCPTools() {
1151528
1151966
  function getMCPTools() {
1151529
1151967
  return _mcpTools ?? {};
1151530
1151968
  }
1151969
+ function getMCPToolsByServer() {
1151970
+ if (!_mcpTools)
1151971
+ return {};
1151972
+ const byServer = {};
1151973
+ for (const toolName of Object.keys(_mcpTools)) {
1151974
+ const underscoreIdx = toolName.indexOf("_");
1151975
+ if (underscoreIdx > 0) {
1151976
+ const serverName = toolName.substring(0, underscoreIdx);
1151977
+ if (!byServer[serverName])
1151978
+ byServer[serverName] = [];
1151979
+ byServer[serverName].push(toolName);
1151980
+ }
1151981
+ }
1151982
+ return byServer;
1151983
+ }
1151531
1151984
  async function disconnectMCP() {
1151532
1151985
  if (_mcpClient) {
1151533
1151986
  try {
@@ -1151549,8 +1152002,12 @@ function enableMCPHotReload(intervalMs = 5000) {
1151549
1152002
  const installed = pluginInstaller.getInstalled().filter((p) => p.enabled);
1151550
1152003
  const fingerprint = installed.map((p) => `${p.id}:${p.enabled ? "1" : "0"}:${p.version ?? "0"}`).sort().join("|");
1151551
1152004
  if (_lastPluginFingerprint !== null && fingerprint !== _lastPluginFingerprint) {
1151552
- console.log("[MCP] Plugin change detected, hot-reloading tools...");
1151553
- await reloadMCPTools();
1152005
+ console.log("[MCP] Plugin change detected, hot-reloading...");
1152006
+ if (isSkillsInitialized()) {
1152007
+ await reloadSkills();
1152008
+ } else {
1152009
+ await reloadMCPTools();
1152010
+ }
1151554
1152011
  }
1151555
1152012
  _lastPluginFingerprint = fingerprint;
1151556
1152013
  } catch (error48) {
@@ -1151565,10 +1152022,11 @@ function disableMCPHotReload() {
1151565
1152022
  }
1151566
1152023
  }
1151567
1152024
  var _mcpClient = null, _mcpTools = null, _initPromise = null, _hotReloadTimer = null, _lastPluginFingerprint = null;
1151568
- var init_client13 = __esm(() => {
1152025
+ var init_client14 = __esm(async () => {
1151569
1152026
  init_dist18();
1151570
1152027
  init_installer();
1151571
1152028
  init_credentials();
1152029
+ await init_manager4();
1151572
1152030
  });
1151573
1152031
 
1151574
1152032
  // src/infra/agents/agents.ts
@@ -1151659,12 +1152117,15 @@ function getScannerAgent() {
1151659
1152117
  defillama_search_protocols: instrumentedAgentKitDefiTools.defillama_search_protocols,
1151660
1152118
  indexer_top_pools: instrumentedBaseIndexerTools.indexer_top_pools,
1151661
1152119
  indexer_aerodrome_pools: instrumentedBaseIndexerTools.indexer_aerodrome_pools,
1152120
+ search_dex_pairs: instrumentedDexSearchTools.search_dex_pairs,
1152121
+ get_boosted_tokens: instrumentedDexSearchTools.get_boosted_tokens,
1151662
1152122
  get_uniswap_protocol_overview: instrumentedUniswapDataTools.get_uniswap_protocol_overview,
1151663
1152123
  get_liquidity_events: instrumentedUniswapDataTools.get_liquidity_events,
1151664
1152124
  report_setup: instrumentedPositionTrackingTools.report_setup,
1151665
1152125
  ...instrumentedMemoryTools,
1151666
1152126
  ...instrumentedPlaybookTools,
1151667
- ...instrumentedRegimeTools
1152127
+ ...instrumentedRegimeTools,
1152128
+ ...getSkillToolsForAgent("Scanner")
1151668
1152129
  },
1151669
1152130
  memory: createSubAgentMemory(),
1151670
1152131
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151709,6 +1152170,9 @@ function getAnalystAgent() {
1151709
1152170
  get_pool_flash_events: instrumentedUniswapDataTools.get_pool_flash_events,
1151710
1152171
  get_fee_collections: instrumentedUniswapDataTools.get_fee_collections,
1151711
1152172
  get_uniswap_protocol_overview: instrumentedUniswapDataTools.get_uniswap_protocol_overview,
1152173
+ get_uniswap_pool_yields: instrumentedDefillamaYieldTools.get_uniswap_pool_yields,
1152174
+ get_top_defi_yields: instrumentedDefillamaYieldTools.get_top_defi_yields,
1152175
+ search_dex_pairs: instrumentedDexSearchTools.search_dex_pairs,
1151712
1152176
  track_base_wallet: instrumentedBaseSignalTools.track_base_wallet,
1151713
1152177
  get_base_token_holders: instrumentedBaseSignalTools.get_base_token_holders,
1151714
1152178
  get_base_dex_pairs: instrumentedBaseSignalTools.get_base_dex_pairs,
@@ -1151721,7 +1152185,8 @@ function getAnalystAgent() {
1151721
1152185
  ...instrumentedPlaybookTools,
1151722
1152186
  detect_market_regime: instrumentedRegimeTools.detect_market_regime,
1151723
1152187
  get_regime_history: instrumentedRegimeTools.get_regime_history,
1151724
- ...instrumentedProtocolTools
1152188
+ ...instrumentedProtocolTools,
1152189
+ ...getSkillToolsForAgent("Analyst")
1151725
1152190
  },
1151726
1152191
  memory: createSubAgentMemory(),
1151727
1152192
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151767,7 +1152232,8 @@ function getPlannerAgent() {
1151767
1152232
  stop_strategy: instrumentedRuntimeTools.stop_strategy,
1151768
1152233
  rebalance_portfolio: instrumentedRuntimeTools.rebalance_portfolio,
1151769
1152234
  simulate_order_bundle: instrumentedAdvancedTools.simulate_order_bundle,
1151770
- generate_circuit_breaker_proof: instrumentedAdvancedTools.generate_circuit_breaker_proof
1152235
+ generate_circuit_breaker_proof: instrumentedAdvancedTools.generate_circuit_breaker_proof,
1152236
+ ...getSkillToolsForAgent("Planner")
1151771
1152237
  },
1151772
1152238
  memory: createSubAgentMemory(),
1151773
1152239
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151818,7 +1152284,8 @@ function getExecutorAgent() {
1151818
1152284
  search_memory: instrumentedMemoryTools.search_memory,
1151819
1152285
  approve_strategy_trade: instrumentedRuntimeTools.approve_strategy_trade,
1151820
1152286
  simulate_order_bundle: instrumentedAdvancedTools.simulate_order_bundle,
1151821
- verify_circuit_breaker_proof: instrumentedAdvancedTools.verify_circuit_breaker_proof
1152287
+ verify_circuit_breaker_proof: instrumentedAdvancedTools.verify_circuit_breaker_proof,
1152288
+ ...getSkillToolsForAgent("Executor")
1151822
1152289
  },
1151823
1152290
  memory: createSubAgentMemory(),
1151824
1152291
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151866,7 +1152333,8 @@ function getMonitorAgent() {
1151866
1152333
  get_portfolio_state: instrumentedRuntimeTools.get_portfolio_state,
1151867
1152334
  check_portfolio_health: instrumentedRuntimeTools.check_portfolio_health,
1151868
1152335
  generate_circuit_breaker_proof: instrumentedAdvancedTools.generate_circuit_breaker_proof,
1151869
- query_regime_scoped_memory: instrumentedAdvancedTools.query_regime_scoped_memory
1152336
+ query_regime_scoped_memory: instrumentedAdvancedTools.query_regime_scoped_memory,
1152337
+ ...getSkillToolsForAgent("Monitor")
1151870
1152338
  },
1151871
1152339
  memory: createSubAgentMemory(),
1151872
1152340
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151892,7 +1152360,8 @@ function getTeacherAgent() {
1151892
1152360
  ...instrumentedMemoryTools,
1151893
1152361
  ...instrumentedPlaybookTools,
1151894
1152362
  query_audit_trail: instrumentedAuditTools.query_audit_trail,
1151895
- get_decision_path: instrumentedAuditTools.get_decision_path
1152363
+ get_decision_path: instrumentedAuditTools.get_decision_path,
1152364
+ ...getSkillToolsForAgent("Teacher")
1151896
1152365
  },
1151897
1152366
  memory: createSubAgentMemory(),
1151898
1152367
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151922,7 +1152391,8 @@ function getBacktesterAgent() {
1151922
1152391
  search_memory: instrumentedMemoryTools.search_memory,
1151923
1152392
  get_lessons: instrumentedMemoryTools.get_lessons,
1151924
1152393
  ...instrumentedPlaybookTools,
1151925
- ...instrumentedPlaybookBacktestTools
1152394
+ ...instrumentedPlaybookBacktestTools,
1152395
+ ...getSkillToolsForAgent("Backtester")
1151926
1152396
  },
1151927
1152397
  memory: createSubAgentMemory(),
1151928
1152398
  inputProcessors: [new TokenLimiterProcessor({ limit: 32000 })]
@@ -1151953,7 +1152423,8 @@ function getGordonAgent() {
1151953
1152423
  ...instrumentedSystemTools,
1151954
1152424
  ...instrumentedSchedulerTools,
1151955
1152425
  ...instrumentedAutonomousTools,
1151956
- ...getMCPTools()
1152426
+ ...getMCPTools(),
1152427
+ ...getSkillToolsForAgent("Gordon")
1151957
1152428
  },
1151958
1152429
  memory: createMemory(),
1151959
1152430
  inputProcessors: [new TokenLimiterProcessor({ limit: 64000 })]
@@ -1151965,7 +1152436,7 @@ function resetAgents() {
1151965
1152436
  _agents = {};
1151966
1152437
  _subAgentMemory = null;
1151967
1152438
  }
1151968
- var DEFAULT_MEMORY_CONFIG, _memoryConfig, instrumentedIndicatorTools, instrumentedExplainTools, instrumentedMarketTools, instrumentedPositionTools, instrumentedSchedulerTools, instrumentedSystemTools, instrumentedEarnTools, instrumentedChartTools, instrumentedOrderbookTools, instrumentedWalletTools, instrumentedDiscoveryTools, instrumentedHistoryTools, instrumentedAccountTools, instrumentedTradingTools, instrumentedMarketAnalysisTools, instrumentedLiquidationIntelligenceTools, instrumentedRiskManagementTools, instrumentedStrategyTools, instrumentedMetricsTools, instrumentedCompositionTools, instrumentedBacktestTools, instrumentedSharedContextTools, instrumentedParallelAnalysisTools, instrumentedStrategyGenerationTools, instrumentedMultiModalChartTools, instrumentedMarketDataTools, instrumentedPairAnalysisTools, instrumentedAutonomousTools, instrumentedBaseOnchainTools, instrumentedAgentKitOnchainTools, instrumentedAgentKitDefiTools, instrumentedBaseSignalTools, instrumentedBaseIndexerTools, instrumentedUniswapDataTools, instrumentedEvalTools, instrumentedPositionTrackingTools, instrumentedMemoryTools, instrumentedPlaybookTools, instrumentedPlaybookBacktestTools, instrumentedAuditTools, instrumentedProtocolTools, instrumentedRegimeTools, instrumentedRuntimeTools, instrumentedAdvancedTools, instrumentedCheckRiskTool, WORKING_MEMORY_TEMPLATE = `
1152439
+ var DEFAULT_MEMORY_CONFIG, _memoryConfig, instrumentedIndicatorTools, instrumentedExplainTools, instrumentedMarketTools, instrumentedPositionTools, instrumentedSchedulerTools, instrumentedSystemTools, instrumentedEarnTools, instrumentedChartTools, instrumentedOrderbookTools, instrumentedWalletTools, instrumentedDiscoveryTools, instrumentedHistoryTools, instrumentedAccountTools, instrumentedTradingTools, instrumentedMarketAnalysisTools, instrumentedLiquidationIntelligenceTools, instrumentedRiskManagementTools, instrumentedStrategyTools, instrumentedMetricsTools, instrumentedCompositionTools, instrumentedBacktestTools, instrumentedSharedContextTools, instrumentedParallelAnalysisTools, instrumentedStrategyGenerationTools, instrumentedMultiModalChartTools, instrumentedMarketDataTools, instrumentedPairAnalysisTools, instrumentedAutonomousTools, instrumentedBaseOnchainTools, instrumentedAgentKitOnchainTools, instrumentedAgentKitDefiTools, instrumentedBaseSignalTools, instrumentedBaseIndexerTools, instrumentedUniswapDataTools, instrumentedDexSearchTools, instrumentedDefillamaYieldTools, instrumentedEvalTools, instrumentedPositionTrackingTools, instrumentedMemoryTools, instrumentedPlaybookTools, instrumentedPlaybookBacktestTools, instrumentedAuditTools, instrumentedProtocolTools, instrumentedRegimeTools, instrumentedRuntimeTools, instrumentedAdvancedTools, instrumentedCheckRiskTool, WORKING_MEMORY_TEMPLATE = `
1151969
1152440
  # Trader Profile
1151970
1152441
 
1151971
1152442
  ## Personal Info
@@ -1152571,8 +1153042,11 @@ var init_agents = __esm(async () => {
1152571
1153042
  init_registry2();
1152572
1153043
  init_shared_context();
1152573
1153044
  init_evals2();
1152574
- init_client13();
1152575
- await init_tools3();
1153045
+ await __promiseAll([
1153046
+ init_tools3(),
1153047
+ init_client14(),
1153048
+ init_manager4()
1153049
+ ]);
1152576
1153050
  DEFAULT_MEMORY_CONFIG = {
1152577
1153051
  lastMessages: 20,
1152578
1153052
  maxSessionDurationHours: 24,
@@ -1152613,6 +1153087,8 @@ var init_agents = __esm(async () => {
1152613
1153087
  instrumentedBaseSignalTools = withToolsMetrics(baseSignalTools);
1152614
1153088
  instrumentedBaseIndexerTools = withToolsMetrics(baseIndexerTools);
1152615
1153089
  instrumentedUniswapDataTools = withToolsMetrics(uniswapDataTools);
1153090
+ instrumentedDexSearchTools = withToolsMetrics(dexSearchTools);
1153091
+ instrumentedDefillamaYieldTools = withToolsMetrics(defillamaYieldTools);
1152616
1153092
  instrumentedEvalTools = withToolsMetrics(evalTools);
1152617
1153093
  instrumentedPositionTrackingTools = withToolsMetrics(positionTrackingTools);
1152618
1153094
  instrumentedMemoryTools = withToolsMetrics(memoryTools);
@@ -1153387,6 +1153863,9 @@ function getSummarizationStats(context, messages) {
1153387
1153863
  };
1153388
1153864
  }
1153389
1153865
  function getAgentForTool(toolName) {
1153866
+ const dynamicAgent = getDynamicToolAgentMap()[toolName];
1153867
+ if (dynamicAgent)
1153868
+ return dynamicAgent;
1153390
1153869
  const agent = TOOL_AGENT_MAP[toolName];
1153391
1153870
  if (!agent) {
1153392
1153871
  logger103.debug("Unmapped tool called, staying with current agent", { toolName });
@@ -1154224,7 +1154703,10 @@ var init_orchestrator = __esm(async () => {
1154224
1154703
  init_streamWriter();
1154225
1154704
  init_parallel();
1154226
1154705
  init_memory3();
1154227
- await init_agents();
1154706
+ await __promiseAll([
1154707
+ init_agents(),
1154708
+ init_manager4()
1154709
+ ]);
1154228
1154710
  DEFAULT_FALLBACK_CHAIN = {
1154229
1154711
  Analyst: {
1154230
1154712
  primaryAgent: "Analyst",
@@ -1154455,6 +1154937,10 @@ var init_orchestrator = __esm(async () => {
1154455
1154937
  get_lp_positions: "Monitor",
1154456
1154938
  get_uniswap_protocol_overview: "Scanner",
1154457
1154939
  get_fee_collections: "Monitor",
1154940
+ search_dex_pairs: "Scanner",
1154941
+ get_boosted_tokens: "Scanner",
1154942
+ get_uniswap_pool_yields: "Analyst",
1154943
+ get_top_defi_yields: "Analyst",
1154458
1154944
  scan_base_whale_transfers: "Scanner",
1154459
1154945
  scan_base_volume_spikes: "Scanner",
1154460
1154946
  scan_base_new_tokens: "Scanner",
@@ -1154706,25 +1155192,25 @@ var exports_scaffold = {};
1154706
1155192
  __export(exports_scaffold, {
1154707
1155193
  scaffoldProject: () => scaffoldProject
1154708
1155194
  });
1154709
- import { mkdir as mkdir12, writeFile as writeFile5 } from "fs/promises";
1154710
- import { join as join20 } from "path";
1155195
+ import { mkdir as mkdir12, writeFile as writeFile6 } from "fs/promises";
1155196
+ import { join as join21 } from "path";
1154711
1155197
  function applyTokens(content, options) {
1154712
1155198
  const runCmd = options.packageManager === "bun" ? "bun run" : "npx tsx";
1154713
1155199
  return content.replace(/\{\{PROJECT_NAME\}\}/g, options.name).replace(/\{\{RUN_CMD\}\}/g, runCmd);
1154714
1155200
  }
1154715
1155201
  async function scaffoldProject(targetDir, options) {
1154716
- const srcDir = join20(targetDir, "src");
1155202
+ const srcDir = join21(targetDir, "src");
1154717
1155203
  await mkdir12(srcDir, { recursive: true });
1154718
1155204
  const sourceTemplate = options.template === "agent" ? AGENT_TEMPLATE : STRATEGY_TEMPLATE;
1154719
1155205
  const files = [
1154720
- { path: join20(srcDir, "index.ts"), content: applyTokens(sourceTemplate, options) },
1154721
- { path: join20(targetDir, "package.json"), content: applyTokens(PACKAGE_JSON_TEMPLATE, options) },
1154722
- { path: join20(targetDir, "tsconfig.json"), content: applyTokens(TSCONFIG_TEMPLATE, options) },
1154723
- { path: join20(targetDir, ".env.example"), content: applyTokens(ENV_EXAMPLE_TEMPLATE, options) }
1155206
+ { path: join21(srcDir, "index.ts"), content: applyTokens(sourceTemplate, options) },
1155207
+ { path: join21(targetDir, "package.json"), content: applyTokens(PACKAGE_JSON_TEMPLATE, options) },
1155208
+ { path: join21(targetDir, "tsconfig.json"), content: applyTokens(TSCONFIG_TEMPLATE, options) },
1155209
+ { path: join21(targetDir, ".env.example"), content: applyTokens(ENV_EXAMPLE_TEMPLATE, options) }
1154724
1155210
  ];
1154725
1155211
  const created = [];
1154726
1155212
  for (const file2 of files) {
1154727
- await writeFile5(file2.path, file2.content, "utf-8");
1155213
+ await writeFile6(file2.path, file2.content, "utf-8");
1154728
1155214
  created.push(file2.path);
1154729
1155215
  }
1154730
1155216
  return created;
@@ -1154833,6 +1155319,808 @@ var require_cjs10 = __commonJS((exports, module) => {
1154833
1155319
  module.exports = deepmerge_1;
1154834
1155320
  });
1154835
1155321
 
1155322
+ // src/infra/mcp/marketplace/index.ts
1155323
+ var init_marketplace = __esm(() => {
1155324
+ init_registry5();
1155325
+ init_installer();
1155326
+ });
1155327
+
1155328
+ // src/app/commands/mcp.ts
1155329
+ var exports_mcp = {};
1155330
+ __export(exports_mcp, {
1155331
+ mcpUpdate: () => mcpUpdate,
1155332
+ mcpUninstall: () => mcpUninstall,
1155333
+ mcpSuggest: () => mcpSuggest,
1155334
+ mcpShowcase: () => mcpShowcase,
1155335
+ mcpSearch: () => mcpSearch,
1155336
+ mcpList: () => mcpList,
1155337
+ mcpInstall: () => mcpInstall,
1155338
+ mcpInfo: () => mcpInfo,
1155339
+ mcpEnable: () => mcpEnable,
1155340
+ mcpDisable: () => mcpDisable,
1155341
+ mcpConfigure: () => mcpConfigure,
1155342
+ handleMCPCommand: () => handleMCPCommand,
1155343
+ formatPluginSuggestionsMessage: () => formatPluginSuggestionsMessage,
1155344
+ checkForPluginSuggestions: () => checkForPluginSuggestions
1155345
+ });
1155346
+ async function mcpList() {
1155347
+ try {
1155348
+ await pluginInstaller.initialize();
1155349
+ const installed = pluginInstaller.getInstalled();
1155350
+ if (installed.length === 0) {
1155351
+ return {
1155352
+ success: true,
1155353
+ message: 'No plugins installed. Use "/mcp search" to find plugins.',
1155354
+ data: { plugins: [] }
1155355
+ };
1155356
+ }
1155357
+ const pluginList = installed.map((p) => ({
1155358
+ id: p.id,
1155359
+ name: p.manifest.name,
1155360
+ version: p.version,
1155361
+ enabled: p.enabled,
1155362
+ category: p.manifest.category,
1155363
+ tools: p.manifest.tools.length
1155364
+ }));
1155365
+ const enabledCount = installed.filter((p) => p.enabled).length;
1155366
+ return {
1155367
+ success: true,
1155368
+ message: `${installed.length} plugin(s) installed (${enabledCount} enabled)`,
1155369
+ data: { plugins: pluginList }
1155370
+ };
1155371
+ } catch (error48) {
1155372
+ return {
1155373
+ success: false,
1155374
+ message: `Failed to list plugins: ${error48 instanceof Error ? error48.message : String(error48)}`
1155375
+ };
1155376
+ }
1155377
+ }
1155378
+ function getStarRating(stars) {
1155379
+ if (!stars)
1155380
+ return "";
1155381
+ const rating = Math.min(5, Math.round(stars / 100 * 1));
1155382
+ const filled = Math.max(1, Math.min(5, rating));
1155383
+ return "\u2605".repeat(filled) + "\u2606".repeat(5 - filled);
1155384
+ }
1155385
+ function formatPricing(pricing) {
1155386
+ switch (pricing.type) {
1155387
+ case "free":
1155388
+ return "Free";
1155389
+ case "freemium":
1155390
+ return pricing.freeUsage ? `Freemium (${pricing.freeUsage})` : "Freemium";
1155391
+ case "paid":
1155392
+ return "Paid";
1155393
+ default:
1155394
+ return pricing.type;
1155395
+ }
1155396
+ }
1155397
+ async function mcpSearch(query) {
1155398
+ try {
1155399
+ let category;
1155400
+ let searchQuery = query;
1155401
+ const categoryMatch = query.match(/category:(\S+)/);
1155402
+ if (categoryMatch) {
1155403
+ category = categoryMatch[1];
1155404
+ searchQuery = query.replace(/category:\S+/, "").trim();
1155405
+ }
1155406
+ const results = await marketplaceClient.searchAdvanced({
1155407
+ query: searchQuery || undefined,
1155408
+ category,
1155409
+ sortBy: "downloads",
1155410
+ sortOrder: "desc",
1155411
+ limit: 20
1155412
+ });
1155413
+ if (results.plugins.length === 0) {
1155414
+ return {
1155415
+ success: true,
1155416
+ message: query ? `No plugins found matching "${query}"` : "No plugins available",
1155417
+ data: { plugins: [], total: 0 }
1155418
+ };
1155419
+ }
1155420
+ const pluginList = results.plugins.map((p) => ({
1155421
+ id: p.id,
1155422
+ name: p.manifest.name,
1155423
+ description: p.manifest.description,
1155424
+ shortDescription: p.manifest.description.substring(0, 60) + (p.manifest.description.length > 60 ? "..." : ""),
1155425
+ category: p.manifest.category,
1155426
+ verified: p.verified,
1155427
+ official: p.officialProvider,
1155428
+ pricing: p.pricing.type,
1155429
+ pricingFormatted: formatPricing(p.pricing),
1155430
+ stars: p.stars,
1155431
+ starRating: getStarRating(p.stars),
1155432
+ downloads: p.downloads,
1155433
+ downloadsFormatted: p.downloads ? `${(p.downloads / 1000).toFixed(1)}k` : undefined,
1155434
+ installed: pluginInstaller.isInstalled(p.id),
1155435
+ toolCount: p.manifest.tools.length
1155436
+ }));
1155437
+ const lines = [`Found ${results.total} plugin(s)${query ? ` matching "${query}"` : ""}:
1155438
+ `];
1155439
+ for (const plugin of pluginList) {
1155440
+ const status = plugin.installed ? "[installed]" : "";
1155441
+ const verified = plugin.verified ? "\u2713" : "";
1155442
+ lines.push(`${plugin.id} (${plugin.category}) ${plugin.starRating} ${status}`);
1155443
+ lines.push(` ${plugin.shortDescription}`);
1155444
+ lines.push(` Pricing: ${plugin.pricingFormatted} | Verified: ${verified || "-"} | Tools: ${plugin.toolCount}`);
1155445
+ lines.push("");
1155446
+ }
1155447
+ return {
1155448
+ success: true,
1155449
+ message: lines.join(`
1155450
+ `),
1155451
+ data: { plugins: pluginList, total: results.total }
1155452
+ };
1155453
+ } catch (error48) {
1155454
+ return {
1155455
+ success: false,
1155456
+ message: `Search failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155457
+ };
1155458
+ }
1155459
+ }
1155460
+ async function mcpInstall(pluginId) {
1155461
+ try {
1155462
+ if (pluginInstaller.isInstalled(pluginId)) {
1155463
+ return {
1155464
+ success: false,
1155465
+ message: `Plugin "${pluginId}" is already installed`
1155466
+ };
1155467
+ }
1155468
+ const listing = await marketplaceClient.getPlugin(pluginId);
1155469
+ if (!listing) {
1155470
+ return {
1155471
+ success: false,
1155472
+ message: `Plugin "${pluginId}" not found in marketplace`
1155473
+ };
1155474
+ }
1155475
+ const installed = await pluginInstaller.install(listing);
1155476
+ const needsCredentials = listing.manifest.authentication.type !== "none" && !credentialManager.hasRequiredCredentials(listing.manifest);
1155477
+ let message4 = `Successfully installed "${listing.manifest.name}" v${installed.version}`;
1155478
+ if (needsCredentials) {
1155479
+ message4 += `. Note: This plugin requires credentials. Use "/mcp configure ${pluginId}" to set them up.`;
1155480
+ }
1155481
+ return {
1155482
+ success: true,
1155483
+ message: message4,
1155484
+ data: {
1155485
+ plugin: {
1155486
+ id: installed.id,
1155487
+ name: installed.manifest.name,
1155488
+ version: installed.version,
1155489
+ enabled: installed.enabled,
1155490
+ needsCredentials
1155491
+ }
1155492
+ }
1155493
+ };
1155494
+ } catch (error48) {
1155495
+ return {
1155496
+ success: false,
1155497
+ message: `Installation failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155498
+ };
1155499
+ }
1155500
+ }
1155501
+ async function mcpUninstall(pluginId) {
1155502
+ try {
1155503
+ const plugin = pluginInstaller.getPlugin(pluginId);
1155504
+ if (!plugin) {
1155505
+ return {
1155506
+ success: false,
1155507
+ message: `Plugin "${pluginId}" is not installed`
1155508
+ };
1155509
+ }
1155510
+ const pluginName = plugin.manifest.name;
1155511
+ await pluginInstaller.uninstall(pluginId);
1155512
+ credentialManager.delete(pluginId);
1155513
+ return {
1155514
+ success: true,
1155515
+ message: `Successfully uninstalled "${pluginName}"`
1155516
+ };
1155517
+ } catch (error48) {
1155518
+ return {
1155519
+ success: false,
1155520
+ message: `Uninstall failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155521
+ };
1155522
+ }
1155523
+ }
1155524
+ async function mcpConfigure(pluginId) {
1155525
+ try {
1155526
+ const plugin = pluginInstaller.getPlugin(pluginId);
1155527
+ if (!plugin) {
1155528
+ return {
1155529
+ success: false,
1155530
+ message: `Plugin "${pluginId}" is not installed`
1155531
+ };
1155532
+ }
1155533
+ const { authentication } = plugin.manifest;
1155534
+ if (authentication.type === "none") {
1155535
+ return {
1155536
+ success: true,
1155537
+ message: `Plugin "${plugin.manifest.name}" does not require any credentials`
1155538
+ };
1155539
+ }
1155540
+ const missing = credentialManager.getMissingCredentials(plugin.manifest);
1155541
+ if (missing.length === 0) {
1155542
+ return {
1155543
+ success: true,
1155544
+ message: `Plugin "${plugin.manifest.name}" is fully configured`,
1155545
+ data: { configured: true }
1155546
+ };
1155547
+ }
1155548
+ let instructions;
1155549
+ if (authentication.type === "api_key" && authentication.envVar) {
1155550
+ instructions = `Set the ${authentication.envVar} environment variable, or store credentials using the credential manager.`;
1155551
+ } else if (authentication.fields) {
1155552
+ const fieldList = authentication.fields.map((f2) => `- ${f2.label} (${f2.name})${f2.sensitive ? " [sensitive]" : ""}`).join(`
1155553
+ `);
1155554
+ instructions = `Required credentials:
1155555
+ ${fieldList}`;
1155556
+ } else {
1155557
+ instructions = `Missing credentials: ${missing.join(", ")}`;
1155558
+ }
1155559
+ return {
1155560
+ success: true,
1155561
+ message: `Plugin "${plugin.manifest.name}" needs configuration:
1155562
+ ${instructions}`,
1155563
+ data: {
1155564
+ configured: false,
1155565
+ missing,
1155566
+ authType: authentication.type,
1155567
+ envVar: authentication.envVar,
1155568
+ fields: authentication.fields
1155569
+ }
1155570
+ };
1155571
+ } catch (error48) {
1155572
+ return {
1155573
+ success: false,
1155574
+ message: `Configuration check failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155575
+ };
1155576
+ }
1155577
+ }
1155578
+ async function mcpEnable(pluginId) {
1155579
+ try {
1155580
+ const plugin = pluginInstaller.getPlugin(pluginId);
1155581
+ if (!plugin) {
1155582
+ return {
1155583
+ success: false,
1155584
+ message: `Plugin "${pluginId}" is not installed`
1155585
+ };
1155586
+ }
1155587
+ if (plugin.enabled) {
1155588
+ return {
1155589
+ success: true,
1155590
+ message: `Plugin "${plugin.manifest.name}" is already enabled`
1155591
+ };
1155592
+ }
1155593
+ await pluginInstaller.enable(pluginId);
1155594
+ return {
1155595
+ success: true,
1155596
+ message: `Plugin "${plugin.manifest.name}" has been enabled`
1155597
+ };
1155598
+ } catch (error48) {
1155599
+ return {
1155600
+ success: false,
1155601
+ message: `Enable failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155602
+ };
1155603
+ }
1155604
+ }
1155605
+ async function mcpDisable(pluginId) {
1155606
+ try {
1155607
+ const plugin = pluginInstaller.getPlugin(pluginId);
1155608
+ if (!plugin) {
1155609
+ return {
1155610
+ success: false,
1155611
+ message: `Plugin "${pluginId}" is not installed`
1155612
+ };
1155613
+ }
1155614
+ if (!plugin.enabled) {
1155615
+ return {
1155616
+ success: true,
1155617
+ message: `Plugin "${plugin.manifest.name}" is already disabled`
1155618
+ };
1155619
+ }
1155620
+ await pluginInstaller.disable(pluginId);
1155621
+ return {
1155622
+ success: true,
1155623
+ message: `Plugin "${plugin.manifest.name}" has been disabled`
1155624
+ };
1155625
+ } catch (error48) {
1155626
+ return {
1155627
+ success: false,
1155628
+ message: `Disable failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155629
+ };
1155630
+ }
1155631
+ }
1155632
+ async function mcpUpdate() {
1155633
+ try {
1155634
+ await pluginInstaller.initialize();
1155635
+ const installed = pluginInstaller.getInstalled();
1155636
+ if (installed.length === 0) {
1155637
+ return {
1155638
+ success: true,
1155639
+ message: "No plugins installed to update"
1155640
+ };
1155641
+ }
1155642
+ const updates = await pluginInstaller.checkUpdates();
1155643
+ if (updates.length === 0) {
1155644
+ return {
1155645
+ success: true,
1155646
+ message: "All plugins are up to date",
1155647
+ data: { updated: [], checked: installed.length }
1155648
+ };
1155649
+ }
1155650
+ const results = [];
1155651
+ for (const { plugin, availableVersion } of updates) {
1155652
+ try {
1155653
+ const updated = await pluginInstaller.update(plugin.id);
1155654
+ results.push({
1155655
+ id: plugin.id,
1155656
+ name: plugin.manifest.name,
1155657
+ oldVersion: plugin.version,
1155658
+ newVersion: updated.version,
1155659
+ success: true
1155660
+ });
1155661
+ } catch (error48) {
1155662
+ results.push({
1155663
+ id: plugin.id,
1155664
+ name: plugin.manifest.name,
1155665
+ oldVersion: plugin.version,
1155666
+ newVersion: availableVersion,
1155667
+ success: false,
1155668
+ error: error48 instanceof Error ? error48.message : String(error48)
1155669
+ });
1155670
+ }
1155671
+ }
1155672
+ const successCount = results.filter((r) => r.success).length;
1155673
+ const failCount = results.filter((r) => !r.success).length;
1155674
+ let message4 = `Updated ${successCount} plugin(s)`;
1155675
+ if (failCount > 0) {
1155676
+ message4 += `, ${failCount} failed`;
1155677
+ }
1155678
+ return {
1155679
+ success: failCount === 0,
1155680
+ message: message4,
1155681
+ data: { results }
1155682
+ };
1155683
+ } catch (error48) {
1155684
+ return {
1155685
+ success: false,
1155686
+ message: `Update failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1155687
+ };
1155688
+ }
1155689
+ }
1155690
+ function formatToolSignature(tool3) {
1155691
+ const schema = tool3.inputSchema;
1155692
+ const properties = schema.properties || {};
1155693
+ const required2 = schema.required || [];
1155694
+ const params = Object.entries(properties).map(([name16, prop]) => {
1155695
+ const isRequired = required2.includes(name16);
1155696
+ const type2 = prop.type || "any";
1155697
+ return isRequired ? `${name16}: ${type2}` : `${name16}?: ${type2}`;
1155698
+ });
1155699
+ return `${tool3.name}(${params.join(", ")})`;
1155700
+ }
1155701
+ function getIntegrationCommands(category) {
1155702
+ const integrations = {
1155703
+ "data-provider": ["/scan", "/analyze", "/compare", "/history"],
1155704
+ analytics: ["/scan", "/analyze", "/signals"],
1155705
+ execution: ["/trade", "/order", "/position"],
1155706
+ portfolio: ["/portfolio", "/pnl", "/balance"],
1155707
+ research: ["/analyze", "/research", "/sentiment"],
1155708
+ utility: ["/alert", "/notify"]
1155709
+ };
1155710
+ return integrations[category] || [];
1155711
+ }
1155712
+ async function mcpInfo(pluginId) {
1155713
+ try {
1155714
+ const installed = pluginInstaller.getPlugin(pluginId);
1155715
+ const listing = await marketplaceClient.getPlugin(pluginId);
1155716
+ if (!installed && !listing) {
1155717
+ return {
1155718
+ success: false,
1155719
+ message: `Plugin "${pluginId}" not found`
1155720
+ };
1155721
+ }
1155722
+ const manifest = installed?.manifest ?? listing.manifest;
1155723
+ const pricing = listing?.pricing;
1155724
+ const auth2 = manifest.authentication;
1155725
+ const info = {
1155726
+ id: manifest.id,
1155727
+ name: manifest.name,
1155728
+ version: installed?.version ?? manifest.version,
1155729
+ description: manifest.description,
1155730
+ author: manifest.author,
1155731
+ category: manifest.category,
1155732
+ tools: manifest.tools.map((t3) => ({
1155733
+ name: t3.name,
1155734
+ description: t3.description,
1155735
+ signature: formatToolSignature(t3)
1155736
+ })),
1155737
+ authentication: manifest.authentication.type,
1155738
+ installed: !!installed,
1155739
+ enabled: installed?.enabled ?? false,
1155740
+ installedAt: installed?.installedAt,
1155741
+ installedFrom: installed?.installedFrom,
1155742
+ marketplace: listing ? {
1155743
+ repository: listing.repository,
1155744
+ verified: listing.verified,
1155745
+ official: listing.officialProvider,
1155746
+ pricing: listing.pricing,
1155747
+ stars: listing.stars,
1155748
+ downloads: listing.downloads,
1155749
+ lastUpdated: listing.lastUpdated
1155750
+ } : null
1155751
+ };
1155752
+ const lines = [];
1155753
+ const verifiedMark = listing?.verified ? "\u2713" : "";
1155754
+ lines.push(`Plugin: ${manifest.name}`);
1155755
+ lines.push(`Version: ${info.version} | Category: ${manifest.category} | Verified: ${verifiedMark || "-"}`);
1155756
+ lines.push("");
1155757
+ lines.push("What it does:");
1155758
+ const descParts = manifest.description.split(/[.!]\s+/).filter(Boolean);
1155759
+ for (const part of descParts) {
1155760
+ lines.push(` \u2022 ${part.trim()}`);
1155761
+ }
1155762
+ lines.push("");
1155763
+ lines.push("Tools added:");
1155764
+ for (const tool3 of manifest.tools) {
1155765
+ lines.push(` - ${formatToolSignature(tool3)}`);
1155766
+ lines.push(` ${tool3.description}`);
1155767
+ }
1155768
+ lines.push("");
1155769
+ lines.push("Requirements:");
1155770
+ if (auth2.type === "none") {
1155771
+ lines.push(" \u2022 No authentication required");
1155772
+ } else if (auth2.type === "api_key") {
1155773
+ const envNote = auth2.envVar ? ` (set ${auth2.envVar})` : "";
1155774
+ const urlNote = pricing?.pricingUrl ? ` - Get at ${pricing.pricingUrl}` : "";
1155775
+ lines.push(` \u2022 API Key: Required${envNote}${urlNote}`);
1155776
+ } else if (auth2.type === "oauth") {
1155777
+ lines.push(" \u2022 OAuth: Authorization required");
1155778
+ }
1155779
+ if (auth2.fields && auth2.fields.length > 0) {
1155780
+ for (const field of auth2.fields) {
1155781
+ const sensitive = field.sensitive ? " [sensitive]" : "";
1155782
+ lines.push(` - ${field.label}${sensitive}`);
1155783
+ }
1155784
+ }
1155785
+ lines.push("");
1155786
+ const integrations = getIntegrationCommands(manifest.category);
1155787
+ if (integrations.length > 0) {
1155788
+ lines.push("Integration:");
1155789
+ lines.push(` \u2022 Works with: ${integrations.join(", ")}`);
1155790
+ if (auth2.type === "none") {
1155791
+ lines.push(" \u2022 Auto-enabled after installation");
1155792
+ } else {
1155793
+ lines.push(" \u2022 Auto-enabled after configuration");
1155794
+ }
1155795
+ lines.push("");
1155796
+ }
1155797
+ if (pricing) {
1155798
+ lines.push(`Pricing: ${formatPricing(pricing)}`);
1155799
+ if (pricing.pricingUrl) {
1155800
+ lines.push(` See: ${pricing.pricingUrl}`);
1155801
+ }
1155802
+ lines.push("");
1155803
+ }
1155804
+ if (listing) {
1155805
+ const stats = [];
1155806
+ if (listing.stars)
1155807
+ stats.push(`${listing.stars} stars`);
1155808
+ if (listing.downloads)
1155809
+ stats.push(`${(listing.downloads / 1000).toFixed(1)}k downloads`);
1155810
+ if (stats.length > 0) {
1155811
+ lines.push(`Stats: ${stats.join(" | ")}`);
1155812
+ }
1155813
+ if (listing.repository) {
1155814
+ lines.push(`Repository: ${listing.repository}`);
1155815
+ }
1155816
+ }
1155817
+ if (installed) {
1155818
+ lines.push("");
1155819
+ lines.push(`Status: Installed ${installed.enabled ? "(enabled)" : "(disabled)"}`);
1155820
+ if (installed.installedAt) {
1155821
+ lines.push(`Installed: ${new Date(installed.installedAt).toLocaleDateString()}`);
1155822
+ }
1155823
+ }
1155824
+ return {
1155825
+ success: true,
1155826
+ message: lines.join(`
1155827
+ `),
1155828
+ data: info
1155829
+ };
1155830
+ } catch (error48) {
1155831
+ return {
1155832
+ success: false,
1155833
+ message: `Failed to get plugin info: ${error48 instanceof Error ? error48.message : String(error48)}`
1155834
+ };
1155835
+ }
1155836
+ }
1155837
+ async function mcpShowcase() {
1155838
+ try {
1155839
+ const lines = [];
1155840
+ lines.push("=== Recommended Plugins by Use Case ===");
1155841
+ lines.push("");
1155842
+ for (const category of PLUGIN_SHOWCASE) {
1155843
+ lines.push(`${category.title}:`);
1155844
+ for (const plugin of category.plugins) {
1155845
+ const pricingNote = plugin.pricingNote ? ` (${plugin.pricingNote})` : "";
1155846
+ const isInstalled = pluginInstaller.isInstalled(plugin.id);
1155847
+ const installedMark = isInstalled ? " [installed]" : "";
1155848
+ lines.push(` \u2022 ${plugin.id} - ${plugin.summary}${pricingNote}${installedMark}`);
1155849
+ }
1155850
+ lines.push("");
1155851
+ }
1155852
+ lines.push('Tip: Use "/mcp info <plugin>" for details or "/mcp install <plugin>" to add.');
1155853
+ const showcaseData = PLUGIN_SHOWCASE.map((cat) => ({
1155854
+ title: cat.title,
1155855
+ description: cat.description,
1155856
+ plugins: cat.plugins.map((p) => ({
1155857
+ ...p,
1155858
+ installed: pluginInstaller.isInstalled(p.id)
1155859
+ }))
1155860
+ }));
1155861
+ return {
1155862
+ success: true,
1155863
+ message: lines.join(`
1155864
+ `),
1155865
+ data: { categories: showcaseData }
1155866
+ };
1155867
+ } catch (error48) {
1155868
+ return {
1155869
+ success: false,
1155870
+ message: `Failed to load showcase: ${error48 instanceof Error ? error48.message : String(error48)}`
1155871
+ };
1155872
+ }
1155873
+ }
1155874
+ async function mcpSuggest(query) {
1155875
+ try {
1155876
+ const queryLower = query.toLowerCase();
1155877
+ const matches = [];
1155878
+ for (const suggestion of PLUGIN_SUGGESTIONS) {
1155879
+ const matchedKeywords = suggestion.keywords.filter((kw) => queryLower.includes(kw.toLowerCase()));
1155880
+ if (matchedKeywords.length > 0) {
1155881
+ matches.push({
1155882
+ pluginId: suggestion.pluginId,
1155883
+ reason: suggestion.reason,
1155884
+ matchedKeywords,
1155885
+ installed: pluginInstaller.isInstalled(suggestion.pluginId)
1155886
+ });
1155887
+ }
1155888
+ }
1155889
+ if (matches.length === 0) {
1155890
+ return {
1155891
+ success: true,
1155892
+ message: `No plugin suggestions for "${query}". Try "/mcp showcase" to browse available plugins.`,
1155893
+ data: { suggestions: [] }
1155894
+ };
1155895
+ }
1155896
+ matches.sort((a2, b) => b.matchedKeywords.length - a2.matchedKeywords.length);
1155897
+ const lines = [];
1155898
+ lines.push(`Plugin suggestions for "${query}":`);
1155899
+ lines.push("");
1155900
+ for (const match of matches) {
1155901
+ const status = match.installed ? "[installed]" : "";
1155902
+ const listing = await marketplaceClient.getPlugin(match.pluginId);
1155903
+ const name16 = listing?.manifest.name || match.pluginId;
1155904
+ const pricing = listing ? formatPricing(listing.pricing) : "";
1155905
+ lines.push(`\u2022 ${name16} (${match.pluginId}) ${status}`);
1155906
+ lines.push(` ${match.reason}`);
1155907
+ if (pricing && !match.installed) {
1155908
+ lines.push(` Pricing: ${pricing}`);
1155909
+ }
1155910
+ if (!match.installed) {
1155911
+ lines.push(` Install: /mcp install ${match.pluginId}`);
1155912
+ }
1155913
+ lines.push("");
1155914
+ }
1155915
+ return {
1155916
+ success: true,
1155917
+ message: lines.join(`
1155918
+ `),
1155919
+ data: { suggestions: matches }
1155920
+ };
1155921
+ } catch (error48) {
1155922
+ return {
1155923
+ success: false,
1155924
+ message: `Failed to get suggestions: ${error48 instanceof Error ? error48.message : String(error48)}`
1155925
+ };
1155926
+ }
1155927
+ }
1155928
+ function checkForPluginSuggestions(userMessage) {
1155929
+ const messageLower = userMessage.toLowerCase();
1155930
+ const matches = [];
1155931
+ for (const suggestion of PLUGIN_SUGGESTIONS) {
1155932
+ if (pluginInstaller.isInstalled(suggestion.pluginId)) {
1155933
+ continue;
1155934
+ }
1155935
+ const hasMatch = suggestion.keywords.some((kw) => messageLower.includes(kw.toLowerCase()));
1155936
+ if (hasMatch) {
1155937
+ matches.push(suggestion);
1155938
+ }
1155939
+ }
1155940
+ return matches;
1155941
+ }
1155942
+ function formatPluginSuggestionsMessage(suggestions) {
1155943
+ if (suggestions.length === 0)
1155944
+ return "";
1155945
+ const lines = [`
1155946
+ ---`, "Tip: Plugins available for this feature:"];
1155947
+ for (const suggestion of suggestions.slice(0, 3)) {
1155948
+ lines.push(` \u2022 ${suggestion.pluginId} - ${suggestion.reason}`);
1155949
+ }
1155950
+ if (suggestions.length > 0) {
1155951
+ lines.push(`Use "/mcp suggest <topic>" for more or "/mcp showcase" to browse all.`);
1155952
+ }
1155953
+ return lines.join(`
1155954
+ `);
1155955
+ }
1155956
+ async function handleMCPCommand(args) {
1155957
+ const subcommand = args[0]?.toLowerCase() ?? "list";
1155958
+ const subArgs = args.slice(1);
1155959
+ switch (subcommand) {
1155960
+ case "list":
1155961
+ case "ls":
1155962
+ return mcpList();
1155963
+ case "search":
1155964
+ case "find":
1155965
+ if (subArgs.length === 0) {
1155966
+ return mcpSearch("");
1155967
+ }
1155968
+ return mcpSearch(subArgs.join(" "));
1155969
+ case "install":
1155970
+ case "add":
1155971
+ if (subArgs.length === 0 || !subArgs[0]) {
1155972
+ return {
1155973
+ success: false,
1155974
+ message: "Usage: /mcp install <pluginId>"
1155975
+ };
1155976
+ }
1155977
+ return mcpInstall(subArgs[0]);
1155978
+ case "uninstall":
1155979
+ case "remove":
1155980
+ case "rm":
1155981
+ if (subArgs.length === 0 || !subArgs[0]) {
1155982
+ return {
1155983
+ success: false,
1155984
+ message: "Usage: /mcp uninstall <pluginId>"
1155985
+ };
1155986
+ }
1155987
+ return mcpUninstall(subArgs[0]);
1155988
+ case "configure":
1155989
+ case "config":
1155990
+ if (subArgs.length === 0 || !subArgs[0]) {
1155991
+ return {
1155992
+ success: false,
1155993
+ message: "Usage: /mcp configure <pluginId>"
1155994
+ };
1155995
+ }
1155996
+ return mcpConfigure(subArgs[0]);
1155997
+ case "enable":
1155998
+ if (subArgs.length === 0 || !subArgs[0]) {
1155999
+ return {
1156000
+ success: false,
1156001
+ message: "Usage: /mcp enable <pluginId>"
1156002
+ };
1156003
+ }
1156004
+ return mcpEnable(subArgs[0]);
1156005
+ case "disable":
1156006
+ if (subArgs.length === 0 || !subArgs[0]) {
1156007
+ return {
1156008
+ success: false,
1156009
+ message: "Usage: /mcp disable <pluginId>"
1156010
+ };
1156011
+ }
1156012
+ return mcpDisable(subArgs[0]);
1156013
+ case "update":
1156014
+ case "upgrade":
1156015
+ return mcpUpdate();
1156016
+ case "info":
1156017
+ case "show":
1156018
+ if (subArgs.length === 0 || !subArgs[0]) {
1156019
+ return {
1156020
+ success: false,
1156021
+ message: "Usage: /mcp info <pluginId>"
1156022
+ };
1156023
+ }
1156024
+ return mcpInfo(subArgs[0]);
1156025
+ case "showcase":
1156026
+ case "recommended":
1156027
+ case "featured":
1156028
+ return mcpShowcase();
1156029
+ case "suggest":
1156030
+ case "recommend":
1156031
+ if (subArgs.length === 0) {
1156032
+ return {
1156033
+ success: false,
1156034
+ message: `Usage: /mcp suggest <query>
1156035
+ Example: /mcp suggest on-chain data`
1156036
+ };
1156037
+ }
1156038
+ return mcpSuggest(subArgs.join(" "));
1156039
+ case "help":
1156040
+ return {
1156041
+ success: true,
1156042
+ message: `MCP Plugin Manager Commands:
1156043
+ /mcp list - List installed plugins
1156044
+ /mcp search <query> - Search marketplace
1156045
+ /mcp install <id> - Install a plugin
1156046
+ /mcp uninstall <id> - Remove a plugin
1156047
+ /mcp configure <id> - Configure credentials
1156048
+ /mcp enable <id> - Enable a plugin
1156049
+ /mcp disable <id> - Disable a plugin
1156050
+ /mcp update - Update all plugins
1156051
+ /mcp info <id> - Show plugin details
1156052
+ /mcp showcase - Browse recommended plugins by use case
1156053
+ /mcp suggest <query> - Get plugin suggestions for a feature
1156054
+
1156055
+ Search tips:
1156056
+ /mcp search price - Search by keyword
1156057
+ /mcp search category:data-provider - Filter by category
1156058
+
1156059
+ Categories: data-provider, analytics, execution, portfolio, research, utility`
1156060
+ };
1156061
+ default:
1156062
+ return {
1156063
+ success: false,
1156064
+ message: `Unknown subcommand: ${subcommand}. Use "/mcp help" for available commands.`
1156065
+ };
1156066
+ }
1156067
+ }
1156068
+ var PLUGIN_SHOWCASE, PLUGIN_SUGGESTIONS;
1156069
+ var init_mcp = __esm(() => {
1156070
+ init_marketplace();
1156071
+ init_credentials();
1156072
+ PLUGIN_SHOWCASE = [
1156073
+ {
1156074
+ title: "For Better Data",
1156075
+ description: "Enhanced market data and historical prices",
1156076
+ plugins: [
1156077
+ { id: "coingecko", summary: "Historical prices, 50+ alt coins", pricingNote: "freemium" },
1156078
+ { id: "glassnode", summary: "On-chain analytics", pricingNote: "paid" }
1156079
+ ]
1156080
+ },
1156081
+ {
1156082
+ title: "For Alerts",
1156083
+ description: "Stay notified about important market events",
1156084
+ plugins: [
1156085
+ { id: "telegram-alerts", summary: "Position notifications" },
1156086
+ { id: "tradingview-signals", summary: "Webhook integration" }
1156087
+ ]
1156088
+ },
1156089
+ {
1156090
+ title: "For DeFi",
1156091
+ description: "Decentralized finance analytics and data",
1156092
+ plugins: [
1156093
+ { id: "defi-llama", summary: "TVL analytics" },
1156094
+ { id: "dexscreener", summary: "DEX trading data" }
1156095
+ ]
1156096
+ },
1156097
+ {
1156098
+ title: "For Sentiment",
1156099
+ description: "Social metrics and market sentiment",
1156100
+ plugins: [
1156101
+ { id: "lunarcrush", summary: "Social metrics", pricingNote: "freemium" }
1156102
+ ]
1156103
+ },
1156104
+ {
1156105
+ title: "For Portfolio",
1156106
+ description: "Track and analyze your holdings",
1156107
+ plugins: [
1156108
+ { id: "portfolio-tracker", summary: "PnL tracking, tax reports" }
1156109
+ ]
1156110
+ }
1156111
+ ];
1156112
+ PLUGIN_SUGGESTIONS = [
1156113
+ { keywords: ["on-chain", "onchain", "nupl", "sopr", "whale", "flow"], pluginId: "glassnode", reason: "provides on-chain analytics and whale tracking" },
1156114
+ { keywords: ["social", "sentiment", "twitter", "influencer"], pluginId: "lunarcrush", reason: "tracks social media sentiment and influencer activity" },
1156115
+ { keywords: ["defi", "tvl", "yield", "farming", "protocol"], pluginId: "defi-llama", reason: "provides DeFi protocol analytics and TVL data" },
1156116
+ { keywords: ["dex", "uniswap", "pancakeswap", "liquidity", "new pair"], pluginId: "dexscreener", reason: "tracks DEX trading data and new pairs" },
1156117
+ { keywords: ["alert", "notification", "telegram", "notify"], pluginId: "telegram-alerts", reason: "sends alerts to Telegram" },
1156118
+ { keywords: ["tradingview", "signal", "webhook"], pluginId: "tradingview-signals", reason: "integrates TradingView alerts" },
1156119
+ { keywords: ["historical", "history", "ohlc", "altcoin", "market cap"], pluginId: "coingecko", reason: "provides historical price data for thousands of coins" },
1156120
+ { keywords: ["portfolio", "pnl", "profit", "loss", "tax"], pluginId: "portfolio-tracker", reason: "tracks portfolio and generates tax reports" }
1156121
+ ];
1156122
+ });
1156123
+
1154836
1156124
  // src/index.tsx
1154837
1156125
  init_cli();
1154838
1156126
 
@@ -1156603,7 +1157891,7 @@ async function checkOrphanedOrders(exchange, activeTrades, result) {
1156603
1157891
  }
1156604
1157892
 
1156605
1157893
  // src/gateway/runtime/gateway-runtime.ts
1156606
- init_client13();
1157894
+ await init_client14();
1156607
1157895
 
1156608
1157896
  // src/gateway/scheduler/local-cron.ts
1156609
1157897
  init_logger2();
@@ -1157457,8 +1158745,8 @@ class ReconciliationLoop {
1157457
1158745
  }
1157458
1158746
  }
1157459
1158747
  // src/gateway/daemon/process.ts
1157460
- init_client13();
1157461
1158748
  init_engine();
1158749
+ await init_client14();
1157462
1158750
  var logger116 = createModuleLogger("gateway-daemon");
1157463
1158751
  async function startGatewayDaemonProcess() {
1157464
1158752
  await bootstrapV07();
@@ -1157816,8 +1159104,8 @@ async function runCLICommand(command) {
1157816
1159104
  // src/infra/license/index.ts
1157817
1159105
  init_paths();
1157818
1159106
  init_cli();
1157819
- import * as fs10 from "fs";
1157820
- import * as path8 from "path";
1159107
+ import * as fs11 from "fs";
1159108
+ import * as path9 from "path";
1157821
1159109
  import * as os6 from "os";
1157822
1159110
  import * as crypto9 from "crypto";
1157823
1159111
  import * as readline from "readline";
@@ -1157913,18 +1159201,18 @@ function requeue(batch) {
1157913
1159201
  }
1157914
1159202
 
1157915
1159203
  // src/infra/license/index.ts
1157916
- var LICENSE_FILE = path8.join(GORDON_DIR, "license.json");
1157917
- var MACHINE_ID_FILE = path8.join(GORDON_DIR, ".machine-id");
1159204
+ var LICENSE_FILE = path9.join(GORDON_DIR, "license.json");
1159205
+ var MACHINE_ID_FILE = path9.join(GORDON_DIR, ".machine-id");
1157918
1159206
  function getMachineId() {
1157919
1159207
  try {
1157920
- if (fs10.existsSync(MACHINE_ID_FILE)) {
1157921
- const stored = fs10.readFileSync(MACHINE_ID_FILE, "utf-8").trim();
1159208
+ if (fs11.existsSync(MACHINE_ID_FILE)) {
1159209
+ const stored = fs11.readFileSync(MACHINE_ID_FILE, "utf-8").trim();
1157922
1159210
  if (stored.length >= 16)
1157923
1159211
  return stored;
1157924
1159212
  }
1157925
1159213
  const id2 = crypto9.randomUUID().replace(/-/g, "");
1157926
- fs10.mkdirSync(path8.dirname(MACHINE_ID_FILE), { recursive: true });
1157927
- fs10.writeFileSync(MACHINE_ID_FILE, id2, { encoding: "utf-8", mode: 384 });
1159214
+ fs11.mkdirSync(path9.dirname(MACHINE_ID_FILE), { recursive: true });
1159215
+ fs11.writeFileSync(MACHINE_ID_FILE, id2, { encoding: "utf-8", mode: 384 });
1157928
1159216
  return id2;
1157929
1159217
  } catch {
1157930
1159218
  let username = "unknown";
@@ -1157937,9 +1159225,9 @@ function getMachineId() {
1157937
1159225
  }
1157938
1159226
  function readLicense() {
1157939
1159227
  try {
1157940
- if (!fs10.existsSync(LICENSE_FILE))
1159228
+ if (!fs11.existsSync(LICENSE_FILE))
1157941
1159229
  return null;
1157942
- const data = fs10.readFileSync(LICENSE_FILE, "utf-8");
1159230
+ const data = fs11.readFileSync(LICENSE_FILE, "utf-8");
1157943
1159231
  const parsed = JSON.parse(data);
1157944
1159232
  if (!parsed.token)
1157945
1159233
  return null;
@@ -1157949,8 +1159237,8 @@ function readLicense() {
1157949
1159237
  }
1157950
1159238
  }
1157951
1159239
  function writeLicense(license) {
1157952
- fs10.mkdirSync(path8.dirname(LICENSE_FILE), { recursive: true });
1157953
- fs10.writeFileSync(LICENSE_FILE, JSON.stringify(license, null, 2), { encoding: "utf-8", mode: 384 });
1159240
+ fs11.mkdirSync(path9.dirname(LICENSE_FILE), { recursive: true });
1159241
+ fs11.writeFileSync(LICENSE_FILE, JSON.stringify(license, null, 2), { encoding: "utf-8", mode: 384 });
1157954
1159242
  }
1157955
1159243
  async function promptInviteCode() {
1157956
1159244
  return new Promise((resolve6) => {
@@ -1158095,7 +1159383,7 @@ async function checkLicense() {
1158095
1159383
  console.error(`
1158096
1159384
  Your access has been revoked. Contact the Gordon team.`);
1158097
1159385
  try {
1158098
- fs10.unlinkSync(LICENSE_FILE);
1159386
+ fs11.unlinkSync(LICENSE_FILE);
1158099
1159387
  } catch {}
1158100
1159388
  process.exit(1);
1158101
1159389
  }
@@ -1161587,6 +1162875,16 @@ var SLASH_COMMANDS = [
1161587
1162875
  action: "tool",
1161588
1162876
  target: "handle_mcp_command"
1161589
1162877
  },
1162878
+ {
1162879
+ name: "skill",
1162880
+ aliases: ["skills"],
1162881
+ description: "Manage skills (plugins with agent routing)",
1162882
+ usage: "/skill <list|search|install|uninstall|route|configure|enable|disable|info|help>",
1162883
+ category: "system",
1162884
+ level: 2,
1162885
+ action: "tool",
1162886
+ target: "handle_skill_command"
1162887
+ },
1161590
1162888
  {
1161591
1162889
  name: "workflow",
1161592
1162890
  aliases: ["wf", "flow"],
@@ -1162241,6 +1163539,45 @@ function commandToPrompt(command, args) {
1162241
1163539
  default:
1162242
1163540
  return "Show my installed MCP plugins";
1162243
1163541
  }
1163542
+ case "skill":
1163543
+ case "skills": {
1163544
+ if (!args)
1163545
+ return "List my installed skills with routing info";
1163546
+ const skillParts = args.split(/\s+/);
1163547
+ const skillSub = skillParts[0]?.toLowerCase();
1163548
+ const skillRest = skillParts.slice(1).join(" ");
1163549
+ switch (skillSub) {
1163550
+ case "list":
1163551
+ case "ls":
1163552
+ return "List my installed skills with routing info";
1163553
+ case "search":
1163554
+ case "find":
1163555
+ return skillRest ? `Search for skills matching "${skillRest}"` : "Show the skills marketplace";
1163556
+ case "install":
1163557
+ case "add":
1163558
+ return skillRest ? `Install the skill "${skillRest}"` : "Show available skills";
1163559
+ case "uninstall":
1163560
+ case "remove":
1163561
+ case "rm":
1163562
+ return skillRest ? `Uninstall the skill "${skillRest}"` : "Which skill to uninstall?";
1163563
+ case "route":
1163564
+ case "assign":
1163565
+ return `Route skill tools: ${skillRest}`;
1163566
+ case "configure":
1163567
+ case "config":
1163568
+ return skillRest ? `Configure credentials for skill "${skillRest}"` : "Which skill to configure?";
1163569
+ case "enable":
1163570
+ return skillRest ? `Enable the skill "${skillRest}"` : "Which skill to enable?";
1163571
+ case "disable":
1163572
+ return skillRest ? `Disable the skill "${skillRest}"` : "Which skill to disable?";
1163573
+ case "info":
1163574
+ return skillRest ? `Show info for skill "${skillRest}"` : "Which skill?";
1163575
+ case "help":
1163576
+ return "Show help for skill management commands";
1163577
+ default:
1163578
+ return "List my installed skills with routing info";
1163579
+ }
1163580
+ }
1162244
1163581
  case "workflow":
1162245
1163582
  if (!args)
1162246
1163583
  return "Show available workflows. Use: /workflow quick <symbol>, /workflow dd <symbol>, or /workflow backtest-cycle <strategy> <symbol>";
@@ -1163590,7 +1164927,7 @@ var import_react64 = __toESM(require_react(), 1);
1163590
1164927
  // package.json
1163591
1164928
  var package_default2 = {
1163592
1164929
  name: "@general-liquidity/gordon-cli",
1163593
- version: "0.75.5",
1164930
+ version: "0.75.7",
1163594
1164931
  description: "The Frontier Trading Agent",
1163595
1164932
  author: "General Liquidity, Inc.",
1163596
1164933
  license: "MIT",
@@ -1165718,8 +1167055,8 @@ async function ensureThreadRegistered() {
1165718
1167055
 
1165719
1167056
  // src/infra/agents/index.ts
1165720
1167057
  init_memory3();
1165721
- init_client13();
1165722
1167058
  init_reflection();
1167059
+ await init_client14();
1165723
1167060
 
1165724
1167061
  // src/app/SetupWizard.tsx
1165725
1167062
  init_binance2();
@@ -1167635,12 +1168972,15 @@ function useTheme() {
1167635
1168972
  }
1167636
1168973
 
1167637
1168974
  // src/app/App.tsx
1167638
- init_client13();
1167639
1168975
  init_llm();
1167640
1168976
  init_binance2();
1167641
1168977
  init_exchange();
1167642
1168978
  init_monitor();
1167643
- await init_orchestrator();
1168979
+ await __promiseAll([
1168980
+ init_orchestrator(),
1168981
+ init_client14(),
1168982
+ init_manager4()
1168983
+ ]);
1167644
1168984
  init_trades();
1167645
1168985
  init_scanner();
1167646
1168986
  init_config2();
@@ -1168363,781 +1169703,258 @@ async function checkOrphanedOrders2(client2, activeTrades, result) {
1168363
1169703
  init_errorContext();
1168364
1169704
  init_theme();
1168365
1169705
 
1168366
- // src/infra/mcp/marketplace/index.ts
1168367
- init_registry5();
1168368
- init_installer();
1169706
+ // src/app/commands/index.ts
1169707
+ init_mcp();
1168369
1169708
 
1168370
- // src/app/commands/mcp.ts
1169709
+ // src/app/commands/skill.ts
1169710
+ init_installer();
1169711
+ init_registry5();
1168371
1169712
  init_credentials();
1168372
- var PLUGIN_SHOWCASE = [
1168373
- {
1168374
- title: "For Better Data",
1168375
- description: "Enhanced market data and historical prices",
1168376
- plugins: [
1168377
- { id: "coingecko", summary: "Historical prices, 50+ alt coins", pricingNote: "freemium" },
1168378
- { id: "glassnode", summary: "On-chain analytics", pricingNote: "paid" }
1168379
- ]
1168380
- },
1168381
- {
1168382
- title: "For Alerts",
1168383
- description: "Stay notified about important market events",
1168384
- plugins: [
1168385
- { id: "telegram-alerts", summary: "Position notifications" },
1168386
- { id: "tradingview-signals", summary: "Webhook integration" }
1168387
- ]
1168388
- },
1168389
- {
1168390
- title: "For DeFi",
1168391
- description: "Decentralized finance analytics and data",
1168392
- plugins: [
1168393
- { id: "defi-llama", summary: "TVL analytics" },
1168394
- { id: "dexscreener", summary: "DEX trading data" }
1168395
- ]
1168396
- },
1168397
- {
1168398
- title: "For Sentiment",
1168399
- description: "Social metrics and market sentiment",
1168400
- plugins: [
1168401
- { id: "lunarcrush", summary: "Social metrics", pricingNote: "freemium" }
1168402
- ]
1168403
- },
1168404
- {
1168405
- title: "For Portfolio",
1168406
- description: "Track and analyze your holdings",
1168407
- plugins: [
1168408
- { id: "portfolio-tracker", summary: "PnL tracking, tax reports" }
1168409
- ]
1168410
- }
1168411
- ];
1168412
- var PLUGIN_SUGGESTIONS = [
1168413
- { keywords: ["on-chain", "onchain", "nupl", "sopr", "whale", "flow"], pluginId: "glassnode", reason: "provides on-chain analytics and whale tracking" },
1168414
- { keywords: ["social", "sentiment", "twitter", "influencer"], pluginId: "lunarcrush", reason: "tracks social media sentiment and influencer activity" },
1168415
- { keywords: ["defi", "tvl", "yield", "farming", "protocol"], pluginId: "defi-llama", reason: "provides DeFi protocol analytics and TVL data" },
1168416
- { keywords: ["dex", "uniswap", "pancakeswap", "liquidity", "new pair"], pluginId: "dexscreener", reason: "tracks DEX trading data and new pairs" },
1168417
- { keywords: ["alert", "notification", "telegram", "notify"], pluginId: "telegram-alerts", reason: "sends alerts to Telegram" },
1168418
- { keywords: ["tradingview", "signal", "webhook"], pluginId: "tradingview-signals", reason: "integrates TradingView alerts" },
1168419
- { keywords: ["historical", "history", "ohlc", "altcoin", "market cap"], pluginId: "coingecko", reason: "provides historical price data for thousands of coins" },
1168420
- { keywords: ["portfolio", "pnl", "profit", "loss", "tax"], pluginId: "portfolio-tracker", reason: "tracks portfolio and generates tax reports" }
1169713
+ await init_manager4();
1169714
+ var VALID_AGENTS = [
1169715
+ "Scanner",
1169716
+ "Analyst",
1169717
+ "Planner",
1169718
+ "Executor",
1169719
+ "Monitor",
1169720
+ "Teacher",
1169721
+ "Backtester",
1169722
+ "Gordon"
1168421
1169723
  ];
1168422
- async function mcpList() {
1168423
- try {
1168424
- await pluginInstaller.initialize();
1168425
- const installed = pluginInstaller.getInstalled();
1168426
- if (installed.length === 0) {
1168427
- return {
1168428
- success: true,
1168429
- message: 'No plugins installed. Use "/mcp search" to find plugins.',
1168430
- data: { plugins: [] }
1168431
- };
1168432
- }
1168433
- const pluginList = installed.map((p) => ({
1168434
- id: p.id,
1168435
- name: p.manifest.name,
1168436
- version: p.version,
1168437
- enabled: p.enabled,
1168438
- category: p.manifest.category,
1168439
- tools: p.manifest.tools.length
1168440
- }));
1168441
- const enabledCount = installed.filter((p) => p.enabled).length;
1168442
- return {
1168443
- success: true,
1168444
- message: `${installed.length} plugin(s) installed (${enabledCount} enabled)`,
1168445
- data: { plugins: pluginList }
1168446
- };
1168447
- } catch (error48) {
1168448
- return {
1168449
- success: false,
1168450
- message: `Failed to list plugins: ${error48 instanceof Error ? error48.message : String(error48)}`
1168451
- };
1168452
- }
1168453
- }
1168454
- function getStarRating(stars) {
1168455
- if (!stars)
1168456
- return "";
1168457
- const rating = Math.min(5, Math.round(stars / 100 * 1));
1168458
- const filled = Math.max(1, Math.min(5, rating));
1168459
- return "\u2605".repeat(filled) + "\u2606".repeat(5 - filled);
1168460
- }
1168461
- function formatPricing(pricing) {
1168462
- switch (pricing.type) {
1168463
- case "free":
1168464
- return "Free";
1168465
- case "freemium":
1168466
- return pricing.freeUsage ? `Freemium (${pricing.freeUsage})` : "Freemium";
1168467
- case "paid":
1168468
- return "Paid";
1168469
- default:
1168470
- return pricing.type;
1168471
- }
1169724
+ function isValidAgent(name16) {
1169725
+ return VALID_AGENTS.includes(name16);
1168472
1169726
  }
1168473
- async function mcpSearch(query) {
1168474
- try {
1168475
- let category;
1168476
- let searchQuery = query;
1168477
- const categoryMatch = query.match(/category:(\S+)/);
1168478
- if (categoryMatch) {
1168479
- category = categoryMatch[1];
1168480
- searchQuery = query.replace(/category:\S+/, "").trim();
1168481
- }
1168482
- const results = await marketplaceClient.searchAdvanced({
1168483
- query: searchQuery || undefined,
1168484
- category,
1168485
- sortBy: "downloads",
1168486
- sortOrder: "desc",
1168487
- limit: 20
1168488
- });
1168489
- if (results.plugins.length === 0) {
1168490
- return {
1168491
- success: true,
1168492
- message: query ? `No plugins found matching "${query}"` : "No plugins available",
1168493
- data: { plugins: [], total: 0 }
1168494
- };
1168495
- }
1168496
- const pluginList = results.plugins.map((p) => ({
1168497
- id: p.id,
1168498
- name: p.manifest.name,
1168499
- description: p.manifest.description,
1168500
- shortDescription: p.manifest.description.substring(0, 60) + (p.manifest.description.length > 60 ? "..." : ""),
1168501
- category: p.manifest.category,
1168502
- verified: p.verified,
1168503
- official: p.officialProvider,
1168504
- pricing: p.pricing.type,
1168505
- pricingFormatted: formatPricing(p.pricing),
1168506
- stars: p.stars,
1168507
- starRating: getStarRating(p.stars),
1168508
- downloads: p.downloads,
1168509
- downloadsFormatted: p.downloads ? `${(p.downloads / 1000).toFixed(1)}k` : undefined,
1168510
- installed: pluginInstaller.isInstalled(p.id),
1168511
- toolCount: p.manifest.tools.length
1168512
- }));
1168513
- const lines = [`Found ${results.total} plugin(s)${query ? ` matching "${query}"` : ""}:
1168514
- `];
1168515
- for (const plugin of pluginList) {
1168516
- const status = plugin.installed ? "[installed]" : "";
1168517
- const verified = plugin.verified ? "\u2713" : "";
1168518
- lines.push(`${plugin.id} (${plugin.category}) ${plugin.starRating} ${status}`);
1168519
- lines.push(` ${plugin.shortDescription}`);
1168520
- lines.push(` Pricing: ${plugin.pricingFormatted} | Verified: ${verified || "-"} | Tools: ${plugin.toolCount}`);
1168521
- lines.push("");
1168522
- }
1169727
+ async function skillList() {
1169728
+ const skills = getResolvedSkills();
1169729
+ if (skills.length === 0) {
1168523
1169730
  return {
1168524
1169731
  success: true,
1168525
- message: lines.join(`
1168526
- `),
1168527
- data: { plugins: pluginList, total: results.total }
1168528
- };
1168529
- } catch (error48) {
1168530
- return {
1168531
- success: false,
1168532
- message: `Search failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1169732
+ message: `No skills installed.
1169733
+ Use "/skill search <query>" to find skills or "/skill help" for usage.`
1168533
1169734
  };
1168534
1169735
  }
1168535
- }
1168536
- async function mcpInstall(pluginId) {
1168537
- try {
1168538
- if (pluginInstaller.isInstalled(pluginId)) {
1168539
- return {
1168540
- success: false,
1168541
- message: `Plugin "${pluginId}" is already installed`
1168542
- };
1168543
- }
1168544
- const listing = await marketplaceClient.getPlugin(pluginId);
1168545
- if (!listing) {
1168546
- return {
1168547
- success: false,
1168548
- message: `Plugin "${pluginId}" not found in marketplace`
1168549
- };
1168550
- }
1168551
- const installed = await pluginInstaller.install(listing);
1168552
- const needsCredentials = listing.manifest.authentication.type !== "none" && !credentialManager.hasRequiredCredentials(listing.manifest);
1168553
- let message4 = `Successfully installed "${listing.manifest.name}" v${installed.version}`;
1168554
- if (needsCredentials) {
1168555
- message4 += `. Note: This plugin requires credentials. Use "/mcp configure ${pluginId}" to set them up.`;
1168556
- }
1168557
- return {
1168558
- success: true,
1168559
- message: message4,
1168560
- data: {
1168561
- plugin: {
1168562
- id: installed.id,
1168563
- name: installed.manifest.name,
1168564
- version: installed.version,
1168565
- enabled: installed.enabled,
1168566
- needsCredentials
1168567
- }
1168568
- }
1168569
- };
1168570
- } catch (error48) {
1168571
- return {
1168572
- success: false,
1168573
- message: `Installation failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1168574
- };
1169736
+ const lines = [`${skills.length} skill(s) installed:
1169737
+ `];
1169738
+ for (const skill of skills) {
1169739
+ const sm = skill.skillManifest;
1169740
+ const status = skill.enabled ? "enabled" : "disabled";
1169741
+ const routing = sm.toolAgentMap && sm.toolAgentMap.length > 0 ? `${sm.toolAgentMap.length} custom route(s), default -> ${sm.defaultAgent}` : `all -> ${sm.defaultAgent}`;
1169742
+ const gordonFlag = sm.alsoOnGordon ? " (+Gordon)" : "";
1169743
+ lines.push(` ${skill.pluginId} [${status}] \u2014 ${skill.toolCount} tool(s) [${routing}${gordonFlag}]`);
1168575
1169744
  }
1169745
+ return { success: true, message: lines.join(`
1169746
+ `), data: { skills } };
1168576
1169747
  }
1168577
- async function mcpUninstall(pluginId) {
1168578
- try {
1168579
- const plugin = pluginInstaller.getPlugin(pluginId);
1168580
- if (!plugin) {
1168581
- return {
1168582
- success: false,
1168583
- message: `Plugin "${pluginId}" is not installed`
1168584
- };
1168585
- }
1168586
- const pluginName = plugin.manifest.name;
1168587
- await pluginInstaller.uninstall(pluginId);
1168588
- credentialManager.delete(pluginId);
1168589
- return {
1168590
- success: true,
1168591
- message: `Successfully uninstalled "${pluginName}"`
1168592
- };
1168593
- } catch (error48) {
1169748
+ async function skillInstall(pluginId, defaultAgent = "Scanner") {
1169749
+ const listing = await marketplaceClient.getPlugin(pluginId);
1169750
+ if (!listing) {
1168594
1169751
  return {
1168595
1169752
  success: false,
1168596
- message: `Uninstall failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1169753
+ message: `Skill "${pluginId}" not found in marketplace.`
1168597
1169754
  };
1168598
1169755
  }
1168599
- }
1168600
- async function mcpConfigure(pluginId) {
1168601
- try {
1168602
- const plugin = pluginInstaller.getPlugin(pluginId);
1168603
- if (!plugin) {
1168604
- return {
1168605
- success: false,
1168606
- message: `Plugin "${pluginId}" is not installed`
1168607
- };
1168608
- }
1168609
- const { authentication } = plugin.manifest;
1168610
- if (authentication.type === "none") {
1168611
- return {
1168612
- success: true,
1168613
- message: `Plugin "${plugin.manifest.name}" does not require any credentials`
1168614
- };
1168615
- }
1168616
- const missing = credentialManager.getMissingCredentials(plugin.manifest);
1168617
- if (missing.length === 0) {
1168618
- return {
1168619
- success: true,
1168620
- message: `Plugin "${plugin.manifest.name}" is fully configured`,
1168621
- data: { configured: true }
1168622
- };
1168623
- }
1168624
- let instructions;
1168625
- if (authentication.type === "api_key" && authentication.envVar) {
1168626
- instructions = `Set the ${authentication.envVar} environment variable, or store credentials using the credential manager.`;
1168627
- } else if (authentication.fields) {
1168628
- const fieldList = authentication.fields.map((f2) => `- ${f2.label} (${f2.name})${f2.sensitive ? " [sensitive]" : ""}`).join(`
1168629
- `);
1168630
- instructions = `Required credentials:
1168631
- ${fieldList}`;
1168632
- } else {
1168633
- instructions = `Missing credentials: ${missing.join(", ")}`;
1168634
- }
1168635
- return {
1168636
- success: true,
1168637
- message: `Plugin "${plugin.manifest.name}" needs configuration:
1168638
- ${instructions}`,
1168639
- data: {
1168640
- configured: false,
1168641
- missing,
1168642
- authType: authentication.type,
1168643
- envVar: authentication.envVar,
1168644
- fields: authentication.fields
1168645
- }
1168646
- };
1168647
- } catch (error48) {
1169756
+ if (pluginInstaller.isInstalled(pluginId)) {
1168648
1169757
  return {
1168649
1169758
  success: false,
1168650
- message: `Configuration check failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1169759
+ message: `Skill "${pluginId}" is already installed. Use "/skill route ${pluginId} <agent>" to change routing.`
1168651
1169760
  };
1168652
1169761
  }
1168653
- }
1168654
- async function mcpEnable(pluginId) {
1168655
- try {
1168656
- const plugin = pluginInstaller.getPlugin(pluginId);
1168657
- if (!plugin) {
1168658
- return {
1168659
- success: false,
1168660
- message: `Plugin "${pluginId}" is not installed`
1168661
- };
1168662
- }
1168663
- if (plugin.enabled) {
1168664
- return {
1168665
- success: true,
1168666
- message: `Plugin "${plugin.manifest.name}" is already enabled`
1168667
- };
1168668
- }
1168669
- await pluginInstaller.enable(pluginId);
1168670
- return {
1168671
- success: true,
1168672
- message: `Plugin "${plugin.manifest.name}" has been enabled`
1168673
- };
1168674
- } catch (error48) {
1168675
- return {
1168676
- success: false,
1168677
- message: `Enable failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1168678
- };
1169762
+ await pluginInstaller.install(listing);
1169763
+ const skillManifest = {
1169764
+ pluginId,
1169765
+ defaultAgent,
1169766
+ alsoOnGordon: false
1169767
+ };
1169768
+ await writeSkillManifest(skillManifest);
1169769
+ await reloadSkills();
1169770
+ const needsCredentials = listing.manifest.authentication.type !== "none" && !credentialManager.hasRequiredCredentials(listing.manifest);
1169771
+ let message4 = `Installed skill "${listing.manifest.name}" -> ${defaultAgent} (${listing.manifest.tools.length} tools)`;
1169772
+ if (needsCredentials) {
1169773
+ message4 += `
1169774
+ Configure credentials: /skill configure ${pluginId}`;
1168679
1169775
  }
1169776
+ return { success: true, message: message4, data: { pluginId, defaultAgent } };
1168680
1169777
  }
1168681
- async function mcpDisable(pluginId) {
1168682
- try {
1168683
- const plugin = pluginInstaller.getPlugin(pluginId);
1168684
- if (!plugin) {
1168685
- return {
1168686
- success: false,
1168687
- message: `Plugin "${pluginId}" is not installed`
1168688
- };
1168689
- }
1168690
- if (!plugin.enabled) {
1168691
- return {
1168692
- success: true,
1168693
- message: `Plugin "${plugin.manifest.name}" is already disabled`
1168694
- };
1168695
- }
1168696
- await pluginInstaller.disable(pluginId);
1168697
- return {
1168698
- success: true,
1168699
- message: `Plugin "${plugin.manifest.name}" has been disabled`
1168700
- };
1168701
- } catch (error48) {
1169778
+ async function skillRoute(pluginId, agentName) {
1169779
+ if (!pluginInstaller.isInstalled(pluginId)) {
1168702
1169780
  return {
1168703
1169781
  success: false,
1168704
- message: `Disable failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1169782
+ message: `Skill "${pluginId}" is not installed.`
1168705
1169783
  };
1168706
1169784
  }
1168707
- }
1168708
- async function mcpUpdate() {
1168709
- try {
1168710
- await pluginInstaller.initialize();
1168711
- const installed = pluginInstaller.getInstalled();
1168712
- if (installed.length === 0) {
1168713
- return {
1168714
- success: true,
1168715
- message: "No plugins installed to update"
1168716
- };
1168717
- }
1168718
- const updates = await pluginInstaller.checkUpdates();
1168719
- if (updates.length === 0) {
1168720
- return {
1168721
- success: true,
1168722
- message: "All plugins are up to date",
1168723
- data: { updated: [], checked: installed.length }
1168724
- };
1168725
- }
1168726
- const results = [];
1168727
- for (const { plugin, availableVersion } of updates) {
1168728
- try {
1168729
- const updated = await pluginInstaller.update(plugin.id);
1168730
- results.push({
1168731
- id: plugin.id,
1168732
- name: plugin.manifest.name,
1168733
- oldVersion: plugin.version,
1168734
- newVersion: updated.version,
1168735
- success: true
1168736
- });
1168737
- } catch (error48) {
1168738
- results.push({
1168739
- id: plugin.id,
1168740
- name: plugin.manifest.name,
1168741
- oldVersion: plugin.version,
1168742
- newVersion: availableVersion,
1168743
- success: false,
1168744
- error: error48 instanceof Error ? error48.message : String(error48)
1168745
- });
1168746
- }
1168747
- }
1168748
- const successCount = results.filter((r) => r.success).length;
1168749
- const failCount = results.filter((r) => !r.success).length;
1168750
- let message4 = `Updated ${successCount} plugin(s)`;
1168751
- if (failCount > 0) {
1168752
- message4 += `, ${failCount} failed`;
1168753
- }
1168754
- return {
1168755
- success: failCount === 0,
1168756
- message: message4,
1168757
- data: { results }
1168758
- };
1168759
- } catch (error48) {
1169785
+ if (!isValidAgent(agentName)) {
1168760
1169786
  return {
1168761
1169787
  success: false,
1168762
- message: `Update failed: ${error48 instanceof Error ? error48.message : String(error48)}`
1169788
+ message: `Invalid agent "${agentName}". Valid: ${VALID_AGENTS.join(", ")}`
1168763
1169789
  };
1168764
1169790
  }
1168765
- }
1168766
- function formatToolSignature(tool3) {
1168767
- const schema = tool3.inputSchema;
1168768
- const properties = schema.properties || {};
1168769
- const required2 = schema.required || [];
1168770
- const params = Object.entries(properties).map(([name16, prop]) => {
1168771
- const isRequired = required2.includes(name16);
1168772
- const type2 = prop.type || "any";
1168773
- return isRequired ? `${name16}: ${type2}` : `${name16}?: ${type2}`;
1168774
- });
1168775
- return `${tool3.name}(${params.join(", ")})`;
1168776
- }
1168777
- function getIntegrationCommands(category) {
1168778
- const integrations = {
1168779
- "data-provider": ["/scan", "/analyze", "/compare", "/history"],
1168780
- analytics: ["/scan", "/analyze", "/signals"],
1168781
- execution: ["/trade", "/order", "/position"],
1168782
- portfolio: ["/portfolio", "/pnl", "/balance"],
1168783
- research: ["/analyze", "/research", "/sentiment"],
1168784
- utility: ["/alert", "/notify"]
1169791
+ const skillManifest = {
1169792
+ pluginId,
1169793
+ defaultAgent: agentName,
1169794
+ alsoOnGordon: false
1169795
+ };
1169796
+ await writeSkillManifest(skillManifest);
1169797
+ await reloadSkills();
1169798
+ return {
1169799
+ success: true,
1169800
+ message: `Skill "${pluginId}" tools now route to ${agentName}.`
1168785
1169801
  };
1168786
- return integrations[category] || [];
1168787
1169802
  }
1168788
- async function mcpInfo(pluginId) {
1168789
- try {
1168790
- const installed = pluginInstaller.getPlugin(pluginId);
1168791
- const listing = await marketplaceClient.getPlugin(pluginId);
1168792
- if (!installed && !listing) {
1168793
- return {
1168794
- success: false,
1168795
- message: `Plugin "${pluginId}" not found`
1168796
- };
1168797
- }
1168798
- const manifest = installed?.manifest ?? listing.manifest;
1168799
- const pricing = listing?.pricing;
1168800
- const auth2 = manifest.authentication;
1168801
- const info = {
1168802
- id: manifest.id,
1168803
- name: manifest.name,
1168804
- version: installed?.version ?? manifest.version,
1168805
- description: manifest.description,
1168806
- author: manifest.author,
1168807
- category: manifest.category,
1168808
- tools: manifest.tools.map((t3) => ({
1168809
- name: t3.name,
1168810
- description: t3.description,
1168811
- signature: formatToolSignature(t3)
1168812
- })),
1168813
- authentication: manifest.authentication.type,
1168814
- installed: !!installed,
1168815
- enabled: installed?.enabled ?? false,
1168816
- installedAt: installed?.installedAt,
1168817
- installedFrom: installed?.installedFrom,
1168818
- marketplace: listing ? {
1168819
- repository: listing.repository,
1168820
- verified: listing.verified,
1168821
- official: listing.officialProvider,
1168822
- pricing: listing.pricing,
1168823
- stars: listing.stars,
1168824
- downloads: listing.downloads,
1168825
- lastUpdated: listing.lastUpdated
1168826
- } : null
1168827
- };
1168828
- const lines = [];
1168829
- const verifiedMark = listing?.verified ? "\u2713" : "";
1168830
- lines.push(`Plugin: ${manifest.name}`);
1168831
- lines.push(`Version: ${info.version} | Category: ${manifest.category} | Verified: ${verifiedMark || "-"}`);
1168832
- lines.push("");
1168833
- lines.push("What it does:");
1168834
- const descParts = manifest.description.split(/[.!]\s+/).filter(Boolean);
1168835
- for (const part of descParts) {
1168836
- lines.push(` \u2022 ${part.trim()}`);
1168837
- }
1168838
- lines.push("");
1168839
- lines.push("Tools added:");
1168840
- for (const tool3 of manifest.tools) {
1168841
- lines.push(` - ${formatToolSignature(tool3)}`);
1168842
- lines.push(` ${tool3.description}`);
1168843
- }
1168844
- lines.push("");
1168845
- lines.push("Requirements:");
1168846
- if (auth2.type === "none") {
1168847
- lines.push(" \u2022 No authentication required");
1168848
- } else if (auth2.type === "api_key") {
1168849
- const envNote = auth2.envVar ? ` (set ${auth2.envVar})` : "";
1168850
- const urlNote = pricing?.pricingUrl ? ` - Get at ${pricing.pricingUrl}` : "";
1168851
- lines.push(` \u2022 API Key: Required${envNote}${urlNote}`);
1168852
- } else if (auth2.type === "oauth") {
1168853
- lines.push(" \u2022 OAuth: Authorization required");
1168854
- }
1168855
- if (auth2.fields && auth2.fields.length > 0) {
1168856
- for (const field of auth2.fields) {
1168857
- const sensitive = field.sensitive ? " [sensitive]" : "";
1168858
- lines.push(` - ${field.label}${sensitive}`);
1168859
- }
1168860
- }
1168861
- lines.push("");
1168862
- const integrations = getIntegrationCommands(manifest.category);
1168863
- if (integrations.length > 0) {
1168864
- lines.push("Integration:");
1168865
- lines.push(` \u2022 Works with: ${integrations.join(", ")}`);
1168866
- if (auth2.type === "none") {
1168867
- lines.push(" \u2022 Auto-enabled after installation");
1168868
- } else {
1168869
- lines.push(" \u2022 Auto-enabled after configuration");
1168870
- }
1168871
- lines.push("");
1168872
- }
1168873
- if (pricing) {
1168874
- lines.push(`Pricing: ${formatPricing(pricing)}`);
1168875
- if (pricing.pricingUrl) {
1168876
- lines.push(` See: ${pricing.pricingUrl}`);
1168877
- }
1168878
- lines.push("");
1168879
- }
1168880
- if (listing) {
1168881
- const stats = [];
1168882
- if (listing.stars)
1168883
- stats.push(`${listing.stars} stars`);
1168884
- if (listing.downloads)
1168885
- stats.push(`${(listing.downloads / 1000).toFixed(1)}k downloads`);
1168886
- if (stats.length > 0) {
1168887
- lines.push(`Stats: ${stats.join(" | ")}`);
1168888
- }
1168889
- if (listing.repository) {
1168890
- lines.push(`Repository: ${listing.repository}`);
1168891
- }
1168892
- }
1168893
- if (installed) {
1168894
- lines.push("");
1168895
- lines.push(`Status: Installed ${installed.enabled ? "(enabled)" : "(disabled)"}`);
1168896
- if (installed.installedAt) {
1168897
- lines.push(`Installed: ${new Date(installed.installedAt).toLocaleDateString()}`);
1168898
- }
1168899
- }
1168900
- return {
1168901
- success: true,
1168902
- message: lines.join(`
1168903
- `),
1168904
- data: info
1168905
- };
1168906
- } catch (error48) {
1169803
+ async function skillUninstall(pluginId) {
1169804
+ const plugin = pluginInstaller.getPlugin(pluginId);
1169805
+ if (!plugin) {
1168907
1169806
  return {
1168908
1169807
  success: false,
1168909
- message: `Failed to get plugin info: ${error48 instanceof Error ? error48.message : String(error48)}`
1169808
+ message: `Skill "${pluginId}" is not installed.`
1168910
1169809
  };
1168911
1169810
  }
1169811
+ const name16 = plugin.manifest.name;
1169812
+ await pluginInstaller.uninstall(pluginId);
1169813
+ credentialManager.delete(pluginId);
1169814
+ await reloadSkills();
1169815
+ return { success: true, message: `Uninstalled skill "${name16}".` };
1168912
1169816
  }
1168913
- async function mcpShowcase() {
1168914
- try {
1168915
- const lines = [];
1168916
- lines.push("=== Recommended Plugins by Use Case ===");
1168917
- lines.push("");
1168918
- for (const category of PLUGIN_SHOWCASE) {
1168919
- lines.push(`${category.title}:`);
1168920
- for (const plugin of category.plugins) {
1168921
- const pricingNote = plugin.pricingNote ? ` (${plugin.pricingNote})` : "";
1168922
- const isInstalled = pluginInstaller.isInstalled(plugin.id);
1168923
- const installedMark = isInstalled ? " [installed]" : "";
1168924
- lines.push(` \u2022 ${plugin.id} - ${plugin.summary}${pricingNote}${installedMark}`);
1168925
- }
1168926
- lines.push("");
1168927
- }
1168928
- lines.push('Tip: Use "/mcp info <plugin>" for details or "/mcp install <plugin>" to add.');
1168929
- const showcaseData = PLUGIN_SHOWCASE.map((cat) => ({
1168930
- title: cat.title,
1168931
- description: cat.description,
1168932
- plugins: cat.plugins.map((p) => ({
1168933
- ...p,
1168934
- installed: pluginInstaller.isInstalled(p.id)
1168935
- }))
1168936
- }));
1168937
- return {
1168938
- success: true,
1168939
- message: lines.join(`
1168940
- `),
1168941
- data: { categories: showcaseData }
1168942
- };
1168943
- } catch (error48) {
1169817
+ async function skillEnable(pluginId) {
1169818
+ if (!pluginInstaller.isInstalled(pluginId)) {
1168944
1169819
  return {
1168945
1169820
  success: false,
1168946
- message: `Failed to load showcase: ${error48 instanceof Error ? error48.message : String(error48)}`
1169821
+ message: `Skill "${pluginId}" is not installed.`
1168947
1169822
  };
1168948
1169823
  }
1169824
+ await pluginInstaller.enable(pluginId);
1169825
+ await reloadSkills();
1169826
+ return { success: true, message: `Enabled skill "${pluginId}".` };
1168949
1169827
  }
1168950
- async function mcpSuggest(query) {
1168951
- try {
1168952
- const queryLower = query.toLowerCase();
1168953
- const matches = [];
1168954
- for (const suggestion of PLUGIN_SUGGESTIONS) {
1168955
- const matchedKeywords = suggestion.keywords.filter((kw) => queryLower.includes(kw.toLowerCase()));
1168956
- if (matchedKeywords.length > 0) {
1168957
- matches.push({
1168958
- pluginId: suggestion.pluginId,
1168959
- reason: suggestion.reason,
1168960
- matchedKeywords,
1168961
- installed: pluginInstaller.isInstalled(suggestion.pluginId)
1168962
- });
1168963
- }
1168964
- }
1168965
- if (matches.length === 0) {
1168966
- return {
1168967
- success: true,
1168968
- message: `No plugin suggestions for "${query}". Try "/mcp showcase" to browse available plugins.`,
1168969
- data: { suggestions: [] }
1168970
- };
1168971
- }
1168972
- matches.sort((a2, b) => b.matchedKeywords.length - a2.matchedKeywords.length);
1168973
- const lines = [];
1168974
- lines.push(`Plugin suggestions for "${query}":`);
1168975
- lines.push("");
1168976
- for (const match of matches) {
1168977
- const status = match.installed ? "[installed]" : "";
1168978
- const listing = await marketplaceClient.getPlugin(match.pluginId);
1168979
- const name16 = listing?.manifest.name || match.pluginId;
1168980
- const pricing = listing ? formatPricing(listing.pricing) : "";
1168981
- lines.push(`\u2022 ${name16} (${match.pluginId}) ${status}`);
1168982
- lines.push(` ${match.reason}`);
1168983
- if (pricing && !match.installed) {
1168984
- lines.push(` Pricing: ${pricing}`);
1168985
- }
1168986
- if (!match.installed) {
1168987
- lines.push(` Install: /mcp install ${match.pluginId}`);
1168988
- }
1168989
- lines.push("");
1168990
- }
1168991
- return {
1168992
- success: true,
1168993
- message: lines.join(`
1168994
- `),
1168995
- data: { suggestions: matches }
1168996
- };
1168997
- } catch (error48) {
1169828
+ async function skillDisable(pluginId) {
1169829
+ if (!pluginInstaller.isInstalled(pluginId)) {
1168998
1169830
  return {
1168999
1169831
  success: false,
1169000
- message: `Failed to get suggestions: ${error48 instanceof Error ? error48.message : String(error48)}`
1169832
+ message: `Skill "${pluginId}" is not installed.`
1169001
1169833
  };
1169002
1169834
  }
1169835
+ await pluginInstaller.disable(pluginId);
1169836
+ await reloadSkills();
1169837
+ return { success: true, message: `Disabled skill "${pluginId}".` };
1169003
1169838
  }
1169004
- function checkForPluginSuggestions(userMessage) {
1169005
- const messageLower = userMessage.toLowerCase();
1169006
- const matches = [];
1169007
- for (const suggestion of PLUGIN_SUGGESTIONS) {
1169008
- if (pluginInstaller.isInstalled(suggestion.pluginId)) {
1169009
- continue;
1169010
- }
1169011
- const hasMatch = suggestion.keywords.some((kw) => messageLower.includes(kw.toLowerCase()));
1169012
- if (hasMatch) {
1169013
- matches.push(suggestion);
1169014
- }
1169015
- }
1169016
- return matches;
1169017
- }
1169018
- function formatPluginSuggestionsMessage(suggestions) {
1169019
- if (suggestions.length === 0)
1169020
- return "";
1169021
- const lines = [`
1169022
- ---`, "Tip: Plugins available for this feature:"];
1169023
- for (const suggestion of suggestions.slice(0, 3)) {
1169024
- lines.push(` \u2022 ${suggestion.pluginId} - ${suggestion.reason}`);
1169025
- }
1169026
- if (suggestions.length > 0) {
1169027
- lines.push(`Use "/mcp suggest <topic>" for more or "/mcp showcase" to browse all.`);
1169028
- }
1169029
- return lines.join(`
1169030
- `);
1169031
- }
1169032
- async function handleMCPCommand(args) {
1169839
+ async function handleSkillCommand(args) {
1169033
1169840
  const subcommand = args[0]?.toLowerCase() ?? "list";
1169034
1169841
  const subArgs = args.slice(1);
1169035
1169842
  switch (subcommand) {
1169036
1169843
  case "list":
1169037
1169844
  case "ls":
1169038
- return mcpList();
1169039
- case "search":
1169040
- case "find":
1169041
- if (subArgs.length === 0) {
1169042
- return mcpSearch("");
1169043
- }
1169044
- return mcpSearch(subArgs.join(" "));
1169845
+ return skillList();
1169045
1169846
  case "install":
1169046
- case "add":
1169047
- if (subArgs.length === 0 || !subArgs[0]) {
1169847
+ case "add": {
1169848
+ if (!subArgs[0]) {
1169048
1169849
  return {
1169049
1169850
  success: false,
1169050
- message: "Usage: /mcp install <pluginId>"
1169851
+ message: "Usage: /skill install <id> [--agent <name>]"
1169051
1169852
  };
1169052
1169853
  }
1169053
- return mcpInstall(subArgs[0]);
1169054
- case "uninstall":
1169055
- case "remove":
1169056
- case "rm":
1169057
- if (subArgs.length === 0 || !subArgs[0]) {
1169854
+ const agentIdx = subArgs.indexOf("--agent");
1169855
+ let agent = "Scanner";
1169856
+ if (agentIdx >= 0 && subArgs[agentIdx + 1]) {
1169857
+ const candidate = subArgs[agentIdx + 1];
1169858
+ if (!isValidAgent(candidate)) {
1169859
+ return {
1169860
+ success: false,
1169861
+ message: `Invalid agent "${candidate}". Valid: ${VALID_AGENTS.join(", ")}`
1169862
+ };
1169863
+ }
1169864
+ agent = candidate;
1169865
+ }
1169866
+ return skillInstall(subArgs[0], agent);
1169867
+ }
1169868
+ case "route":
1169869
+ case "assign": {
1169870
+ if (!subArgs[0] || !subArgs[1]) {
1169058
1169871
  return {
1169059
1169872
  success: false,
1169060
- message: "Usage: /mcp uninstall <pluginId>"
1169873
+ message: `Usage: /skill route <id> <agent>
1169874
+ Agents: ${VALID_AGENTS.join(", ")}`
1169061
1169875
  };
1169062
1169876
  }
1169063
- return mcpUninstall(subArgs[0]);
1169064
- case "configure":
1169065
- case "config":
1169066
- if (subArgs.length === 0 || !subArgs[0]) {
1169877
+ return skillRoute(subArgs[0], subArgs[1]);
1169878
+ }
1169879
+ case "uninstall":
1169880
+ case "remove":
1169881
+ case "rm":
1169882
+ if (!subArgs[0]) {
1169067
1169883
  return {
1169068
1169884
  success: false,
1169069
- message: "Usage: /mcp configure <pluginId>"
1169885
+ message: "Usage: /skill uninstall <id>"
1169070
1169886
  };
1169071
1169887
  }
1169072
- return mcpConfigure(subArgs[0]);
1169888
+ return skillUninstall(subArgs[0]);
1169073
1169889
  case "enable":
1169074
- if (subArgs.length === 0 || !subArgs[0]) {
1169075
- return {
1169076
- success: false,
1169077
- message: "Usage: /mcp enable <pluginId>"
1169078
- };
1169890
+ if (!subArgs[0]) {
1169891
+ return { success: false, message: "Usage: /skill enable <id>" };
1169079
1169892
  }
1169080
- return mcpEnable(subArgs[0]);
1169893
+ return skillEnable(subArgs[0]);
1169081
1169894
  case "disable":
1169082
- if (subArgs.length === 0 || !subArgs[0]) {
1169083
- return {
1169084
- success: false,
1169085
- message: "Usage: /mcp disable <pluginId>"
1169086
- };
1169895
+ if (!subArgs[0]) {
1169896
+ return { success: false, message: "Usage: /skill disable <id>" };
1169087
1169897
  }
1169088
- return mcpDisable(subArgs[0]);
1169089
- case "update":
1169090
- case "upgrade":
1169091
- return mcpUpdate();
1169092
- case "info":
1169093
- case "show":
1169094
- if (subArgs.length === 0 || !subArgs[0]) {
1169898
+ return skillDisable(subArgs[0]);
1169899
+ case "search":
1169900
+ case "find": {
1169901
+ const { mcpSearch: mcpSearch2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
1169902
+ return mcpSearch2(subArgs.join(" "));
1169903
+ }
1169904
+ case "configure":
1169905
+ case "config": {
1169906
+ if (!subArgs[0]) {
1169095
1169907
  return {
1169096
1169908
  success: false,
1169097
- message: "Usage: /mcp info <pluginId>"
1169909
+ message: "Usage: /skill configure <id>"
1169098
1169910
  };
1169099
1169911
  }
1169100
- return mcpInfo(subArgs[0]);
1169101
- case "showcase":
1169102
- case "recommended":
1169103
- case "featured":
1169104
- return mcpShowcase();
1169105
- case "suggest":
1169106
- case "recommend":
1169107
- if (subArgs.length === 0) {
1169108
- return {
1169109
- success: false,
1169110
- message: `Usage: /mcp suggest <query>
1169111
- Example: /mcp suggest on-chain data`
1169112
- };
1169912
+ const { mcpConfigure: mcpConfigure2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
1169913
+ return mcpConfigure2(subArgs[0]);
1169914
+ }
1169915
+ case "info": {
1169916
+ if (!subArgs[0]) {
1169917
+ return { success: false, message: "Usage: /skill info <id>" };
1169113
1169918
  }
1169114
- return mcpSuggest(subArgs.join(" "));
1169919
+ const { mcpInfo: mcpInfo2 } = await Promise.resolve().then(() => (init_mcp(), exports_mcp));
1169920
+ const infoResult = await mcpInfo2(subArgs[0]);
1169921
+ const skills = getResolvedSkills();
1169922
+ const skill = skills.find((s2) => s2.pluginId === subArgs[0]);
1169923
+ if (skill) {
1169924
+ const sm = skill.skillManifest;
1169925
+ const routing = sm.toolAgentMap && sm.toolAgentMap.length > 0 ? sm.toolAgentMap.map((m) => ` ${m.toolName} -> ${m.agent}`).join(`
1169926
+ `) : ` all -> ${sm.defaultAgent}`;
1169927
+ infoResult.message += `
1169928
+
1169929
+ Routing:
1169930
+ ${routing}`;
1169931
+ if (sm.alsoOnGordon) {
1169932
+ infoResult.message += `
1169933
+ (also available on Gordon)`;
1169934
+ }
1169935
+ }
1169936
+ return infoResult;
1169937
+ }
1169115
1169938
  case "help":
1169116
1169939
  return {
1169117
1169940
  success: true,
1169118
- message: `MCP Plugin Manager Commands:
1169119
- /mcp list - List installed plugins
1169120
- /mcp search <query> - Search marketplace
1169121
- /mcp install <id> - Install a plugin
1169122
- /mcp uninstall <id> - Remove a plugin
1169123
- /mcp configure <id> - Configure credentials
1169124
- /mcp enable <id> - Enable a plugin
1169125
- /mcp disable <id> - Disable a plugin
1169126
- /mcp update - Update all plugins
1169127
- /mcp info <id> - Show plugin details
1169128
- /mcp showcase - Browse recommended plugins by use case
1169129
- /mcp suggest <query> - Get plugin suggestions for a feature
1169130
-
1169131
- Search tips:
1169132
- /mcp search price - Search by keyword
1169133
- /mcp search category:data-provider - Filter by category
1169134
-
1169135
- Categories: data-provider, analytics, execution, portfolio, research, utility`
1169941
+ message: `Skill Commands:
1169942
+ /skill list \u2014 List installed skills with routing
1169943
+ /skill search <query> \u2014 Search marketplace
1169944
+ /skill install <id> [--agent <name>] \u2014 Install and route to agent
1169945
+ /skill uninstall <id> \u2014 Remove a skill
1169946
+ /skill route <id> <agent> \u2014 Change agent routing
1169947
+ /skill configure <id> \u2014 Set up credentials
1169948
+ /skill enable <id> \u2014 Enable a skill
1169949
+ /skill disable <id> \u2014 Disable a skill
1169950
+ /skill info <id> \u2014 Show skill details
1169951
+
1169952
+ Agents: ${VALID_AGENTS.join(", ")}`
1169136
1169953
  };
1169137
1169954
  default:
1169138
1169955
  return {
1169139
1169956
  success: false,
1169140
- message: `Unknown subcommand: ${subcommand}. Use "/mcp help" for available commands.`
1169957
+ message: `Unknown subcommand "${subcommand}". Use "/skill help" for usage.`
1169141
1169958
  };
1169142
1169959
  }
1169143
1169960
  }
@@ -1171502,8 +1172319,8 @@ function formatWorkflowResult(result) {
1171502
1172319
  }
1171503
1172320
  // src/app/commands/export.ts
1171504
1172321
  await init_formatResults();
1171505
- import { mkdir as mkdir13, writeFile as writeFile6 } from "fs/promises";
1171506
- import path9 from "path";
1172322
+ import { mkdir as mkdir13, writeFile as writeFile7 } from "fs/promises";
1172323
+ import path10 from "path";
1171507
1172324
  var EXPORT_DIR = "exports";
1171508
1172325
  function normalizeFormat(format2, fallback) {
1171509
1172326
  if (!format2)
@@ -1171521,17 +1172338,17 @@ function nowStamp() {
1171521
1172338
  return `${now2.getFullYear()}${pad7(now2.getMonth() + 1)}${pad7(now2.getDate())}-${pad7(now2.getHours())}${pad7(now2.getMinutes())}${pad7(now2.getSeconds())}`;
1171522
1172339
  }
1171523
1172340
  function resolveOutputPath(type2, ext, filename) {
1171524
- const baseDir = path9.join(process.cwd(), EXPORT_DIR);
1172341
+ const baseDir = path10.join(process.cwd(), EXPORT_DIR);
1171525
1172342
  if (!filename) {
1171526
1172343
  return {
1171527
- filePath: path9.join(baseDir, `${type2}-${nowStamp()}.${ext}`),
1172344
+ filePath: path10.join(baseDir, `${type2}-${nowStamp()}.${ext}`),
1171528
1172345
  dir: baseDir
1171529
1172346
  };
1171530
1172347
  }
1171531
- const hasExt = path9.extname(filename).length > 0;
1172348
+ const hasExt = path10.extname(filename).length > 0;
1171532
1172349
  const finalName = hasExt ? filename : `${filename}.${ext}`;
1171533
- const filePath = path9.isAbsolute(finalName) ? finalName : path9.join(baseDir, finalName);
1171534
- return { filePath, dir: path9.dirname(filePath) };
1172350
+ const filePath = path10.isAbsolute(finalName) ? finalName : path10.join(baseDir, finalName);
1172351
+ return { filePath, dir: path10.dirname(filePath) };
1171535
1172352
  }
1171536
1172353
  function escapeCsv(value) {
1171537
1172354
  const text5 = String(value ?? "");
@@ -1171598,7 +1172415,7 @@ async function handleExportCommand(args, ctx) {
1171598
1172415
  }
1171599
1172416
  const { filePath, dir } = resolveOutputPath("scan", format2, filename);
1171600
1172417
  await mkdir13(dir, { recursive: true });
1171601
- await writeFile6(filePath, content, "utf8");
1172418
+ await writeFile7(filePath, content, "utf8");
1171602
1172419
  return { success: true, message: `Scan export saved: ${filePath}`, path: filePath };
1171603
1172420
  }
1171604
1172421
  case "analysis": {
@@ -1171639,7 +1172456,7 @@ async function handleExportCommand(args, ctx) {
1171639
1172456
  }
1171640
1172457
  const { filePath, dir } = resolveOutputPath("analysis", format2, filename);
1171641
1172458
  await mkdir13(dir, { recursive: true });
1171642
- await writeFile6(filePath, content, "utf8");
1172459
+ await writeFile7(filePath, content, "utf8");
1171643
1172460
  return { success: true, message: `Analysis export saved: ${filePath}`, path: filePath };
1171644
1172461
  }
1171645
1172462
  case "backtest": {
@@ -1171658,7 +1172475,7 @@ async function handleExportCommand(args, ctx) {
1171658
1172475
  }
1171659
1172476
  const { filePath, dir } = resolveOutputPath("backtest", format2, filename);
1171660
1172477
  await mkdir13(dir, { recursive: true });
1171661
- await writeFile6(filePath, content, "utf8");
1172478
+ await writeFile7(filePath, content, "utf8");
1171662
1172479
  return { success: true, message: `Backtest export saved: ${filePath}`, path: filePath };
1171663
1172480
  }
1171664
1172481
  case "session": {
@@ -1171677,7 +1172494,7 @@ async function handleExportCommand(args, ctx) {
1171677
1172494
  }
1171678
1172495
  const { filePath, dir } = resolveOutputPath("session", format2, filename);
1171679
1172496
  await mkdir13(dir, { recursive: true });
1171680
- await writeFile6(filePath, content, "utf8");
1172497
+ await writeFile7(filePath, content, "utf8");
1171681
1172498
  return { success: true, message: `Session export saved: ${filePath}`, path: filePath };
1171682
1172499
  }
1171683
1172500
  default:
@@ -1171691,6 +1172508,7 @@ async function handleExportCommand(args, ctx) {
1171691
1172508
  init_config2();
1171692
1172509
  init_keyring();
1171693
1172510
  // src/app/App.tsx
1172511
+ init_mcp();
1171694
1172512
  await init_formatResults();
1171695
1172513
  init_events2();
1171696
1172514
  init_events2();
@@ -1171931,7 +1172749,7 @@ function AppContent({ onThemeChange }) {
1171931
1172749
  if (envStatus.keys.OPENAI_API_KEY) {
1171932
1172750
  initializeTracing2().catch((err) => console.error("[Tracing] Init failed:", err.message));
1171933
1172751
  }
1171934
- initMCPTools().catch((err) => console.error("[MCP] Failed to init tools:", err.message));
1172752
+ initMCPTools().then(() => initSkills()).catch((err) => console.error("[Skills] Init failed:", err.message));
1171935
1172753
  enableMCPHotReload(5000);
1171936
1172754
  } catch (error48) {
1171937
1172755
  console.error("Failed to initialize LLM client:", error48);
@@ -1172870,6 +1173688,20 @@ Error: ${result.error || "Unknown error"}`,
1172870
1173688
  }));
1172871
1173689
  return;
1172872
1173690
  }
1173691
+ case "handle_skill_command": {
1173692
+ setState((prev) => ({ ...prev, messages: [...prev.messages, userMessage2], isLoading: true }));
1173693
+ const skillArgs = args.trim().length > 0 ? args.trim().split(/\s+/) : [];
1173694
+ const result = await handleSkillCommand(skillArgs);
1173695
+ setState((prev) => ({
1173696
+ ...prev,
1173697
+ messages: [
1173698
+ ...prev.messages,
1173699
+ { role: "gordon", content: result.message, timestamp: formatTimestamp() }
1173700
+ ],
1173701
+ isLoading: false
1173702
+ }));
1173703
+ return;
1173704
+ }
1172873
1173705
  case "handle_workflow_command": {
1172874
1173706
  if (!exchangeRef.current) {
1172875
1173707
  setState((prev) => ({
@@ -1173787,16 +1174619,16 @@ init_database();
1173787
1174619
  // src/utils/update-notifier.ts
1173788
1174620
  init_paths();
1173789
1174621
  init_cli();
1173790
- import * as fs11 from "fs";
1173791
- import * as path10 from "path";
1173792
- var UPDATE_CHECK_FILE = path10.join(GORDON_DIR, ".update-check");
1174622
+ import * as fs12 from "fs";
1174623
+ import * as path11 from "path";
1174624
+ var UPDATE_CHECK_FILE = path11.join(GORDON_DIR, ".update-check");
1173793
1174625
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
1173794
1174626
  var PACKAGE_NAME2 = "@general-liquidity/gordon-cli";
1173795
1174627
  var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME2}/latest`;
1173796
1174628
  function loadState2() {
1173797
1174629
  try {
1173798
- if (fs11.existsSync(UPDATE_CHECK_FILE)) {
1173799
- const data = fs11.readFileSync(UPDATE_CHECK_FILE, "utf-8");
1174630
+ if (fs12.existsSync(UPDATE_CHECK_FILE)) {
1174631
+ const data = fs12.readFileSync(UPDATE_CHECK_FILE, "utf-8");
1173800
1174632
  return JSON.parse(data);
1173801
1174633
  }
1173802
1174634
  } catch {}
@@ -1173804,8 +1174636,8 @@ function loadState2() {
1173804
1174636
  }
1173805
1174637
  function saveState2(state3) {
1173806
1174638
  try {
1173807
- fs11.mkdirSync(GORDON_DIR, { recursive: true });
1173808
- fs11.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(state3), "utf-8");
1174639
+ fs12.mkdirSync(GORDON_DIR, { recursive: true });
1174640
+ fs12.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(state3), "utf-8");
1173809
1174641
  } catch {}
1173810
1174642
  }
1173811
1174643
  function shouldCheck(state3) {
@@ -1173867,7 +1174699,7 @@ async function checkForUpdates() {
1173867
1174699
 
1173868
1174700
  // src/index.tsx
1173869
1174701
  init_telemetry2();
1173870
- init_client13();
1174702
+ await init_client14();
1173871
1174703
  var jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
1173872
1174704
  var flags = parseFlags();
1173873
1174705
  var command = parseCommand();