@trading-boy/cli 1.11.0 → 2.0.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.
Files changed (83) hide show
  1. package/README.md +50 -22
  2. package/dist/api-client.d.ts +4 -7
  3. package/dist/api-client.js +8 -13
  4. package/dist/cli.bundle.js +1977 -33976
  5. package/dist/credentials.js +1 -1
  6. package/dist/index.d.ts +0 -28
  7. package/dist/index.js +0 -24
  8. package/dist/logger.d.ts +8 -0
  9. package/dist/logger.js +12 -0
  10. package/dist/utils.js +3 -3
  11. package/package.json +20 -5
  12. package/dist/cli.d.ts +0 -5
  13. package/dist/cli.js +0 -157
  14. package/dist/commands/agent-cmd.d.ts +0 -9
  15. package/dist/commands/agent-cmd.js +0 -572
  16. package/dist/commands/audit.d.ts +0 -18
  17. package/dist/commands/audit.js +0 -73
  18. package/dist/commands/behavioral.d.ts +0 -73
  19. package/dist/commands/behavioral.js +0 -349
  20. package/dist/commands/benchmark-cmd.d.ts +0 -3
  21. package/dist/commands/benchmark-cmd.js +0 -191
  22. package/dist/commands/billing.d.ts +0 -12
  23. package/dist/commands/billing.js +0 -142
  24. package/dist/commands/catalysts.d.ts +0 -17
  25. package/dist/commands/catalysts.js +0 -151
  26. package/dist/commands/coaching-cmd.d.ts +0 -16
  27. package/dist/commands/coaching-cmd.js +0 -222
  28. package/dist/commands/config-cmd.d.ts +0 -30
  29. package/dist/commands/config-cmd.js +0 -515
  30. package/dist/commands/connect-chatgpt.d.ts +0 -5
  31. package/dist/commands/connect-chatgpt.js +0 -293
  32. package/dist/commands/connect-claude.d.ts +0 -5
  33. package/dist/commands/connect-claude.js +0 -280
  34. package/dist/commands/context.d.ts +0 -41
  35. package/dist/commands/context.js +0 -405
  36. package/dist/commands/cron-cmd.d.ts +0 -3
  37. package/dist/commands/cron-cmd.js +0 -305
  38. package/dist/commands/decisions.d.ts +0 -57
  39. package/dist/commands/decisions.js +0 -364
  40. package/dist/commands/edge-cmd.d.ts +0 -78
  41. package/dist/commands/edge-cmd.js +0 -183
  42. package/dist/commands/edge-guard-cmd.d.ts +0 -36
  43. package/dist/commands/edge-guard-cmd.js +0 -169
  44. package/dist/commands/events.d.ts +0 -3
  45. package/dist/commands/events.js +0 -117
  46. package/dist/commands/infra.d.ts +0 -24
  47. package/dist/commands/infra.js +0 -137
  48. package/dist/commands/journal.d.ts +0 -3
  49. package/dist/commands/journal.js +0 -302
  50. package/dist/commands/login.d.ts +0 -18
  51. package/dist/commands/login.js +0 -127
  52. package/dist/commands/logout.d.ts +0 -8
  53. package/dist/commands/logout.js +0 -108
  54. package/dist/commands/narratives.d.ts +0 -3
  55. package/dist/commands/narratives.js +0 -259
  56. package/dist/commands/onboarding.d.ts +0 -7
  57. package/dist/commands/onboarding.js +0 -298
  58. package/dist/commands/query.d.ts +0 -32
  59. package/dist/commands/query.js +0 -135
  60. package/dist/commands/replay-cmd.d.ts +0 -43
  61. package/dist/commands/replay-cmd.js +0 -184
  62. package/dist/commands/review.d.ts +0 -3
  63. package/dist/commands/review.js +0 -443
  64. package/dist/commands/risk.d.ts +0 -47
  65. package/dist/commands/risk.js +0 -158
  66. package/dist/commands/social.d.ts +0 -43
  67. package/dist/commands/social.js +0 -318
  68. package/dist/commands/soul-wizard.d.ts +0 -29
  69. package/dist/commands/soul-wizard.js +0 -155
  70. package/dist/commands/strategy-cmd.d.ts +0 -44
  71. package/dist/commands/strategy-cmd.js +0 -340
  72. package/dist/commands/subscribe.d.ts +0 -78
  73. package/dist/commands/subscribe.js +0 -552
  74. package/dist/commands/suggestions-cmd.d.ts +0 -24
  75. package/dist/commands/suggestions-cmd.js +0 -148
  76. package/dist/commands/thesis-cmd.d.ts +0 -3
  77. package/dist/commands/thesis-cmd.js +0 -129
  78. package/dist/commands/trader.d.ts +0 -30
  79. package/dist/commands/trader.js +0 -971
  80. package/dist/commands/watch.d.ts +0 -16
  81. package/dist/commands/watch.js +0 -104
  82. package/dist/commands/whoami.d.ts +0 -14
  83. package/dist/commands/whoami.js +0 -105
@@ -1,135 +0,0 @@
1
- import { Option } from 'commander';
2
- import chalk from 'chalk';
3
- import { createLogger } from '@trading-boy/core';
4
- import { formatConnectionError, ensureRemote } from '../utils.js';
5
- import { apiRequest, ApiError } from '../api-client.js';
6
- // ─── Logger ───
7
- const logger = createLogger('cli-query');
8
- // ─── Formatter ───
9
- export function formatQueryOutput(result) {
10
- const lines = [];
11
- // Header
12
- lines.push('');
13
- lines.push(chalk.bold.cyan(` ${result.token.symbol}`) + (result.token.name ? chalk.gray(` (${result.token.name})`) : ''));
14
- lines.push(chalk.gray(' ' + '─'.repeat(50)));
15
- // Chains
16
- if (result.token.chains.length > 0) {
17
- lines.push(` ${chalk.gray('Chains:')} ${result.token.chains.join(', ')}`);
18
- }
19
- else {
20
- lines.push(` ${chalk.gray('Chains:')} ${chalk.dim('none')}`);
21
- }
22
- // Narratives
23
- if (result.token.narratives.length > 0) {
24
- const narrs = result.token.narratives
25
- .map((n) => `${n.name} ${chalk.dim(`(${n.status})`)}`)
26
- .join(', ');
27
- lines.push(` ${chalk.gray('Narratives:')} ${narrs}`);
28
- }
29
- else {
30
- lines.push(` ${chalk.gray('Narratives:')} ${chalk.dim('none')}`);
31
- }
32
- lines.push('');
33
- // Price
34
- if (result.price.price !== null) {
35
- const priceStr = `$${result.price.price.toLocaleString('en-US', {
36
- minimumFractionDigits: 2,
37
- maximumFractionDigits: 6,
38
- })}`;
39
- lines.push(` ${chalk.gray('Price:')} ${chalk.white.bold(priceStr)}`);
40
- if (result.price.change24h !== null) {
41
- const changeStr = `${result.price.change24h >= 0 ? '+' : ''}${result.price.change24h.toFixed(2)}%`;
42
- const colorFn = result.price.change24h >= 0 ? chalk.green : chalk.red;
43
- lines.push(` ${chalk.gray('24h Change:')} ${colorFn(changeStr)}`);
44
- }
45
- else {
46
- lines.push(` ${chalk.gray('24h Change:')} ${chalk.dim('n/a')}`);
47
- }
48
- }
49
- else {
50
- lines.push(` ${chalk.gray('Price:')} ${chalk.dim('no data')}`);
51
- }
52
- // Funding rate
53
- if (result.funding.fundingRate !== null) {
54
- const rateStr = `${result.funding.fundingRate >= 0 ? '+' : ''}${(result.funding.fundingRate * 100).toFixed(4)}%`;
55
- const colorFn = result.funding.fundingRate >= 0 ? chalk.green : chalk.red;
56
- lines.push(` ${chalk.gray('Funding:')} ${colorFn(rateStr)}`);
57
- }
58
- else {
59
- lines.push(` ${chalk.gray('Funding:')} ${chalk.dim('no perp data')}`);
60
- }
61
- // Whale activity
62
- lines.push(` ${chalk.gray('Whales:')} ${result.whaleActivity.count > 0 ? chalk.yellow(String(result.whaleActivity.count)) : chalk.dim('0')} active`);
63
- // Last updated
64
- if (result.price.lastUpdated) {
65
- const timeStr = new Date(result.price.lastUpdated).toLocaleString();
66
- lines.push('');
67
- lines.push(` ${chalk.dim(`Last updated: ${timeStr}`)}`);
68
- }
69
- lines.push('');
70
- return lines.join('\n');
71
- }
72
- // ─── API Response → QueryResult Mapper ───
73
- function contextToQueryResult(pkg) {
74
- return {
75
- token: {
76
- name: pkg.token.name ?? null,
77
- symbol: pkg.token.symbol,
78
- chains: Array.isArray(pkg.token.chains) ? pkg.token.chains : [],
79
- narratives: Array.isArray(pkg.social?.narrativeMembership)
80
- ? pkg.social.narrativeMembership.map((n) => ({ name: n.narrative, status: n.status }))
81
- : [],
82
- },
83
- price: {
84
- price: pkg.market?.price ?? null,
85
- change24h: pkg.market?.priceChange24h ?? null,
86
- lastUpdated: pkg._meta?.assembledAt ? new Date(pkg._meta.assembledAt) : null,
87
- },
88
- funding: {
89
- fundingRate: pkg.market?.fundingRate ?? null,
90
- lastUpdated: null,
91
- },
92
- whaleActivity: {
93
- count: pkg.onchain?.whaleTransactions24h ?? 0,
94
- },
95
- };
96
- }
97
- // ─── Command Registration ───
98
- export function registerQueryCommand(program) {
99
- program
100
- .command('query <symbol>')
101
- .description('Query token info, price, funding rate, and whale activity')
102
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
103
- .action(async (symbol, options) => {
104
- try {
105
- // ─── Auth pre-flight ───
106
- if (!(await ensureRemote()))
107
- return;
108
- const pkg = await apiRequest(`/api/v1/tokens/${encodeURIComponent(symbol.toUpperCase())}/context`);
109
- const result = contextToQueryResult(pkg);
110
- // Check if the token was actually found
111
- if (result.token.name === null && result.token.chains.length === 0 && result.price.price === null) {
112
- console.error(chalk.red(`Error: Token not found: ${symbol.toUpperCase()}`));
113
- console.error(chalk.dim(' Check the symbol and try again. Use a symbol like SOL, JUP, or BONK.'));
114
- process.exitCode = 1;
115
- return;
116
- }
117
- if (options.format === 'json') {
118
- console.log(JSON.stringify(result, null, 2));
119
- }
120
- else {
121
- console.log(formatQueryOutput(result));
122
- }
123
- }
124
- catch (error) {
125
- const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
126
- logger.error({ error: message }, 'Query failed');
127
- console.error(chalk.red(`Error: ${message}`));
128
- const guidance = formatConnectionError(message);
129
- if (guidance)
130
- console.error(guidance);
131
- process.exitCode = error instanceof ApiError ? 2 : 1;
132
- }
133
- });
134
- }
135
- //# sourceMappingURL=query.js.map
@@ -1,43 +0,0 @@
1
- import { Command } from 'commander';
2
- interface ReplayTrade {
3
- entryTime: string;
4
- exitTime?: string;
5
- direction: string;
6
- setupType?: string;
7
- entryPrice: number;
8
- exitPrice?: number;
9
- pnlPercent?: number;
10
- pnlAbsolute?: number;
11
- regime?: string;
12
- }
13
- interface ReplayRegimeBreakdown {
14
- regime: string;
15
- trades: number;
16
- winRate: number;
17
- avgPnlPercent: number;
18
- }
19
- interface ReplayResult {
20
- jobId: string;
21
- strategyId: string;
22
- tokenSymbol: string;
23
- from: string;
24
- to: string;
25
- status: 'COMPLETE' | 'FAILED';
26
- error?: string;
27
- summary?: {
28
- totalTrades: number;
29
- winRate: number;
30
- avgPnlPercent: number;
31
- totalPnlPercent: number;
32
- maxDrawdownPercent: number;
33
- sharpeRatio?: number;
34
- profitFactor?: number;
35
- };
36
- regimeBreakdown?: ReplayRegimeBreakdown[];
37
- trades?: ReplayTrade[];
38
- completedAt?: string;
39
- }
40
- export declare function formatReplayResult(result: ReplayResult): string;
41
- export declare function registerReplayCommand(program: Command): void;
42
- export {};
43
- //# sourceMappingURL=replay-cmd.d.ts.map
@@ -1,184 +0,0 @@
1
- import { Option } from 'commander';
2
- import chalk from 'chalk';
3
- import { createLogger } from '@trading-boy/core';
4
- import { apiRequest } from '../api-client.js';
5
- import { padRight, handleApiError, ensureRemote } from '../utils.js';
6
- // ─── Logger ───
7
- const logger = createLogger('cli-replay');
8
- // ─── Helpers ───
9
- function formatPercent(val) {
10
- const sign = val >= 0 ? '+' : '';
11
- const str = `${sign}${val.toFixed(2)}%`;
12
- return val >= 0 ? chalk.green(str) : chalk.red(str);
13
- }
14
- function formatShortDate(isoString) {
15
- try {
16
- return new Date(isoString).toISOString().slice(0, 10);
17
- }
18
- catch {
19
- return isoString;
20
- }
21
- }
22
- // ─── Formatters ───
23
- export function formatReplayResult(result) {
24
- const lines = [];
25
- lines.push('');
26
- lines.push(chalk.bold.cyan(` Replay Results — ${result.tokenSymbol} (strategy: ${result.strategyId})`));
27
- lines.push(chalk.gray(' ' + '─'.repeat(60)));
28
- lines.push('');
29
- if (result.status === 'FAILED') {
30
- lines.push(chalk.red(` Replay failed: ${result.error ?? 'Unknown error'}`));
31
- lines.push('');
32
- return lines.join('\n');
33
- }
34
- lines.push(` ${chalk.gray('Period:')} ${formatShortDate(result.from)} → ${formatShortDate(result.to)}`);
35
- if (result.completedAt) {
36
- lines.push(` ${chalk.gray('Completed:')} ${chalk.dim(new Date(result.completedAt).toISOString().slice(0, 19).replace('T', ' '))}`);
37
- }
38
- if (result.summary) {
39
- const s = result.summary;
40
- lines.push('');
41
- lines.push(chalk.bold(' Summary'));
42
- lines.push(` ${chalk.gray('Total Trades:')} ${chalk.white(String(s.totalTrades))}`);
43
- lines.push(` ${chalk.gray('Win Rate:')} ${formatWinRate(s.winRate)}`);
44
- lines.push(` ${chalk.gray('Avg PnL %:')} ${formatPercent(s.avgPnlPercent)}`);
45
- lines.push(` ${chalk.gray('Total PnL %:')} ${formatPercent(s.totalPnlPercent)}`);
46
- lines.push(` ${chalk.gray('Max Drawdown:')} ${chalk.red('-' + Math.abs(s.maxDrawdownPercent).toFixed(2) + '%')}`);
47
- if (s.sharpeRatio !== undefined) {
48
- const sharpeColor = s.sharpeRatio >= 1.0 ? chalk.green : s.sharpeRatio >= 0.5 ? chalk.yellow : chalk.red;
49
- lines.push(` ${chalk.gray('Sharpe Ratio:')} ${sharpeColor(s.sharpeRatio.toFixed(2))}`);
50
- }
51
- if (s.profitFactor !== undefined) {
52
- const pfColor = s.profitFactor >= 1.5 ? chalk.green : s.profitFactor >= 1.0 ? chalk.yellow : chalk.red;
53
- lines.push(` ${chalk.gray('Profit Factor:')} ${pfColor(s.profitFactor.toFixed(2))}`);
54
- }
55
- }
56
- if (result.regimeBreakdown && result.regimeBreakdown.length > 0) {
57
- lines.push('');
58
- lines.push(chalk.bold(' Regime Breakdown'));
59
- lines.push(' ' +
60
- padRight('Regime', 20) +
61
- padRight('Trades', 8) +
62
- padRight('Win Rate', 10) +
63
- 'Avg PnL %');
64
- lines.push(chalk.gray(' ' + '─'.repeat(48)));
65
- for (const r of result.regimeBreakdown) {
66
- lines.push(' ' +
67
- padRight(r.regime, 20) +
68
- padRight(String(r.trades), 8) +
69
- padRight(formatWinRate(r.winRate), 10) +
70
- formatPercent(r.avgPnlPercent));
71
- }
72
- }
73
- lines.push('');
74
- return lines.join('\n');
75
- }
76
- function formatWinRate(rate) {
77
- const str = `${(rate * 100).toFixed(1)}%`;
78
- if (rate >= 0.6)
79
- return chalk.green(str);
80
- if (rate >= 0.4)
81
- return chalk.yellow(str);
82
- return chalk.red(str);
83
- }
84
- // ─── Polling ───
85
- const POLL_INTERVAL_MS = 2000;
86
- const POLL_TIMEOUT_MS = 60000;
87
- async function pollReplayJob(jobId) {
88
- const deadline = Date.now() + POLL_TIMEOUT_MS;
89
- while (Date.now() < deadline) {
90
- const status = await apiRequest(`/api/v1/replay/${encodeURIComponent(jobId)}`);
91
- if (status.status === 'COMPLETE' || status.status === 'FAILED') {
92
- return status;
93
- }
94
- // Wait before next poll
95
- await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
96
- }
97
- throw new Error(`Replay job ${jobId} did not complete within ${POLL_TIMEOUT_MS / 1000}s timeout.`);
98
- }
99
- // ─── Command Registration ───
100
- export function registerReplayCommand(program) {
101
- program
102
- .command('replay')
103
- .description('Run strategy replay (backtest) over a historical period')
104
- .requiredOption('--strategy <id>', 'Strategy ID')
105
- .requiredOption('--token <symbol>', 'Token symbol')
106
- .requiredOption('--from <date>', 'Start date (ISO-8601, e.g. 2025-01-01)')
107
- .requiredOption('--to <date>', 'End date (ISO-8601, e.g. 2025-03-01)')
108
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
109
- .action(async (options) => {
110
- if (!(await ensureRemote()))
111
- return;
112
- // Validate dates
113
- const fromDate = new Date(options.from);
114
- const toDate = new Date(options.to);
115
- if (isNaN(fromDate.getTime())) {
116
- console.error(chalk.red(`Error: Invalid --from date: ${options.from}`));
117
- process.exitCode = 1;
118
- return;
119
- }
120
- if (isNaN(toDate.getTime())) {
121
- console.error(chalk.red(`Error: Invalid --to date: ${options.to}`));
122
- process.exitCode = 1;
123
- return;
124
- }
125
- if (fromDate >= toDate) {
126
- console.error(chalk.red('Error: --from must be before --to'));
127
- process.exitCode = 1;
128
- return;
129
- }
130
- // Use createSpinner for TTY-aware spinners (silent when piped)
131
- const { createSpinner } = await import('../utils.js');
132
- // ─── Submit replay job ───
133
- let jobId;
134
- const submitSpinner = (await createSpinner('Submitting replay job…')).start();
135
- try {
136
- const submitted = await apiRequest('/api/v1/replay', {
137
- method: 'POST',
138
- body: {
139
- strategyId: options.strategy,
140
- tokenSymbol: options.token.toUpperCase(),
141
- from: fromDate.toISOString(),
142
- to: toDate.toISOString(),
143
- },
144
- });
145
- jobId = submitted.jobId;
146
- submitSpinner.succeed(chalk.dim(`Job submitted: ${jobId}`));
147
- }
148
- catch (error) {
149
- submitSpinner.fail('Failed to submit replay job');
150
- handleApiError(error, 'Replay submit failed', logger);
151
- return;
152
- }
153
- // ─── Poll until complete ───
154
- const pollSpinner = (await createSpinner('Running replay…')).start();
155
- let finalStatus;
156
- try {
157
- finalStatus = await pollReplayJob(jobId);
158
- pollSpinner.stop();
159
- }
160
- catch (error) {
161
- pollSpinner.fail('Replay timed out or encountered an error');
162
- handleApiError(error, 'Replay polling failed', logger);
163
- return;
164
- }
165
- // ─── Display results ───
166
- if (!finalStatus.result) {
167
- if (finalStatus.status === 'FAILED') {
168
- console.error(chalk.red(`Error: Replay job failed — ${finalStatus.error ?? 'unknown error'}`));
169
- }
170
- else {
171
- console.error(chalk.red('Error: Replay completed but returned no result data.'));
172
- }
173
- process.exitCode = 1;
174
- return;
175
- }
176
- if (options.format === 'json') {
177
- console.log(JSON.stringify(finalStatus.result, null, 2));
178
- }
179
- else {
180
- console.log(formatReplayResult(finalStatus.result));
181
- }
182
- });
183
- }
184
- //# sourceMappingURL=replay-cmd.js.map
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerReviewCommand(journal: Command): void;
3
- //# sourceMappingURL=review.d.ts.map