clodds 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -47
- package/dist/agents/handlers/kalshi.d.ts +1 -2
- package/dist/agents/handlers/kalshi.js +369 -616
- package/dist/agents/handlers/kalshi.js.map +1 -1
- package/dist/agents/handlers/types.d.ts +1 -1
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.js +435 -710
- package/dist/agents/index.js.map +1 -1
- package/dist/bittensor/index.d.ts +3 -2
- package/dist/bittensor/index.js +44 -5
- package/dist/bittensor/index.js.map +1 -1
- package/dist/cli/commands/gateway.js +37 -2
- package/dist/cli/commands/gateway.js.map +1 -1
- package/dist/cli/commands/index.js +3 -2
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/index.js +6 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cron/index.d.ts +1 -1
- package/dist/cron/index.js +26 -34
- package/dist/cron/index.js.map +1 -1
- package/dist/db/index.d.ts +12 -0
- package/dist/db/index.js +51 -23
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.js +36 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/evm/index.d.ts +1 -0
- package/dist/evm/index.js +2 -0
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/pancakeswap.d.ts +55 -0
- package/dist/evm/pancakeswap.js +299 -0
- package/dist/evm/pancakeswap.js.map +1 -0
- package/dist/exchanges/lighter/index.d.ts +95 -0
- package/dist/exchanges/lighter/index.js +154 -0
- package/dist/exchanges/lighter/index.js.map +1 -0
- package/dist/gateway/server.d.ts +9 -0
- package/dist/gateway/server.js +208 -1
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/signal-bus.d.ts +2 -43
- package/dist/gateway/signal-bus.js.map +1 -1
- package/dist/index.js +40 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/security.d.ts +44 -0
- package/dist/mcp/security.js +143 -0
- package/dist/mcp/security.js.map +1 -0
- package/dist/mcp/server.js +27 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/services/alt-data/index.d.ts +1 -1
- package/dist/sessions/index.js +66 -7
- package/dist/sessions/index.js.map +1 -1
- package/dist/signal-router/router.d.ts +1 -1
- package/dist/signal-router/types.d.ts +1 -1
- package/dist/skills/bundled/arbitrage/index.js +96 -63
- package/dist/skills/bundled/arbitrage/index.js.map +1 -1
- package/dist/skills/bundled/betfair/index.js +121 -83
- package/dist/skills/bundled/betfair/index.js.map +1 -1
- package/dist/skills/bundled/bridge/index.js +42 -13
- package/dist/skills/bundled/bridge/index.js.map +1 -1
- package/dist/skills/bundled/crypto-hft/index.js +267 -226
- package/dist/skills/bundled/crypto-hft/index.js.map +1 -1
- package/dist/skills/bundled/drift/index.js +83 -52
- package/dist/skills/bundled/drift/index.js.map +1 -1
- package/dist/skills/bundled/embeddings/index.js +87 -49
- package/dist/skills/bundled/embeddings/index.js.map +1 -1
- package/dist/skills/bundled/execution/index.js +47 -25
- package/dist/skills/bundled/execution/index.js.map +1 -1
- package/dist/skills/bundled/feeds/index.js +45 -25
- package/dist/skills/bundled/feeds/index.js.map +1 -1
- package/dist/skills/bundled/hyperliquid/index.js +91 -45
- package/dist/skills/bundled/hyperliquid/index.js.map +1 -1
- package/dist/skills/bundled/integrations/index.js +2 -1
- package/dist/skills/bundled/integrations/index.js.map +1 -1
- package/dist/skills/bundled/kamino/index.js +71 -43
- package/dist/skills/bundled/kamino/index.js.map +1 -1
- package/dist/skills/bundled/lighter/index.d.ts +19 -0
- package/dist/skills/bundled/lighter/index.js +385 -0
- package/dist/skills/bundled/lighter/index.js.map +1 -0
- package/dist/skills/bundled/marginfi/index.d.ts +21 -0
- package/dist/skills/bundled/marginfi/index.js +387 -0
- package/dist/skills/bundled/marginfi/index.js.map +1 -0
- package/dist/skills/bundled/opinion/index.js +44 -25
- package/dist/skills/bundled/opinion/index.js.map +1 -1
- package/dist/skills/bundled/pancakeswap/index.d.ts +19 -0
- package/dist/skills/bundled/pancakeswap/index.js +260 -0
- package/dist/skills/bundled/pancakeswap/index.js.map +1 -0
- package/dist/skills/bundled/setup/index.d.ts +16 -0
- package/dist/skills/bundled/setup/index.js +427 -0
- package/dist/skills/bundled/setup/index.js.map +1 -0
- package/dist/skills/bundled/solend/index.d.ts +22 -0
- package/dist/skills/bundled/solend/index.js +401 -0
- package/dist/skills/bundled/solend/index.js.map +1 -0
- package/dist/skills/bundled/trading-evm/index.js +42 -11
- package/dist/skills/bundled/trading-evm/index.js.map +1 -1
- package/dist/skills/errors.d.ts +20 -0
- package/dist/skills/errors.js +84 -0
- package/dist/skills/errors.js.map +1 -0
- package/dist/skills/executor.d.ts +1 -1
- package/dist/skills/executor.js +515 -41
- package/dist/skills/executor.js.map +1 -1
- package/dist/skills/help.d.ts +33 -0
- package/dist/skills/help.js +73 -0
- package/dist/skills/help.js.map +1 -0
- package/dist/solana/marginfi.d.ts +112 -0
- package/dist/solana/marginfi.js +340 -0
- package/dist/solana/marginfi.js.map +1 -0
- package/dist/solana/solend.d.ts +120 -0
- package/dist/solana/solend.js +261 -0
- package/dist/solana/solend.js.map +1 -0
- package/dist/trading/bridge.d.ts +1 -1
- package/dist/trading/position-bridge.d.ts +1 -1
- package/dist/types/signal-bus.d.ts +48 -0
- package/dist/types/signal-bus.js +9 -0
- package/dist/types/signal-bus.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/utils/json-utils.d.ts +8 -8
- package/package.json +8 -6
package/dist/skills/executor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Skill Executor - Central registry for all
|
|
3
|
+
* Skill Executor - Central registry for all 118 bundled CLI skill handlers.
|
|
4
4
|
*
|
|
5
5
|
* ARCHITECTURE:
|
|
6
6
|
* - Each skill lives in src/skills/bundled/<name>/index.ts
|
|
@@ -117,6 +117,8 @@ const SKILL_MANIFEST = [
|
|
|
117
117
|
'jupiter',
|
|
118
118
|
'kamino',
|
|
119
119
|
'ledger',
|
|
120
|
+
'lighter',
|
|
121
|
+
'marginfi',
|
|
120
122
|
'market-index',
|
|
121
123
|
'markets',
|
|
122
124
|
'mcp',
|
|
@@ -135,6 +137,7 @@ const SKILL_MANIFEST = [
|
|
|
135
137
|
'opportunity',
|
|
136
138
|
'orca',
|
|
137
139
|
'pairing',
|
|
140
|
+
'pancakeswap',
|
|
138
141
|
'percolator',
|
|
139
142
|
'permissions',
|
|
140
143
|
'plugins',
|
|
@@ -162,6 +165,7 @@ const SKILL_MANIFEST = [
|
|
|
162
165
|
'sizing',
|
|
163
166
|
'slippage',
|
|
164
167
|
'smarkets',
|
|
168
|
+
'solend',
|
|
165
169
|
'strategy',
|
|
166
170
|
'streaming',
|
|
167
171
|
'tailscale',
|
|
@@ -189,7 +193,300 @@ const SKILL_MANIFEST = [
|
|
|
189
193
|
'token-security',
|
|
190
194
|
'dca',
|
|
191
195
|
'shield',
|
|
196
|
+
'setup',
|
|
192
197
|
];
|
|
198
|
+
const SKILL_CATEGORIES = {
|
|
199
|
+
// DeFi & DEX
|
|
200
|
+
'pancakeswap': 'DeFi & DEX',
|
|
201
|
+
'bridge': 'DeFi & DEX',
|
|
202
|
+
'trading-evm': 'DeFi & DEX',
|
|
203
|
+
'onchainkit': 'DeFi & DEX',
|
|
204
|
+
'ens': 'DeFi & DEX',
|
|
205
|
+
'erc8004': 'DeFi & DEX',
|
|
206
|
+
'endaoment': 'DeFi & DEX',
|
|
207
|
+
'clanker': 'DeFi & DEX',
|
|
208
|
+
'slippage': 'DeFi & DEX',
|
|
209
|
+
'router': 'DeFi & DEX',
|
|
210
|
+
'mev': 'DeFi & DEX',
|
|
211
|
+
'virtuals': 'DeFi & DEX',
|
|
212
|
+
// Futures & Perps
|
|
213
|
+
'hyperliquid': 'Futures & Perps',
|
|
214
|
+
'lighter': 'Futures & Perps',
|
|
215
|
+
'drift': 'Futures & Perps',
|
|
216
|
+
'drift-sdk': 'Futures & Perps',
|
|
217
|
+
'binance-futures': 'Futures & Perps',
|
|
218
|
+
'bybit-futures': 'Futures & Perps',
|
|
219
|
+
'mexc-futures': 'Futures & Perps',
|
|
220
|
+
'trading-futures': 'Futures & Perps',
|
|
221
|
+
// Prediction Markets
|
|
222
|
+
'trading-polymarket': 'Prediction Markets',
|
|
223
|
+
'betfair': 'Prediction Markets',
|
|
224
|
+
'trading-kalshi': 'Prediction Markets',
|
|
225
|
+
'trading-manifold': 'Prediction Markets',
|
|
226
|
+
'predictfun': 'Prediction Markets',
|
|
227
|
+
'predictit': 'Prediction Markets',
|
|
228
|
+
'smarkets': 'Prediction Markets',
|
|
229
|
+
'metaculus': 'Prediction Markets',
|
|
230
|
+
'veil': 'Prediction Markets',
|
|
231
|
+
'agentbets': 'Prediction Markets',
|
|
232
|
+
'opinion': 'Prediction Markets',
|
|
233
|
+
// Solana DeFi
|
|
234
|
+
'jupiter': 'Solana DeFi',
|
|
235
|
+
'raydium': 'Solana DeFi',
|
|
236
|
+
'orca': 'Solana DeFi',
|
|
237
|
+
'meteora': 'Solana DeFi',
|
|
238
|
+
'meteora-dbc': 'Solana DeFi',
|
|
239
|
+
'pumpfun': 'Solana DeFi',
|
|
240
|
+
'pump-swarm': 'Solana DeFi',
|
|
241
|
+
'kamino': 'Solana DeFi',
|
|
242
|
+
'marginfi': 'Solana DeFi',
|
|
243
|
+
'trading-solana': 'Solana DeFi',
|
|
244
|
+
'copy-trading-solana': 'Solana DeFi',
|
|
245
|
+
'solend': 'Solana DeFi',
|
|
246
|
+
// Portfolio & Risk
|
|
247
|
+
'portfolio': 'Portfolio & Risk',
|
|
248
|
+
'portfolio-sync': 'Portfolio & Risk',
|
|
249
|
+
'positions': 'Portfolio & Risk',
|
|
250
|
+
'bags': 'Portfolio & Risk',
|
|
251
|
+
'risk': 'Portfolio & Risk',
|
|
252
|
+
'sizing': 'Portfolio & Risk',
|
|
253
|
+
'ledger': 'Portfolio & Risk',
|
|
254
|
+
'history': 'Portfolio & Risk',
|
|
255
|
+
'divergence': 'Portfolio & Risk',
|
|
256
|
+
'edge': 'Portfolio & Risk',
|
|
257
|
+
'dca': 'Portfolio & Risk',
|
|
258
|
+
// Data & Feeds
|
|
259
|
+
'feeds': 'Data & Feeds',
|
|
260
|
+
'markets': 'Data & Feeds',
|
|
261
|
+
'market-index': 'Data & Feeds',
|
|
262
|
+
'news': 'Data & Feeds',
|
|
263
|
+
'ticks': 'Data & Feeds',
|
|
264
|
+
'signals': 'Data & Feeds',
|
|
265
|
+
'whale-tracking': 'Data & Feeds',
|
|
266
|
+
'analytics': 'Data & Feeds',
|
|
267
|
+
'metrics': 'Data & Feeds',
|
|
268
|
+
'weather': 'Data & Feeds',
|
|
269
|
+
// AI & Strategy
|
|
270
|
+
'ai-strategy': 'AI & Strategy',
|
|
271
|
+
'strategy': 'AI & Strategy',
|
|
272
|
+
'arbitrage': 'AI & Strategy',
|
|
273
|
+
'copy-trading': 'AI & Strategy',
|
|
274
|
+
'crypto-hft': 'AI & Strategy',
|
|
275
|
+
'execution': 'AI & Strategy',
|
|
276
|
+
'backtest': 'AI & Strategy',
|
|
277
|
+
'pairing': 'AI & Strategy',
|
|
278
|
+
'mm': 'AI & Strategy',
|
|
279
|
+
'opportunity': 'AI & Strategy',
|
|
280
|
+
'research': 'AI & Strategy',
|
|
281
|
+
'embeddings': 'AI & Strategy',
|
|
282
|
+
'features': 'AI & Strategy',
|
|
283
|
+
'trading-system': 'AI & Strategy',
|
|
284
|
+
'percolator': 'AI & Strategy',
|
|
285
|
+
// Infrastructure
|
|
286
|
+
'credentials': 'Infrastructure',
|
|
287
|
+
'automation': 'Infrastructure',
|
|
288
|
+
'monitoring': 'Infrastructure',
|
|
289
|
+
'alerts': 'Infrastructure',
|
|
290
|
+
'triggers': 'Infrastructure',
|
|
291
|
+
'webhooks': 'Infrastructure',
|
|
292
|
+
'streaming': 'Infrastructure',
|
|
293
|
+
'sessions': 'Infrastructure',
|
|
294
|
+
'remote': 'Infrastructure',
|
|
295
|
+
'mcp': 'Infrastructure',
|
|
296
|
+
'plugins': 'Infrastructure',
|
|
297
|
+
'processes': 'Infrastructure',
|
|
298
|
+
'routing': 'Infrastructure',
|
|
299
|
+
'tailscale': 'Infrastructure',
|
|
300
|
+
'search-config': 'Infrastructure',
|
|
301
|
+
'setup': 'Infrastructure',
|
|
302
|
+
// Social & Identity
|
|
303
|
+
'farcaster': 'Social & Identity',
|
|
304
|
+
'identity': 'Social & Identity',
|
|
305
|
+
'presence': 'Social & Identity',
|
|
306
|
+
'botchan': 'Social & Identity',
|
|
307
|
+
'auto-reply': 'Social & Identity',
|
|
308
|
+
'tweet-ideas': 'Social & Identity',
|
|
309
|
+
'voice': 'Social & Identity',
|
|
310
|
+
'tts': 'Social & Identity',
|
|
311
|
+
// Utilities
|
|
312
|
+
'doctor': 'Utilities',
|
|
313
|
+
'usage': 'Utilities',
|
|
314
|
+
'verify': 'Utilities',
|
|
315
|
+
'sandbox': 'Utilities',
|
|
316
|
+
'permissions': 'Utilities',
|
|
317
|
+
'integrations': 'Utilities',
|
|
318
|
+
'memory': 'Utilities',
|
|
319
|
+
'qmd': 'Utilities',
|
|
320
|
+
'qrcoin': 'Utilities',
|
|
321
|
+
'bankr': 'Utilities',
|
|
322
|
+
'yoink': 'Utilities',
|
|
323
|
+
'acp': 'Utilities',
|
|
324
|
+
'harden': 'Utilities',
|
|
325
|
+
// Security
|
|
326
|
+
'token-security': 'Security',
|
|
327
|
+
'shield': 'Security',
|
|
328
|
+
};
|
|
329
|
+
// =============================================================================
|
|
330
|
+
// COMMAND ALIASES — alternative names that map to real commands
|
|
331
|
+
// =============================================================================
|
|
332
|
+
const COMMAND_ALIASES = {
|
|
333
|
+
'/pancakeswap': '/cake',
|
|
334
|
+
'/pancake': '/cake',
|
|
335
|
+
'/hyperliquid': '/hl',
|
|
336
|
+
'/hyper': '/hl',
|
|
337
|
+
'/polymarket': '/poly',
|
|
338
|
+
'/prediction': '/poly',
|
|
339
|
+
'/uniswap': '/swap',
|
|
340
|
+
'/sushiswap': '/swap',
|
|
341
|
+
'/balance': '/bags',
|
|
342
|
+
'/wallet': '/bags',
|
|
343
|
+
'/pnl': '/positions',
|
|
344
|
+
'/trades': '/history',
|
|
345
|
+
'/arb': '/arbitrage',
|
|
346
|
+
'/hft': '/crypto-hft',
|
|
347
|
+
'/bt': '/backtest',
|
|
348
|
+
'/creds': '/credentials',
|
|
349
|
+
'/keys': '/credentials',
|
|
350
|
+
'/mon': '/monitoring',
|
|
351
|
+
'/pricecheck': '/feeds',
|
|
352
|
+
'/sol': '/trading-solana',
|
|
353
|
+
'/solana': '/trading-solana',
|
|
354
|
+
'/evm': '/trading-evm',
|
|
355
|
+
'/kalshi': '/trading-kalshi',
|
|
356
|
+
'/manifold': '/trading-manifold',
|
|
357
|
+
'/security': '/token-security',
|
|
358
|
+
'/audit': '/token-security',
|
|
359
|
+
'/config': '/setup',
|
|
360
|
+
'/onboard': '/setup',
|
|
361
|
+
'/start': '/setup',
|
|
362
|
+
'/mrg': '/marginfi',
|
|
363
|
+
};
|
|
364
|
+
// =============================================================================
|
|
365
|
+
// ENV VAR DOCUMENTATION — describes what each var is for
|
|
366
|
+
// =============================================================================
|
|
367
|
+
const ENV_VAR_DOCS = {
|
|
368
|
+
EVM_PRIVATE_KEY: {
|
|
369
|
+
description: 'Private key for EVM chains (ETH, BSC, ARB, Base)',
|
|
370
|
+
example: 'export EVM_PRIVATE_KEY="0xabcdef..."',
|
|
371
|
+
},
|
|
372
|
+
SOLANA_PRIVATE_KEY: {
|
|
373
|
+
description: 'Base58 private key for Solana transactions',
|
|
374
|
+
example: 'export SOLANA_PRIVATE_KEY="5abc..."',
|
|
375
|
+
},
|
|
376
|
+
SOLANA_KEYPAIR_PATH: {
|
|
377
|
+
description: 'Path to Solana keypair JSON file (alternative to SOLANA_PRIVATE_KEY)',
|
|
378
|
+
example: 'export SOLANA_KEYPAIR_PATH="~/.config/solana/id.json"',
|
|
379
|
+
},
|
|
380
|
+
HYPERLIQUID_PRIVATE_KEY: {
|
|
381
|
+
description: 'Private key for Hyperliquid L1',
|
|
382
|
+
example: 'export HYPERLIQUID_PRIVATE_KEY="0xabcdef..."',
|
|
383
|
+
},
|
|
384
|
+
HYPERLIQUID_WALLET: {
|
|
385
|
+
description: 'Wallet address on Hyperliquid (for vault/sub-account trading)',
|
|
386
|
+
example: 'export HYPERLIQUID_WALLET="0x1234..."',
|
|
387
|
+
},
|
|
388
|
+
LIGHTER_API_KEY: {
|
|
389
|
+
description: 'API key for Lighter DEX (optional, increases rate limits)',
|
|
390
|
+
example: 'export LIGHTER_API_KEY="your-api-key"',
|
|
391
|
+
url: 'https://lighter.xyz',
|
|
392
|
+
},
|
|
393
|
+
POLY_API_KEY: {
|
|
394
|
+
description: 'Polymarket CLOB API key',
|
|
395
|
+
example: 'export POLY_API_KEY="your-key"',
|
|
396
|
+
url: 'https://docs.polymarket.com',
|
|
397
|
+
},
|
|
398
|
+
POLY_API_SECRET: {
|
|
399
|
+
description: 'Polymarket CLOB API secret',
|
|
400
|
+
example: 'export POLY_API_SECRET="your-secret"',
|
|
401
|
+
},
|
|
402
|
+
POLY_API_PASSPHRASE: {
|
|
403
|
+
description: 'Polymarket CLOB API passphrase',
|
|
404
|
+
example: 'export POLY_API_PASSPHRASE="your-passphrase"',
|
|
405
|
+
},
|
|
406
|
+
OPENAI_API_KEY: {
|
|
407
|
+
description: 'OpenAI API key for embeddings and AI features',
|
|
408
|
+
example: 'export OPENAI_API_KEY="sk-..."',
|
|
409
|
+
url: 'https://platform.openai.com/api-keys',
|
|
410
|
+
},
|
|
411
|
+
BETFAIR_APP_KEY: {
|
|
412
|
+
description: 'Betfair application key',
|
|
413
|
+
example: 'export BETFAIR_APP_KEY="your-app-key"',
|
|
414
|
+
url: 'https://developer.betfair.com',
|
|
415
|
+
},
|
|
416
|
+
BETFAIR_SESSION_TOKEN: {
|
|
417
|
+
description: 'Betfair session token for authenticated requests',
|
|
418
|
+
example: 'export BETFAIR_SESSION_TOKEN="your-token"',
|
|
419
|
+
},
|
|
420
|
+
BINANCE_API_KEY: {
|
|
421
|
+
description: 'Binance API key for futures trading',
|
|
422
|
+
example: 'export BINANCE_API_KEY="your-key"',
|
|
423
|
+
url: 'https://www.binance.com/en/my/settings/api-management',
|
|
424
|
+
},
|
|
425
|
+
BINANCE_API_SECRET: {
|
|
426
|
+
description: 'Binance API secret',
|
|
427
|
+
example: 'export BINANCE_API_SECRET="your-secret"',
|
|
428
|
+
},
|
|
429
|
+
BYBIT_API_KEY: {
|
|
430
|
+
description: 'Bybit API key for derivatives trading',
|
|
431
|
+
example: 'export BYBIT_API_KEY="your-key"',
|
|
432
|
+
url: 'https://www.bybit.com/app/user/api-management',
|
|
433
|
+
},
|
|
434
|
+
BYBIT_API_SECRET: {
|
|
435
|
+
description: 'Bybit API secret',
|
|
436
|
+
example: 'export BYBIT_API_SECRET="your-secret"',
|
|
437
|
+
},
|
|
438
|
+
MEXC_API_KEY: {
|
|
439
|
+
description: 'MEXC API key for futures trading',
|
|
440
|
+
example: 'export MEXC_API_KEY="your-key"',
|
|
441
|
+
url: 'https://www.mexc.com/user/openapi',
|
|
442
|
+
},
|
|
443
|
+
MEXC_API_SECRET: {
|
|
444
|
+
description: 'MEXC API secret',
|
|
445
|
+
example: 'export MEXC_API_SECRET="your-secret"',
|
|
446
|
+
},
|
|
447
|
+
DRY_RUN: {
|
|
448
|
+
description: 'When "true", simulates trades without executing',
|
|
449
|
+
example: 'export DRY_RUN="true"',
|
|
450
|
+
},
|
|
451
|
+
CLODDS_CREDENTIAL_KEY: {
|
|
452
|
+
description: 'Encryption key for credential storage (AES-256-GCM)',
|
|
453
|
+
example: 'export CLODDS_CREDENTIAL_KEY="your-32-char-key"',
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
// =============================================================================
|
|
457
|
+
// SKILL RELATIONS — maps skills to related skills for "See Also"
|
|
458
|
+
// =============================================================================
|
|
459
|
+
const SKILL_RELATIONS = {
|
|
460
|
+
'pancakeswap': ['trading-evm', 'bridge', 'bags', 'slippage'],
|
|
461
|
+
'lighter': ['hyperliquid', 'drift', 'trading-futures', 'positions'],
|
|
462
|
+
'hyperliquid': ['lighter', 'drift', 'binance-futures', 'positions', 'copy-trading'],
|
|
463
|
+
'drift': ['hyperliquid', 'lighter', 'trading-solana', 'positions'],
|
|
464
|
+
'trading-polymarket': ['betfair', 'trading-kalshi', 'predictfun', 'feeds', 'arbitrage'],
|
|
465
|
+
'betfair': ['trading-polymarket', 'smarkets', 'trading-kalshi', 'arbitrage'],
|
|
466
|
+
'trading-kalshi': ['trading-polymarket', 'betfair', 'predictit'],
|
|
467
|
+
'jupiter': ['raydium', 'orca', 'trading-solana', 'bags', 'kamino', 'marginfi', 'solend'],
|
|
468
|
+
'marginfi': ['kamino', 'solend', 'jupiter', 'bags'],
|
|
469
|
+
'raydium': ['jupiter', 'orca', 'meteora', 'pumpfun'],
|
|
470
|
+
'portfolio': ['positions', 'bags', 'history', 'risk'],
|
|
471
|
+
'positions': ['portfolio', 'bags', 'risk', 'history'],
|
|
472
|
+
'bags': ['portfolio', 'positions', 'trading-solana', 'trading-evm'],
|
|
473
|
+
'arbitrage': ['trading-polymarket', 'betfair', 'feeds', 'signals'],
|
|
474
|
+
'bridge': ['trading-evm', 'pancakeswap', 'bags'],
|
|
475
|
+
'credentials': ['setup', 'doctor'],
|
|
476
|
+
'doctor': ['setup', 'credentials', 'monitoring'],
|
|
477
|
+
'copy-trading': ['hyperliquid', 'crypto-hft', 'execution'],
|
|
478
|
+
'binance-futures': ['bybit-futures', 'mexc-futures', 'hyperliquid', 'trading-futures'],
|
|
479
|
+
'bybit-futures': ['binance-futures', 'mexc-futures', 'hyperliquid'],
|
|
480
|
+
'mexc-futures': ['binance-futures', 'bybit-futures', 'hyperliquid'],
|
|
481
|
+
'feeds': ['markets', 'signals', 'news', 'ticks'],
|
|
482
|
+
'signals': ['feeds', 'strategy', 'alerts', 'triggers'],
|
|
483
|
+
'risk': ['sizing', 'portfolio', 'positions'],
|
|
484
|
+
'setup': ['credentials', 'doctor'],
|
|
485
|
+
'token-security': ['shield', 'verify'],
|
|
486
|
+
'shield': ['token-security', 'harden'],
|
|
487
|
+
'solend': ['kamino', 'marginfi', 'jupiter', 'bags'],
|
|
488
|
+
'kamino': ['marginfi', 'solend', 'jupiter', 'bags'],
|
|
489
|
+
};
|
|
193
490
|
/** Normalize skill handler to consistent interface */
|
|
194
491
|
function normalizeSkill(skill) {
|
|
195
492
|
// Normalize commands array (some skills have {name,description,usage} format)
|
|
@@ -207,7 +504,28 @@ function normalizeSkill(skill) {
|
|
|
207
504
|
wrappedHandle = async (args) => {
|
|
208
505
|
const missing = requiredEnv.filter((v) => !process.env[v]);
|
|
209
506
|
if (missing.length > 0) {
|
|
210
|
-
|
|
507
|
+
const lines = [`**${skill.name}** requires configuration:\n`];
|
|
508
|
+
for (const v of missing) {
|
|
509
|
+
const doc = ENV_VAR_DOCS[v];
|
|
510
|
+
if (doc) {
|
|
511
|
+
lines.push(` ${v} — ${doc.description}`);
|
|
512
|
+
lines.push(` ${doc.example}`);
|
|
513
|
+
if (doc.url)
|
|
514
|
+
lines.push(` Docs: ${doc.url}`);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
lines.push(` ${v}`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
lines.push('\nSet these in your environment or .env file.');
|
|
521
|
+
// Suggest /setup if available
|
|
522
|
+
const related = SKILL_RELATIONS[skill.name];
|
|
523
|
+
if (related) {
|
|
524
|
+
const suggestions = related.slice(0, 3).map(r => `/${r}`);
|
|
525
|
+
lines.push(`\nSee also: ${suggestions.join(', ')}`);
|
|
526
|
+
}
|
|
527
|
+
lines.push('Run /setup to configure all skills interactively.');
|
|
528
|
+
return lines.join('\n');
|
|
211
529
|
}
|
|
212
530
|
return boundHandle(args);
|
|
213
531
|
};
|
|
@@ -297,53 +615,201 @@ async function initializeSkills() {
|
|
|
297
615
|
return initializing;
|
|
298
616
|
}
|
|
299
617
|
/**
|
|
300
|
-
* Register the built-in /skills command
|
|
618
|
+
* Register the built-in /skills command with categories, search, and status
|
|
301
619
|
*/
|
|
302
620
|
function registerBuiltinSkillsCommand() {
|
|
303
621
|
const skillsHandler = {
|
|
304
622
|
name: 'skills-status',
|
|
305
|
-
description: '
|
|
623
|
+
description: 'Browse, search, and check status of all skills',
|
|
306
624
|
commands: ['/skills'],
|
|
307
|
-
handle: async (
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (reqs && reqs.length > 0) {
|
|
317
|
-
const missing = reqs.filter((v) => !process.env[v]);
|
|
318
|
-
if (missing.length > 0) {
|
|
319
|
-
needsConfig.push(` ⚙ ${skill.name} — needs: ${missing.join(', ')}`);
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
ready.push(` ✓ ${skill.name}`);
|
|
324
|
-
}
|
|
325
|
-
lines.push(`## Ready (${ready.length})`);
|
|
326
|
-
if (ready.length > 0) {
|
|
327
|
-
lines.push(ready.join('\n'));
|
|
625
|
+
handle: async (args) => {
|
|
626
|
+
const parts = args.trim().split(/\s+/);
|
|
627
|
+
const subCmd = parts[0]?.toLowerCase();
|
|
628
|
+
// /skills search <query>
|
|
629
|
+
if (subCmd === 'search' || subCmd === 'find' || subCmd === 'grep') {
|
|
630
|
+
const query = parts.slice(1).join(' ').toLowerCase();
|
|
631
|
+
if (!query)
|
|
632
|
+
return 'Usage: /skills search <query>\nExample: /skills search swap';
|
|
633
|
+
return handleSkillSearch(query);
|
|
328
634
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
635
|
+
// /skills <category>
|
|
636
|
+
if (subCmd && subCmd !== 'status' && subCmd !== 'all' && subCmd !== '') {
|
|
637
|
+
const categories = Object.values(SKILL_CATEGORIES);
|
|
638
|
+
const matchedCat = categories.find(c => c.toLowerCase().includes(subCmd) || c.toLowerCase().replace(/[&\s]/g, '').includes(subCmd));
|
|
639
|
+
if (matchedCat)
|
|
640
|
+
return handleSkillCategory(matchedCat);
|
|
641
|
+
// Maybe they typed a skill name
|
|
642
|
+
const matchedSkill = registeredSkills.find(s => s.name.includes(subCmd) || s.commands.some(c => c.includes(subCmd)));
|
|
643
|
+
if (matchedSkill)
|
|
644
|
+
return handleSkillInfo(matchedSkill);
|
|
645
|
+
// Fuzzy search fallback
|
|
646
|
+
return handleSkillSearch(subCmd);
|
|
332
647
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
for (const f of failedSkills) {
|
|
336
|
-
// Truncate long error messages
|
|
337
|
-
const shortErr = f.error.length > 80 ? f.error.slice(0, 77) + '...' : f.error;
|
|
338
|
-
lines.push(` ✗ ${f.name} — ${shortErr}`);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
lines.push(`\n**Total:** ${registeredSkills.length - 1} loaded, ${failedSkills.length} failed, ${SKILL_MANIFEST.length} in manifest`);
|
|
342
|
-
return lines.join('\n');
|
|
648
|
+
// /skills (default) — categorized overview
|
|
649
|
+
return handleSkillOverview();
|
|
343
650
|
},
|
|
344
651
|
};
|
|
345
652
|
registerSkill(skillsHandler);
|
|
346
653
|
}
|
|
654
|
+
function handleSkillOverview() {
|
|
655
|
+
const lines = ['**Skills Directory**\n'];
|
|
656
|
+
// Group by category
|
|
657
|
+
const grouped = new Map();
|
|
658
|
+
for (const skill of registeredSkills) {
|
|
659
|
+
if (skill.name === 'skills-status')
|
|
660
|
+
continue;
|
|
661
|
+
const cat = SKILL_CATEGORIES[skill.name] || 'Utilities';
|
|
662
|
+
if (!grouped.has(cat)) {
|
|
663
|
+
grouped.set(cat, []);
|
|
664
|
+
}
|
|
665
|
+
const reqs = skillRequirements.get(skill.name);
|
|
666
|
+
const ready = !reqs || reqs.length === 0 || reqs.every((v) => !!process.env[v]);
|
|
667
|
+
grouped.get(cat).push({
|
|
668
|
+
name: skill.name,
|
|
669
|
+
cmds: skill.commands,
|
|
670
|
+
ready,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
// Category display order
|
|
674
|
+
const categoryOrder = [
|
|
675
|
+
'Futures & Perps', 'DeFi & DEX', 'Solana DeFi', 'Prediction Markets',
|
|
676
|
+
'AI & Strategy', 'Portfolio & Risk', 'Data & Feeds', 'Security',
|
|
677
|
+
'Infrastructure', 'Social & Identity', 'Utilities',
|
|
678
|
+
];
|
|
679
|
+
for (const cat of categoryOrder) {
|
|
680
|
+
const skills = grouped.get(cat);
|
|
681
|
+
if (!skills || skills.length === 0)
|
|
682
|
+
continue;
|
|
683
|
+
const readyCount = skills.filter(s => s.ready).length;
|
|
684
|
+
lines.push(`**${cat}** (${readyCount}/${skills.length} ready)`);
|
|
685
|
+
for (const s of skills) {
|
|
686
|
+
const status = s.ready ? '+' : '-';
|
|
687
|
+
const cmds = s.cmds.map(c => `/${c}`).join(', ');
|
|
688
|
+
lines.push(` ${status} ${s.name} (${cmds})`);
|
|
689
|
+
}
|
|
690
|
+
lines.push('');
|
|
691
|
+
}
|
|
692
|
+
// Failed skills
|
|
693
|
+
if (failedSkills.length > 0) {
|
|
694
|
+
lines.push(`**Failed to Load** (${failedSkills.length})`);
|
|
695
|
+
for (const f of failedSkills) {
|
|
696
|
+
const shortErr = f.error.length > 60 ? f.error.slice(0, 57) + '...' : f.error;
|
|
697
|
+
lines.push(` x ${f.name} — ${shortErr}`);
|
|
698
|
+
}
|
|
699
|
+
lines.push('');
|
|
700
|
+
}
|
|
701
|
+
const total = registeredSkills.length - 1;
|
|
702
|
+
lines.push(`**Total:** ${total} loaded, ${failedSkills.length} failed`);
|
|
703
|
+
lines.push('');
|
|
704
|
+
lines.push('**Commands:**');
|
|
705
|
+
lines.push(' /skills <category> — Browse a category (e.g., /skills defi)');
|
|
706
|
+
lines.push(' /skills search <query> — Search skills by name or keyword');
|
|
707
|
+
lines.push(' /skills <name> — Info about a specific skill');
|
|
708
|
+
lines.push(' /setup — Configure environment for skills');
|
|
709
|
+
return lines.join('\n');
|
|
710
|
+
}
|
|
711
|
+
function handleSkillSearch(query) {
|
|
712
|
+
const results = [];
|
|
713
|
+
for (const skill of registeredSkills) {
|
|
714
|
+
if (skill.name === 'skills-status')
|
|
715
|
+
continue;
|
|
716
|
+
const searchable = `${skill.name} ${skill.description} ${skill.commands.join(' ')}`.toLowerCase();
|
|
717
|
+
const cat = SKILL_CATEGORIES[skill.name] || 'Utilities';
|
|
718
|
+
if (searchable.includes(query)) {
|
|
719
|
+
results.push({
|
|
720
|
+
name: skill.name,
|
|
721
|
+
cmds: skill.commands,
|
|
722
|
+
desc: skill.description,
|
|
723
|
+
cat,
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
if (results.length === 0) {
|
|
728
|
+
return `No skills found matching "${query}". Try /skills to browse all categories.`;
|
|
729
|
+
}
|
|
730
|
+
const lines = [`**Search results for "${query}"** (${results.length} found)\n`];
|
|
731
|
+
for (const r of results) {
|
|
732
|
+
const cmds = r.cmds.map(c => `/${c}`).join(', ');
|
|
733
|
+
lines.push(` ${r.name} (${cmds}) — ${r.desc}`);
|
|
734
|
+
lines.push(` Category: ${r.cat}`);
|
|
735
|
+
}
|
|
736
|
+
return lines.join('\n');
|
|
737
|
+
}
|
|
738
|
+
function handleSkillCategory(category) {
|
|
739
|
+
const skills = [];
|
|
740
|
+
for (const skill of registeredSkills) {
|
|
741
|
+
if (skill.name === 'skills-status')
|
|
742
|
+
continue;
|
|
743
|
+
const cat = SKILL_CATEGORIES[skill.name];
|
|
744
|
+
if (cat !== category)
|
|
745
|
+
continue;
|
|
746
|
+
const reqs = skillRequirements.get(skill.name);
|
|
747
|
+
const ready = !reqs || reqs.length === 0 || reqs.every((v) => !!process.env[v]);
|
|
748
|
+
skills.push({ name: skill.name, cmds: skill.commands, desc: skill.description, ready });
|
|
749
|
+
}
|
|
750
|
+
if (skills.length === 0) {
|
|
751
|
+
return `No skills in category "${category}".`;
|
|
752
|
+
}
|
|
753
|
+
const lines = [`**${category}** (${skills.length} skills)\n`];
|
|
754
|
+
for (const s of skills) {
|
|
755
|
+
const status = s.ready ? '+' : '-';
|
|
756
|
+
const cmds = s.cmds.map(c => `/${c}`).join(', ');
|
|
757
|
+
lines.push(` ${status} **${s.name}** (${cmds})`);
|
|
758
|
+
lines.push(` ${s.desc}`);
|
|
759
|
+
const reqs = skillRequirements.get(s.name);
|
|
760
|
+
if (reqs && reqs.length > 0) {
|
|
761
|
+
const missing = reqs.filter(v => !process.env[v]);
|
|
762
|
+
if (missing.length > 0) {
|
|
763
|
+
lines.push(` Needs: ${missing.join(', ')}`);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
const related = SKILL_RELATIONS[s.name];
|
|
767
|
+
if (related) {
|
|
768
|
+
lines.push(` See also: ${related.slice(0, 3).map(r => `/${r}`).join(', ')}`);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return lines.join('\n');
|
|
772
|
+
}
|
|
773
|
+
function handleSkillInfo(skill) {
|
|
774
|
+
const lines = [`**${skill.name}**`];
|
|
775
|
+
lines.push(skill.description);
|
|
776
|
+
lines.push('');
|
|
777
|
+
const cat = SKILL_CATEGORIES[skill.name] || 'Utilities';
|
|
778
|
+
lines.push(`Category: ${cat}`);
|
|
779
|
+
lines.push(`Commands: ${skill.commands.map(c => `/${c}`).join(', ')}`);
|
|
780
|
+
const reqs = skillRequirements.get(skill.name);
|
|
781
|
+
if (reqs && reqs.length > 0) {
|
|
782
|
+
const missing = reqs.filter(v => !process.env[v]);
|
|
783
|
+
lines.push('');
|
|
784
|
+
lines.push('**Environment Variables:**');
|
|
785
|
+
for (const v of reqs) {
|
|
786
|
+
const doc = ENV_VAR_DOCS[v];
|
|
787
|
+
const status = process.env[v] ? 'set' : 'MISSING';
|
|
788
|
+
if (doc) {
|
|
789
|
+
lines.push(` ${status === 'set' ? '+' : '-'} ${v} (${status}) — ${doc.description}`);
|
|
790
|
+
if (status !== 'set')
|
|
791
|
+
lines.push(` ${doc.example}`);
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
lines.push(` ${status === 'set' ? '+' : '-'} ${v} (${status})`);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
const related = SKILL_RELATIONS[skill.name];
|
|
799
|
+
if (related && related.length > 0) {
|
|
800
|
+
lines.push('');
|
|
801
|
+
lines.push('**Related Skills:**');
|
|
802
|
+
for (const r of related) {
|
|
803
|
+
const relSkill = registeredSkills.find(s => s.name === r);
|
|
804
|
+
if (relSkill) {
|
|
805
|
+
lines.push(` /${relSkill.commands[0] || r} — ${relSkill.description}`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
lines.push('');
|
|
810
|
+
lines.push(`Run /${skill.commands[0] || skill.name} help for full command list.`);
|
|
811
|
+
return lines.join('\n');
|
|
812
|
+
}
|
|
347
813
|
/** Map of /command → dispatch target for skills with command-dispatch: tool */
|
|
348
814
|
const dispatchMap = new Map();
|
|
349
815
|
/**
|
|
@@ -384,8 +850,12 @@ async function executeSkillCommand(message) {
|
|
|
384
850
|
}
|
|
385
851
|
// Parse command and arguments
|
|
386
852
|
const spaceIndex = trimmed.indexOf(' ');
|
|
387
|
-
|
|
853
|
+
let command = spaceIndex === -1 ? trimmed.toLowerCase() : trimmed.slice(0, spaceIndex).toLowerCase();
|
|
388
854
|
const args = spaceIndex === -1 ? '' : trimmed.slice(spaceIndex + 1);
|
|
855
|
+
// Resolve aliases (e.g., /pancakeswap → /cake, /start → /setup)
|
|
856
|
+
if (COMMAND_ALIASES[command]) {
|
|
857
|
+
command = COMMAND_ALIASES[command];
|
|
858
|
+
}
|
|
389
859
|
// Check dispatch map first (command-dispatch: tool skills bypass LLM)
|
|
390
860
|
const dispatch = dispatchMap.get(command);
|
|
391
861
|
if (dispatch) {
|
|
@@ -434,14 +904,18 @@ function getRegisteredSkills() {
|
|
|
434
904
|
* Get skill handler by command
|
|
435
905
|
*/
|
|
436
906
|
function getSkillByCommand(command) {
|
|
437
|
-
|
|
907
|
+
let normalized = command.toLowerCase().startsWith('/') ? command.toLowerCase() : `/${command.toLowerCase()}`;
|
|
908
|
+
if (COMMAND_ALIASES[normalized])
|
|
909
|
+
normalized = COMMAND_ALIASES[normalized];
|
|
438
910
|
return commandToSkill.get(normalized);
|
|
439
911
|
}
|
|
440
912
|
/**
|
|
441
913
|
* Check if a command is handled by a skill (handler or dispatch)
|
|
442
914
|
*/
|
|
443
915
|
function isSkillCommand(command) {
|
|
444
|
-
|
|
916
|
+
let normalized = command.toLowerCase().startsWith('/') ? command.toLowerCase() : `/${command.toLowerCase()}`;
|
|
917
|
+
if (COMMAND_ALIASES[normalized])
|
|
918
|
+
normalized = COMMAND_ALIASES[normalized];
|
|
445
919
|
return commandToSkill.has(normalized) || dispatchMap.has(normalized);
|
|
446
920
|
}
|
|
447
921
|
/**
|