@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.
- package/dist/gordon.js +1607 -775
- 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
|
|
287121
|
-
const data = await dexScreenerFetch(`/token-pairs/v1
|
|
287122
|
-
return (data.pairs ?? []).filter((p) => p.chainId ===
|
|
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
|
|
287133
|
+
async function searchDexPairs(query, chain, dex) {
|
|
287125
287134
|
const data = await dexScreenerFetch(`/latest/dex/search?q=${encodeURIComponent(query)}`);
|
|
287126
|
-
|
|
287127
|
-
|
|
287128
|
-
|
|
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
|
|
287133
|
-
return (data.pairs ?? []).filter((p) => p.chainId ===
|
|
287146
|
+
const data = await dexScreenerFetch(`/tokens/v1/${chain}/${batch}`);
|
|
287147
|
+
return (data.pairs ?? []).filter((p) => p.chainId === chain);
|
|
287134
287148
|
}
|
|
287135
|
-
async function
|
|
287149
|
+
async function getNewTokens(chain) {
|
|
287136
287150
|
const data = await dexScreenerFetch(`/token-profiles/latest/v1`);
|
|
287137
|
-
|
|
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
|
|
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
|
|
1142434
|
+
var init_client13 = __esm(() => {
|
|
1142113
1142435
|
init_protocol3();
|
|
1142114
1142436
|
init_types19();
|
|
1142115
1142437
|
init_ajv_provider();
|
|
1142116
1142438
|
init_zod_compat();
|
|
1142117
|
-
|
|
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
|
-
|
|
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
|
|
1151553
|
-
|
|
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
|
|
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
|
-
|
|
1152575
|
-
|
|
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
|
|
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
|
|
1154710
|
-
import { join as
|
|
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 =
|
|
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:
|
|
1154721
|
-
{ path:
|
|
1154722
|
-
{ path:
|
|
1154723
|
-
{ path:
|
|
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
|
|
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
|
-
|
|
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
|
|
1157820
|
-
import * as
|
|
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 =
|
|
1157917
|
-
var MACHINE_ID_FILE =
|
|
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 (
|
|
1157921
|
-
const stored =
|
|
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
|
-
|
|
1157927
|
-
|
|
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 (!
|
|
1159228
|
+
if (!fs11.existsSync(LICENSE_FILE))
|
|
1157941
1159229
|
return null;
|
|
1157942
|
-
const data =
|
|
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
|
-
|
|
1157953
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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/
|
|
1168367
|
-
|
|
1168368
|
-
init_installer();
|
|
1169706
|
+
// src/app/commands/index.ts
|
|
1169707
|
+
init_mcp();
|
|
1168369
1169708
|
|
|
1168370
|
-
// src/app/commands/
|
|
1169709
|
+
// src/app/commands/skill.ts
|
|
1169710
|
+
init_installer();
|
|
1169711
|
+
init_registry5();
|
|
1168371
1169712
|
init_credentials();
|
|
1168372
|
-
|
|
1168373
|
-
|
|
1168374
|
-
|
|
1168375
|
-
|
|
1168376
|
-
|
|
1168377
|
-
|
|
1168378
|
-
|
|
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
|
-
|
|
1168423
|
-
|
|
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
|
|
1168474
|
-
|
|
1168475
|
-
|
|
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:
|
|
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
|
-
|
|
1168537
|
-
|
|
1168538
|
-
|
|
1168539
|
-
|
|
1168540
|
-
|
|
1168541
|
-
|
|
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
|
|
1168578
|
-
|
|
1168579
|
-
|
|
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: `
|
|
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: `
|
|
1169759
|
+
message: `Skill "${pluginId}" is already installed. Use "/skill route ${pluginId} <agent>" to change routing.`
|
|
1168651
1169760
|
};
|
|
1168652
1169761
|
}
|
|
1168653
|
-
|
|
1168654
|
-
|
|
1168655
|
-
|
|
1168656
|
-
|
|
1168657
|
-
|
|
1168658
|
-
|
|
1168659
|
-
|
|
1168660
|
-
|
|
1168661
|
-
|
|
1168662
|
-
|
|
1168663
|
-
|
|
1168664
|
-
|
|
1168665
|
-
|
|
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
|
|
1168682
|
-
|
|
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: `
|
|
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: `
|
|
1169788
|
+
message: `Invalid agent "${agentName}". Valid: ${VALID_AGENTS.join(", ")}`
|
|
1168763
1169789
|
};
|
|
1168764
1169790
|
}
|
|
1168765
|
-
|
|
1168766
|
-
|
|
1168767
|
-
|
|
1168768
|
-
|
|
1168769
|
-
|
|
1168770
|
-
|
|
1168771
|
-
|
|
1168772
|
-
|
|
1168773
|
-
|
|
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
|
|
1168789
|
-
|
|
1168790
|
-
|
|
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: `
|
|
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
|
|
1168914
|
-
|
|
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: `
|
|
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
|
|
1168951
|
-
|
|
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: `
|
|
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
|
|
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
|
|
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 (
|
|
1169847
|
+
case "add": {
|
|
1169848
|
+
if (!subArgs[0]) {
|
|
1169048
1169849
|
return {
|
|
1169049
1169850
|
success: false,
|
|
1169050
|
-
message: "Usage: /
|
|
1169851
|
+
message: "Usage: /skill install <id> [--agent <name>]"
|
|
1169051
1169852
|
};
|
|
1169052
1169853
|
}
|
|
1169053
|
-
|
|
1169054
|
-
|
|
1169055
|
-
|
|
1169056
|
-
|
|
1169057
|
-
|
|
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:
|
|
1169873
|
+
message: `Usage: /skill route <id> <agent>
|
|
1169874
|
+
Agents: ${VALID_AGENTS.join(", ")}`
|
|
1169061
1169875
|
};
|
|
1169062
1169876
|
}
|
|
1169063
|
-
return
|
|
1169064
|
-
|
|
1169065
|
-
case "
|
|
1169066
|
-
|
|
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: /
|
|
1169885
|
+
message: "Usage: /skill uninstall <id>"
|
|
1169070
1169886
|
};
|
|
1169071
1169887
|
}
|
|
1169072
|
-
return
|
|
1169888
|
+
return skillUninstall(subArgs[0]);
|
|
1169073
1169889
|
case "enable":
|
|
1169074
|
-
if (
|
|
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
|
|
1169893
|
+
return skillEnable(subArgs[0]);
|
|
1169081
1169894
|
case "disable":
|
|
1169082
|
-
if (
|
|
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
|
|
1169089
|
-
case "
|
|
1169090
|
-
case "
|
|
1169091
|
-
|
|
1169092
|
-
|
|
1169093
|
-
|
|
1169094
|
-
|
|
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: /
|
|
1169909
|
+
message: "Usage: /skill configure <id>"
|
|
1169098
1169910
|
};
|
|
1169099
1169911
|
}
|
|
1169100
|
-
|
|
1169101
|
-
|
|
1169102
|
-
|
|
1169103
|
-
case "
|
|
1169104
|
-
|
|
1169105
|
-
|
|
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
|
-
|
|
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: `
|
|
1169119
|
-
/
|
|
1169120
|
-
/
|
|
1169121
|
-
/
|
|
1169122
|
-
/
|
|
1169123
|
-
/
|
|
1169124
|
-
/
|
|
1169125
|
-
/
|
|
1169126
|
-
/
|
|
1169127
|
-
/
|
|
1169128
|
-
|
|
1169129
|
-
|
|
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
|
|
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
|
|
1171506
|
-
import
|
|
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 =
|
|
1172341
|
+
const baseDir = path10.join(process.cwd(), EXPORT_DIR);
|
|
1171525
1172342
|
if (!filename) {
|
|
1171526
1172343
|
return {
|
|
1171527
|
-
filePath:
|
|
1172344
|
+
filePath: path10.join(baseDir, `${type2}-${nowStamp()}.${ext}`),
|
|
1171528
1172345
|
dir: baseDir
|
|
1171529
1172346
|
};
|
|
1171530
1172347
|
}
|
|
1171531
|
-
const hasExt =
|
|
1172348
|
+
const hasExt = path10.extname(filename).length > 0;
|
|
1171532
1172349
|
const finalName = hasExt ? filename : `${filename}.${ext}`;
|
|
1171533
|
-
const filePath =
|
|
1171534
|
-
return { filePath, dir:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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("[
|
|
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
|
|
1173791
|
-
import * as
|
|
1173792
|
-
var UPDATE_CHECK_FILE =
|
|
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 (
|
|
1173799
|
-
const data =
|
|
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
|
-
|
|
1173808
|
-
|
|
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
|
-
|
|
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();
|