@darksol/terminal 0.9.2 → 0.10.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/package.json +1 -1
- package/src/cli.js +191 -24
- package/src/services/poker.js +937 -0
- package/src/web/commands.js +253 -1
- package/src/web/server.js +6 -4
- package/src/web/terminal.js +1 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ import { executeLifiSwap, executeLifiBridge, checkBridgeStatus, showSupportedCha
|
|
|
17
17
|
import { topMovers, tokenDetail, compareTokens } from './services/market.js';
|
|
18
18
|
import { oracleFlip, oracleDice, oracleNumber, oracleShuffle, oracleHealth } from './services/oracle.js';
|
|
19
19
|
import { casinoBet, casinoTables, casinoStats, casinoReceipt, casinoHealth, casinoVerify } from './services/casino.js';
|
|
20
|
+
import { pokerNewGame, pokerAction, pokerStatus, pokerHistory } from './services/poker.js';
|
|
20
21
|
import { cardsCatalog, cardsOrder, cardsStatus } from './services/cards.js';
|
|
21
22
|
import { facilitatorHealth, facilitatorVerify, facilitatorSettle } from './services/facilitator.js';
|
|
22
23
|
import { buildersLeaderboard, buildersLookup, buildersFeed } from './services/builders.js';
|
|
@@ -41,7 +42,7 @@ export function cli(argv) {
|
|
|
41
42
|
|
|
42
43
|
program
|
|
43
44
|
.name('darksol')
|
|
44
|
-
.description(theme.gold('DARKSOL Terminal') + theme.dim('
|
|
45
|
+
.description(theme.gold('DARKSOL Terminal') + theme.dim(' - Ghost in the machine with teeth 🌑'))
|
|
45
46
|
.version(PKG_VERSION)
|
|
46
47
|
;
|
|
47
48
|
|
|
@@ -50,7 +51,7 @@ export function cli(argv) {
|
|
|
50
51
|
// ═══════════════════════════════════════
|
|
51
52
|
const wallet = program
|
|
52
53
|
.command('wallet')
|
|
53
|
-
.description('Wallet management
|
|
54
|
+
.description('Wallet management - create, import, list, balance');
|
|
54
55
|
|
|
55
56
|
wallet
|
|
56
57
|
.command('create [name]')
|
|
@@ -115,7 +116,7 @@ export function cli(argv) {
|
|
|
115
116
|
// ═══════════════════════════════════════
|
|
116
117
|
const trade = program
|
|
117
118
|
.command('trade')
|
|
118
|
-
.description('Trading
|
|
119
|
+
.description('Trading - swap, snipe, DCA');
|
|
119
120
|
|
|
120
121
|
trade
|
|
121
122
|
.command('swap')
|
|
@@ -163,14 +164,14 @@ export function cli(argv) {
|
|
|
163
164
|
// If LI.FI failed (not cancelled), fall back to direct
|
|
164
165
|
if (result?.error !== 'cancelled') {
|
|
165
166
|
const { warn: showWarn, info: showInfo } = await import('./ui/components.js');
|
|
166
|
-
showWarn('LI.FI route failed
|
|
167
|
+
showWarn('LI.FI route failed - falling back to direct Uniswap V3...');
|
|
167
168
|
console.log('');
|
|
168
169
|
} else {
|
|
169
170
|
return; // User cancelled, don't fallback
|
|
170
171
|
}
|
|
171
172
|
} catch {
|
|
172
173
|
const { warn: showWarn } = await import('./ui/components.js');
|
|
173
|
-
showWarn('LI.FI unavailable
|
|
174
|
+
showWarn('LI.FI unavailable - falling back to direct Uniswap V3...');
|
|
174
175
|
console.log('');
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -181,7 +182,7 @@ export function cli(argv) {
|
|
|
181
182
|
|
|
182
183
|
trade
|
|
183
184
|
.command('snipe <token>')
|
|
184
|
-
.description('Snipe a token
|
|
185
|
+
.description('Snipe a token - fast buy with ETH')
|
|
185
186
|
.requiredOption('-a, --amount <eth>', 'ETH amount to spend')
|
|
186
187
|
.option('-s, --slippage <percent>', 'Max slippage %', '1')
|
|
187
188
|
.option('-g, --gas <multiplier>', 'Gas priority multiplier', '1.5')
|
|
@@ -215,7 +216,7 @@ export function cli(argv) {
|
|
|
215
216
|
optimism: ['ETH/USDC', 'ETH/OP'],
|
|
216
217
|
polygon: ['POL/USDC', 'POL/WETH', 'USDC/USDT'],
|
|
217
218
|
};
|
|
218
|
-
showSection(`COMMON PAIRS
|
|
219
|
+
showSection(`COMMON PAIRS - ${chain.toUpperCase()}`);
|
|
219
220
|
const pairs = byChain[chain] || byChain.base;
|
|
220
221
|
pairs.forEach((p) => console.log(` ${theme.gold(p)}`));
|
|
221
222
|
console.log('');
|
|
@@ -228,7 +229,7 @@ export function cli(argv) {
|
|
|
228
229
|
// ═══════════════════════════════════════
|
|
229
230
|
const bridge = program
|
|
230
231
|
.command('bridge')
|
|
231
|
-
.description('Cross-chain bridge
|
|
232
|
+
.description('Cross-chain bridge - move tokens between chains via LI.FI');
|
|
232
233
|
|
|
233
234
|
bridge
|
|
234
235
|
.command('send')
|
|
@@ -320,7 +321,7 @@ export function cli(argv) {
|
|
|
320
321
|
// ═══════════════════════════════════════
|
|
321
322
|
const market = program
|
|
322
323
|
.command('market')
|
|
323
|
-
.description('Market intel
|
|
324
|
+
.description('Market intel - prices, movers, analysis');
|
|
324
325
|
|
|
325
326
|
market
|
|
326
327
|
.command('top')
|
|
@@ -331,7 +332,7 @@ export function cli(argv) {
|
|
|
331
332
|
|
|
332
333
|
market
|
|
333
334
|
.command('token <query>')
|
|
334
|
-
.description('Token detail
|
|
335
|
+
.description('Token detail - price, volume, liquidity')
|
|
335
336
|
.action((query) => tokenDetail(query));
|
|
336
337
|
|
|
337
338
|
market
|
|
@@ -376,7 +377,7 @@ export function cli(argv) {
|
|
|
376
377
|
// ═══════════════════════════════════════
|
|
377
378
|
const casino = program
|
|
378
379
|
.command('casino')
|
|
379
|
-
.description('The Clawsino
|
|
380
|
+
.description('The Clawsino - on-chain betting');
|
|
380
381
|
|
|
381
382
|
casino
|
|
382
383
|
.command('status')
|
|
@@ -416,12 +417,29 @@ export function cli(argv) {
|
|
|
416
417
|
.description('Verify bet on-chain')
|
|
417
418
|
.action((id) => casinoVerify(id));
|
|
418
419
|
|
|
420
|
+
const poker = program
|
|
421
|
+
.command('poker [subcommand]')
|
|
422
|
+
.description('GTO Poker Arena — heads-up holdem against the house');
|
|
423
|
+
|
|
424
|
+
poker
|
|
425
|
+
.option('--free', 'Free play mode (default)')
|
|
426
|
+
.option('--real', 'Real mode ($1 buy-in, $2 payout on win)')
|
|
427
|
+
.action(async (subcommand, opts) => {
|
|
428
|
+
if (subcommand === 'status') {
|
|
429
|
+
return showPokerCliStatus();
|
|
430
|
+
}
|
|
431
|
+
if (subcommand === 'history') {
|
|
432
|
+
return showPokerCliHistory();
|
|
433
|
+
}
|
|
434
|
+
return playPokerCli(opts);
|
|
435
|
+
});
|
|
436
|
+
|
|
419
437
|
// ═══════════════════════════════════════
|
|
420
438
|
// CARDS COMMANDS
|
|
421
439
|
// ═══════════════════════════════════════
|
|
422
440
|
const cards = program
|
|
423
441
|
.command('cards')
|
|
424
|
-
.description('Prepaid cards
|
|
442
|
+
.description('Prepaid cards - crypto to Visa/MC');
|
|
425
443
|
|
|
426
444
|
cards
|
|
427
445
|
.command('catalog')
|
|
@@ -498,7 +516,7 @@ export function cli(argv) {
|
|
|
498
516
|
// ═══════════════════════════════════════
|
|
499
517
|
const mail = program
|
|
500
518
|
.command('mail')
|
|
501
|
-
.description('📧 AgentMail
|
|
519
|
+
.description('📧 AgentMail - email for your agent');
|
|
502
520
|
|
|
503
521
|
mail
|
|
504
522
|
.command('setup')
|
|
@@ -752,7 +770,7 @@ export function cli(argv) {
|
|
|
752
770
|
// ═══════════════════════════════════════
|
|
753
771
|
program
|
|
754
772
|
.command('setup')
|
|
755
|
-
.description('First-run setup wizard
|
|
773
|
+
.description('First-run setup wizard - configure AI provider, chain, wallet')
|
|
756
774
|
.option('-f, --force', 'Re-run even if already configured')
|
|
757
775
|
.action((opts) => runSetupWizard({ force: opts.force }));
|
|
758
776
|
|
|
@@ -860,7 +878,7 @@ export function cli(argv) {
|
|
|
860
878
|
// ═══════════════════════════════════════
|
|
861
879
|
const keys = program
|
|
862
880
|
.command('keys')
|
|
863
|
-
.description('API key vault
|
|
881
|
+
.description('API key vault - store keys for LLMs, data providers, RPCs');
|
|
864
882
|
|
|
865
883
|
keys
|
|
866
884
|
.command('list')
|
|
@@ -883,7 +901,7 @@ export function cli(argv) {
|
|
|
883
901
|
// ═══════════════════════════════════════
|
|
884
902
|
const agent = program
|
|
885
903
|
.command('agent')
|
|
886
|
-
.description('Secure agent signer
|
|
904
|
+
.description('Secure agent signer - PK-isolated wallet for AI agents');
|
|
887
905
|
|
|
888
906
|
agent
|
|
889
907
|
.command('task <goal...>')
|
|
@@ -991,7 +1009,7 @@ export function cli(argv) {
|
|
|
991
1009
|
// ═══════════════════════════════════════
|
|
992
1010
|
const skills = program
|
|
993
1011
|
.command('skills')
|
|
994
|
-
.description('DARKSOL skills directory
|
|
1012
|
+
.description('DARKSOL skills directory - install agent skills');
|
|
995
1013
|
|
|
996
1014
|
skills
|
|
997
1015
|
.command('list')
|
|
@@ -1056,7 +1074,7 @@ export function cli(argv) {
|
|
|
1056
1074
|
.action(async (address, opts) => {
|
|
1057
1075
|
showMiniBanner();
|
|
1058
1076
|
if (address.length === 42 && address.startsWith('0x')) {
|
|
1059
|
-
// Could be token or wallet
|
|
1077
|
+
// Could be token or wallet - try token first
|
|
1060
1078
|
try {
|
|
1061
1079
|
await showTokenInfo(address, opts.chain);
|
|
1062
1080
|
} catch {
|
|
@@ -1073,7 +1091,7 @@ export function cli(argv) {
|
|
|
1073
1091
|
// ═══════════════════════════════════════
|
|
1074
1092
|
const script = program
|
|
1075
1093
|
.command('script')
|
|
1076
|
-
.description('Execution scripts
|
|
1094
|
+
.description('Execution scripts - automated trading strategies');
|
|
1077
1095
|
|
|
1078
1096
|
script
|
|
1079
1097
|
.command('create')
|
|
@@ -1200,7 +1218,7 @@ export function cli(argv) {
|
|
|
1200
1218
|
});
|
|
1201
1219
|
|
|
1202
1220
|
// ═══════════════════════════════════════
|
|
1203
|
-
// DASHBOARD (default)
|
|
1221
|
+
// DASHBOARD (default) - commands + optional AI
|
|
1204
1222
|
// ═══════════════════════════════════════
|
|
1205
1223
|
program
|
|
1206
1224
|
.command('dashboard', { isDefault: true })
|
|
@@ -1228,7 +1246,7 @@ export function cli(argv) {
|
|
|
1228
1246
|
|
|
1229
1247
|
// ── AI nudge or chat prompt ──
|
|
1230
1248
|
if (hasLLM) {
|
|
1231
|
-
console.log(theme.gold(' 💬 AI is ready
|
|
1249
|
+
console.log(theme.gold(' 💬 AI is ready - run ') + theme.label('darksol ai chat') + theme.gold(' or just ') + theme.label('darksol chat'));
|
|
1232
1250
|
console.log(theme.dim(' "swap 0.1 ETH for USDC" • "what\'s AERO at?" • any question'));
|
|
1233
1251
|
console.log('');
|
|
1234
1252
|
} else {
|
|
@@ -1252,7 +1270,7 @@ export function cli(argv) {
|
|
|
1252
1270
|
const { info, error: showError } = await import('./ui/components.js');
|
|
1253
1271
|
|
|
1254
1272
|
console.log('');
|
|
1255
|
-
info(`"${input}" isn't a command
|
|
1273
|
+
info(`"${input}" isn't a command - asking AI...`);
|
|
1256
1274
|
console.log('');
|
|
1257
1275
|
|
|
1258
1276
|
try {
|
|
@@ -1406,6 +1424,154 @@ async function chatResponse(llm, input) {
|
|
|
1406
1424
|
}
|
|
1407
1425
|
}
|
|
1408
1426
|
|
|
1427
|
+
function pokerModeFromOpts(opts = {}) {
|
|
1428
|
+
return opts.real ? 'real' : 'free';
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
function renderPokerCards(cards, hidden = false) {
|
|
1432
|
+
const suitMap = { s: '♠', h: '♥', d: '♦', c: '♣' };
|
|
1433
|
+
const colorize = (card, text) => {
|
|
1434
|
+
const suit = card[1];
|
|
1435
|
+
return suit === 'h' || suit === 'd' ? theme.error(text) : theme.bright(text);
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
const source = hidden ? ['??', '??'] : cards;
|
|
1439
|
+
const rows = ['', '', '', '', ''];
|
|
1440
|
+
|
|
1441
|
+
for (const card of source) {
|
|
1442
|
+
if (card === '??') {
|
|
1443
|
+
rows[0] += `${theme.dim('┌─────┐')} `;
|
|
1444
|
+
rows[1] += `${theme.dim('│░░░░░│')} `;
|
|
1445
|
+
rows[2] += `${theme.dim('│░░▓░░│')} `;
|
|
1446
|
+
rows[3] += `${theme.dim('│░░░░░│')} `;
|
|
1447
|
+
rows[4] += `${theme.dim('└─────┘')} `;
|
|
1448
|
+
continue;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
const rank = card[0] === 'T' ? '10' : card[0];
|
|
1452
|
+
const suit = suitMap[card[1]];
|
|
1453
|
+
rows[0] += `${theme.dim('┌─────┐')} `;
|
|
1454
|
+
rows[1] += `${theme.dim('│')}${colorize(card, rank.padEnd(2, ' '))}${theme.dim(' │')} `;
|
|
1455
|
+
rows[2] += `${theme.dim('│ ')}${colorize(card, suit)}${theme.dim(' │')} `;
|
|
1456
|
+
rows[3] += `${theme.dim('│ ')}${colorize(card, rank.padStart(2, ' '))}${theme.dim('│')} `;
|
|
1457
|
+
rows[4] += `${theme.dim('└─────┘')} `;
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
rows.forEach((row) => console.log(` ${row}`));
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function showPokerState(status) {
|
|
1464
|
+
showSection(`POKER ARENA - ${status.mode === 'real' ? 'REAL MODE' : 'FREE MODE'}`);
|
|
1465
|
+
kvDisplay([
|
|
1466
|
+
['Street', status.street.toUpperCase()],
|
|
1467
|
+
['Dealer', status.dealer],
|
|
1468
|
+
['Pot', `${status.pot} chips`],
|
|
1469
|
+
['Current Bet', `${status.currentBet} chips`],
|
|
1470
|
+
['Your Stack', `${status.player.stack} chips`],
|
|
1471
|
+
['House Stack', `${status.house.stack} chips`],
|
|
1472
|
+
['To Act', status.currentActor || '-'],
|
|
1473
|
+
]);
|
|
1474
|
+
|
|
1475
|
+
console.log('');
|
|
1476
|
+
console.log(` ${theme.label('House')}`);
|
|
1477
|
+
renderPokerCards(status.house.hole, status.house.holeHidden);
|
|
1478
|
+
console.log('');
|
|
1479
|
+
console.log(` ${theme.label('Board')}`);
|
|
1480
|
+
if (status.community.length) renderPokerCards(status.community);
|
|
1481
|
+
else console.log(` ${theme.dim(' No community cards yet')}`);
|
|
1482
|
+
console.log('');
|
|
1483
|
+
console.log(` ${theme.label('You')}`);
|
|
1484
|
+
renderPokerCards(status.player.hole);
|
|
1485
|
+
console.log('');
|
|
1486
|
+
|
|
1487
|
+
if (status.street === 'finished') {
|
|
1488
|
+
const result = status.winner === 'player'
|
|
1489
|
+
? theme.success('WIN')
|
|
1490
|
+
: status.winner === 'house'
|
|
1491
|
+
? theme.error('LOSS')
|
|
1492
|
+
: theme.warning('PUSH');
|
|
1493
|
+
kvDisplay([
|
|
1494
|
+
['Result', result],
|
|
1495
|
+
['Summary', status.summary || '-'],
|
|
1496
|
+
['Your Hand', status.player.hand?.name || '-'],
|
|
1497
|
+
['House Hand', status.house.hand?.name || '-'],
|
|
1498
|
+
['Payout', status.mode === 'real' && status.winner === 'player' ? `$${status.payoutUsdc} USDC` : status.mode === 'real' ? '$0 USDC' : 'free mode'],
|
|
1499
|
+
]);
|
|
1500
|
+
console.log('');
|
|
1501
|
+
} else if (status.availableActions?.length) {
|
|
1502
|
+
info(`Actions: ${status.availableActions.join(', ')}`);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
async function playPokerCli(opts = {}) {
|
|
1507
|
+
const inquirer = (await import('inquirer')).default;
|
|
1508
|
+
const mode = pokerModeFromOpts(opts);
|
|
1509
|
+
const spin = spinner(`Opening ${mode === 'real' ? 'real-mode' : 'free-mode'} poker table...`).start();
|
|
1510
|
+
|
|
1511
|
+
try {
|
|
1512
|
+
let status = await pokerNewGame({ mode });
|
|
1513
|
+
spin.succeed('Table ready');
|
|
1514
|
+
|
|
1515
|
+
while (status && status.street !== 'finished') {
|
|
1516
|
+
console.log('');
|
|
1517
|
+
showPokerState(status);
|
|
1518
|
+
|
|
1519
|
+
if (status.currentActor !== 'player') {
|
|
1520
|
+
status = pokerStatus(status.id);
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
const { action } = await inquirer.prompt([{
|
|
1525
|
+
type: 'list',
|
|
1526
|
+
name: 'action',
|
|
1527
|
+
message: theme.gold('Pick your action:'),
|
|
1528
|
+
choices: status.availableActions.map((item) => ({
|
|
1529
|
+
name: item === 'all-in' ? 'all-in' : item,
|
|
1530
|
+
value: item,
|
|
1531
|
+
})),
|
|
1532
|
+
}]);
|
|
1533
|
+
|
|
1534
|
+
status = await pokerAction(status.id, action);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
console.log('');
|
|
1538
|
+
showPokerState(status);
|
|
1539
|
+
} catch (err) {
|
|
1540
|
+
spin.fail('Poker table unavailable');
|
|
1541
|
+
error(err.message);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
function showPokerCliStatus() {
|
|
1546
|
+
showMiniBanner();
|
|
1547
|
+
const status = pokerStatus();
|
|
1548
|
+
if (!status) {
|
|
1549
|
+
info('No active poker game');
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
showPokerState(status);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
function showPokerCliHistory() {
|
|
1556
|
+
showMiniBanner();
|
|
1557
|
+
const items = pokerHistory();
|
|
1558
|
+
if (!items.length) {
|
|
1559
|
+
info('No poker hands played yet');
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
showSection('POKER HISTORY');
|
|
1564
|
+
items.slice(0, 10).forEach((item) => {
|
|
1565
|
+
const verdict = item.winner === 'player'
|
|
1566
|
+
? theme.success('W')
|
|
1567
|
+
: item.winner === 'house'
|
|
1568
|
+
? theme.error('L')
|
|
1569
|
+
: theme.warning('P');
|
|
1570
|
+
console.log(` ${verdict} ${theme.gold(item.mode.toUpperCase().padEnd(5))} ${theme.bright(item.summary)}`);
|
|
1571
|
+
});
|
|
1572
|
+
console.log('');
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1409
1575
|
function showCommandList() {
|
|
1410
1576
|
console.log('');
|
|
1411
1577
|
showSection('COMMANDS');
|
|
@@ -1429,10 +1595,11 @@ function showCommandList() {
|
|
|
1429
1595
|
['script', 'Execution scripts & strategies'],
|
|
1430
1596
|
['market', 'Market intel & token data'],
|
|
1431
1597
|
['oracle', 'On-chain random oracle'],
|
|
1432
|
-
['casino', 'The Clawsino
|
|
1598
|
+
['casino', 'The Clawsino - betting'],
|
|
1599
|
+
['poker', 'GTO Poker Arena — heads-up holdem'],
|
|
1433
1600
|
['cards', 'Prepaid Visa/MC cards'],
|
|
1434
1601
|
['builders', 'ERC-8021 builder index'],
|
|
1435
|
-
['mail', 'AgentMail
|
|
1602
|
+
['mail', 'AgentMail - email for your agent'],
|
|
1436
1603
|
['facilitator', 'x402 payment facilitator'],
|
|
1437
1604
|
['skills', 'Agent skill directory'],
|
|
1438
1605
|
['serve', 'Launch web terminal in browser'],
|