@trading-boy/cli 1.12.0 → 2.0.1

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 (84) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +64 -29
  3. package/dist/api-client.d.ts +4 -7
  4. package/dist/api-client.js +8 -13
  5. package/dist/cli.bundle.js +2314 -33711
  6. package/dist/credentials.js +1 -1
  7. package/dist/index.d.ts +0 -28
  8. package/dist/index.js +0 -24
  9. package/dist/logger.d.ts +8 -0
  10. package/dist/logger.js +12 -0
  11. package/dist/utils.js +3 -3
  12. package/package.json +30 -16
  13. package/dist/cli.d.ts +0 -5
  14. package/dist/cli.js +0 -157
  15. package/dist/commands/agent-cmd.d.ts +0 -9
  16. package/dist/commands/agent-cmd.js +0 -567
  17. package/dist/commands/audit.d.ts +0 -18
  18. package/dist/commands/audit.js +0 -73
  19. package/dist/commands/behavioral.d.ts +0 -73
  20. package/dist/commands/behavioral.js +0 -349
  21. package/dist/commands/benchmark-cmd.d.ts +0 -3
  22. package/dist/commands/benchmark-cmd.js +0 -191
  23. package/dist/commands/billing.d.ts +0 -12
  24. package/dist/commands/billing.js +0 -142
  25. package/dist/commands/catalysts.d.ts +0 -17
  26. package/dist/commands/catalysts.js +0 -151
  27. package/dist/commands/coaching-cmd.d.ts +0 -16
  28. package/dist/commands/coaching-cmd.js +0 -222
  29. package/dist/commands/config-cmd.d.ts +0 -30
  30. package/dist/commands/config-cmd.js +0 -515
  31. package/dist/commands/connect-chatgpt.d.ts +0 -5
  32. package/dist/commands/connect-chatgpt.js +0 -293
  33. package/dist/commands/connect-claude.d.ts +0 -5
  34. package/dist/commands/connect-claude.js +0 -280
  35. package/dist/commands/context.d.ts +0 -41
  36. package/dist/commands/context.js +0 -405
  37. package/dist/commands/cron-cmd.d.ts +0 -3
  38. package/dist/commands/cron-cmd.js +0 -305
  39. package/dist/commands/decisions.d.ts +0 -57
  40. package/dist/commands/decisions.js +0 -364
  41. package/dist/commands/edge-cmd.d.ts +0 -78
  42. package/dist/commands/edge-cmd.js +0 -183
  43. package/dist/commands/edge-guard-cmd.d.ts +0 -36
  44. package/dist/commands/edge-guard-cmd.js +0 -169
  45. package/dist/commands/events.d.ts +0 -3
  46. package/dist/commands/events.js +0 -117
  47. package/dist/commands/infra.d.ts +0 -24
  48. package/dist/commands/infra.js +0 -137
  49. package/dist/commands/journal.d.ts +0 -3
  50. package/dist/commands/journal.js +0 -302
  51. package/dist/commands/login.d.ts +0 -18
  52. package/dist/commands/login.js +0 -127
  53. package/dist/commands/logout.d.ts +0 -8
  54. package/dist/commands/logout.js +0 -108
  55. package/dist/commands/narratives.d.ts +0 -3
  56. package/dist/commands/narratives.js +0 -259
  57. package/dist/commands/onboarding.d.ts +0 -7
  58. package/dist/commands/onboarding.js +0 -281
  59. package/dist/commands/query.d.ts +0 -32
  60. package/dist/commands/query.js +0 -135
  61. package/dist/commands/replay-cmd.d.ts +0 -43
  62. package/dist/commands/replay-cmd.js +0 -184
  63. package/dist/commands/review.d.ts +0 -3
  64. package/dist/commands/review.js +0 -443
  65. package/dist/commands/risk.d.ts +0 -47
  66. package/dist/commands/risk.js +0 -158
  67. package/dist/commands/social.d.ts +0 -43
  68. package/dist/commands/social.js +0 -318
  69. package/dist/commands/soul-wizard.d.ts +0 -29
  70. package/dist/commands/soul-wizard.js +0 -155
  71. package/dist/commands/strategy-cmd.d.ts +0 -44
  72. package/dist/commands/strategy-cmd.js +0 -335
  73. package/dist/commands/subscribe.d.ts +0 -78
  74. package/dist/commands/subscribe.js +0 -552
  75. package/dist/commands/suggestions-cmd.d.ts +0 -24
  76. package/dist/commands/suggestions-cmd.js +0 -148
  77. package/dist/commands/thesis-cmd.d.ts +0 -3
  78. package/dist/commands/thesis-cmd.js +0 -129
  79. package/dist/commands/trader.d.ts +0 -30
  80. package/dist/commands/trader.js +0 -971
  81. package/dist/commands/watch.d.ts +0 -16
  82. package/dist/commands/watch.js +0 -104
  83. package/dist/commands/whoami.d.ts +0 -14
  84. package/dist/commands/whoami.js +0 -105
@@ -1,43 +0,0 @@
1
- import { Command } from 'commander';
2
- interface TokenSentiment {
3
- sentiment24h: number;
4
- sentimentTrend: string;
5
- signalCount24h: number;
6
- topTierCount: number;
7
- breakdown: {
8
- tier1Avg: number | null;
9
- tier2Avg: number | null;
10
- tier3Avg: number | null;
11
- };
12
- }
13
- interface MindshareRanking {
14
- rank: number;
15
- compositeScore: number;
16
- txCount24h: number;
17
- uniqueWallets24h: number;
18
- whaleVolume24h: number;
19
- }
20
- interface TokenNarrativeRecord {
21
- narrativeName: string;
22
- narrativeStatus: string;
23
- confidence: number;
24
- }
25
- export interface SocialSignalRecord {
26
- id?: string;
27
- platform: string;
28
- sentiment: number;
29
- authorTier: string;
30
- content?: string | null;
31
- authorId?: string | null;
32
- authorHandle?: string | null;
33
- engagementScore?: number | null;
34
- extractedEntities?: string[];
35
- narrativeTags?: string[];
36
- }
37
- /**
38
- * Format the full social query output for a token.
39
- */
40
- export declare function formatTokenSocial(tokenSymbol: string, sentiment: TokenSentiment | null, mindshare: MindshareRanking | null, narratives: TokenNarrativeRecord[], signals: SocialSignalRecord[]): string;
41
- export declare function registerSocialCommand(program: Command): void;
42
- export {};
43
- //# sourceMappingURL=social.d.ts.map
@@ -1,318 +0,0 @@
1
- import { Option } from 'commander';
2
- import chalk from 'chalk';
3
- import { createLogger, Platform, AuthorTier, } from '@trading-boy/core';
4
- import { formatConnectionError, padRight, truncate, colorSentiment } from '../utils.js';
5
- import { apiRequest, ApiError } from '../api-client.js';
6
- // ─── Logger ───
7
- const logger = createLogger('cli-social');
8
- // ─── Formatters ───
9
- /**
10
- * Color-code a trend direction.
11
- */
12
- function colorTrend(trend) {
13
- switch (trend) {
14
- case 'IMPROVING':
15
- return chalk.green(trend);
16
- case 'DECLINING':
17
- return chalk.red(trend);
18
- case 'STABLE':
19
- default:
20
- return chalk.yellow(trend);
21
- }
22
- }
23
- /**
24
- * Format the full social query output for a token.
25
- */
26
- export function formatTokenSocial(tokenSymbol, sentiment, mindshare, narratives, signals) {
27
- const lines = [];
28
- lines.push('');
29
- lines.push(chalk.bold.cyan(` Social Overview: ${tokenSymbol}`));
30
- lines.push(chalk.gray(' ' + '\u2500'.repeat(60)));
31
- lines.push('');
32
- // ─── Sentiment section ───
33
- lines.push(chalk.bold(' Sentiment'));
34
- if (sentiment) {
35
- lines.push(` ${chalk.gray('24h Sentiment:')} ${colorSentiment(sentiment.sentiment24h)}`);
36
- lines.push(` ${chalk.gray('Trend:')} ${colorTrend(sentiment.sentimentTrend)}`);
37
- lines.push(` ${chalk.gray('Signals (24h):')} ${sentiment.signalCount24h}`);
38
- lines.push(` ${chalk.gray('Top Tier Count:')} ${sentiment.topTierCount}`);
39
- if (sentiment.breakdown.tier1Avg !== null) {
40
- lines.push(` ${chalk.gray('Tier 1 (Mover):')} ${colorSentiment(sentiment.breakdown.tier1Avg)}`);
41
- }
42
- if (sentiment.breakdown.tier2Avg !== null) {
43
- lines.push(` ${chalk.gray('Tier 2 (Alpha):')} ${colorSentiment(sentiment.breakdown.tier2Avg)}`);
44
- }
45
- if (sentiment.breakdown.tier3Avg !== null) {
46
- lines.push(` ${chalk.gray('Tier 3 (Comm.):')} ${colorSentiment(sentiment.breakdown.tier3Avg)}`);
47
- }
48
- }
49
- else {
50
- lines.push(` ${chalk.dim('No sentiment data available.')}`);
51
- }
52
- lines.push('');
53
- // ─── Mindshare section ───
54
- lines.push(chalk.bold(' Mindshare'));
55
- if (mindshare) {
56
- lines.push(` ${chalk.gray('Rank:')} #${mindshare.rank}`);
57
- lines.push(` ${chalk.gray('Composite Score:')} ${mindshare.compositeScore.toFixed(3)}`);
58
- lines.push(` ${chalk.gray('Tx Count (24h):')} ${mindshare.txCount24h.toLocaleString()}`);
59
- lines.push(` ${chalk.gray('Unique Wallets:')} ${mindshare.uniqueWallets24h.toLocaleString()}`);
60
- lines.push(` ${chalk.gray('Whale Volume:')} $${mindshare.whaleVolume24h.toLocaleString()}`);
61
- }
62
- else {
63
- lines.push(` ${chalk.dim('No mindshare data available.')}`);
64
- }
65
- lines.push('');
66
- // ─── Narratives section ───
67
- lines.push(chalk.bold(' Narratives'));
68
- if (narratives.length > 0) {
69
- for (const n of narratives) {
70
- const conf = `${(n.confidence * 100).toFixed(0)}%`;
71
- lines.push(` ${chalk.white(n.narrativeName)} ${chalk.dim(`(${n.narrativeStatus})`)} — confidence: ${conf}`);
72
- }
73
- }
74
- else {
75
- lines.push(` ${chalk.dim('Not linked to any narratives.')}`);
76
- }
77
- lines.push('');
78
- // ─── Recent signals section ───
79
- lines.push(chalk.bold(' Recent Signals'));
80
- if (signals.length > 0) {
81
- for (const s of signals) {
82
- const sentimentStr = colorSentiment(s.sentiment);
83
- const author = s.authorHandle ?? s.authorId ?? chalk.dim('unknown');
84
- const content = s.content ? truncate(s.content, 50) : '-';
85
- lines.push(` ${sentimentStr} ${chalk.dim(s.authorTier)} ${chalk.gray(author)}: ${content}`);
86
- }
87
- }
88
- else {
89
- lines.push(` ${chalk.dim('No recent signals.')}`);
90
- }
91
- lines.push('');
92
- return lines.join('\n');
93
- }
94
- // ─── Command Registration ───
95
- export function registerSocialCommand(program) {
96
- const social = program
97
- .command('social')
98
- .description('Social signal management commands');
99
- // ─── social query ───
100
- social
101
- .command('query <token>')
102
- .description('Show social overview for a token (sentiment, mindshare, narratives, signals)')
103
- .option('--limit <n>', 'Maximum number of recent signals to show', (v) => parseInt(v, 10), 5)
104
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
105
- .action(async (token, options) => {
106
- const tokenSymbol = token.toUpperCase();
107
- try {
108
- const result = await apiRequest(`/api/v1/tokens/${encodeURIComponent(tokenSymbol)}/social?limit=${options.limit}`);
109
- if (options.format === 'json') {
110
- console.log(JSON.stringify(result, null, 2));
111
- return;
112
- }
113
- console.log(formatTokenSocial(tokenSymbol, result.sentiment, result.mindshare, result.narratives, result.signals));
114
- }
115
- catch (error) {
116
- const message = error instanceof Error ? error.message : String(error);
117
- logger.error({ error: message }, 'Failed to query social data');
118
- console.error(chalk.red(`Error: ${message}`));
119
- if (!(error instanceof ApiError)) {
120
- const guidance = formatConnectionError(message);
121
- if (guidance)
122
- console.error(guidance);
123
- }
124
- process.exitCode = error instanceof ApiError ? 2 : 1;
125
- }
126
- });
127
- // ─── social add ───
128
- social
129
- .command('add')
130
- .description('Add a manual social signal')
131
- .requiredOption('--token <symbols...>', 'Token symbol(s) mentioned')
132
- .requiredOption('--sentiment <value>', 'Sentiment score (-1.0 to 1.0)', parseFloat)
133
- .option('--tier <tier>', `Author tier (${Object.values(AuthorTier).join(', ')})`, 'TIER2_ALPHA')
134
- .option('--platform <platform>', `Platform (${Object.values(Platform).join(', ')})`, 'TWITTER')
135
- .option('--content <text>', 'Signal content / note')
136
- .option('--author-id <id>', 'Author identifier')
137
- .option('--author-handle <handle>', 'Author handle (e.g., @username)')
138
- .option('--engagement <score>', 'Engagement score (0-100)', parseFloat)
139
- .option('--narrative <narratives...>', 'Narrative name(s) to link')
140
- .option('--protocol <protocols...>', 'Protocol name(s) to link')
141
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
142
- .action(async (options) => {
143
- // Validate platform
144
- if (!Object.values(Platform).includes(options.platform)) {
145
- console.error(`Error: Invalid platform "${options.platform}". Valid platforms: ${Object.values(Platform).join(', ')}`);
146
- process.exitCode = 1;
147
- return;
148
- }
149
- // Validate author tier
150
- if (!Object.values(AuthorTier).includes(options.tier)) {
151
- console.error(`Error: Invalid author tier "${options.tier}". Valid tiers: ${Object.values(AuthorTier).join(', ')}`);
152
- process.exitCode = 1;
153
- return;
154
- }
155
- // Validate sentiment range
156
- if (isNaN(options.sentiment) || options.sentiment < -1 || options.sentiment > 1) {
157
- console.error('Error: Sentiment must be a number between -1.0 and 1.0');
158
- process.exitCode = 1;
159
- return;
160
- }
161
- try {
162
- const tokens = options.token.map((t) => t.toUpperCase());
163
- const body = {
164
- platform: options.platform,
165
- sentiment: options.sentiment,
166
- authorTier: options.tier,
167
- content: options.content,
168
- authorId: options.authorId,
169
- authorHandle: options.authorHandle,
170
- engagementScore: options.engagement,
171
- extractedEntities: tokens,
172
- narrativeTags: options.narrative ?? [],
173
- tokenSymbol: tokens[0],
174
- protocolNames: options.protocol ?? [],
175
- };
176
- const result = await apiRequest('/api/v1/social/signals', { method: 'POST', body });
177
- if (options.format === 'json') {
178
- console.log(JSON.stringify(result, null, 2));
179
- return;
180
- }
181
- if (result.duplicate) {
182
- console.log(`Duplicate signal detected, existing id=${result.id}`);
183
- return;
184
- }
185
- logger.info({ id: result.id }, 'Social signal created');
186
- console.log(`Signal created: id=${result.id}`);
187
- console.log(` Platform: ${options.platform}`);
188
- console.log(` Sentiment: ${options.sentiment}`);
189
- console.log(` Tier: ${options.tier}`);
190
- console.log(` Tokens: ${tokens.join(', ')}`);
191
- if (options.narrative) {
192
- console.log(` Narratives: ${options.narrative.join(', ')}`);
193
- }
194
- }
195
- catch (error) {
196
- const message = error instanceof Error ? error.message : String(error);
197
- logger.error({ error: message }, 'Failed to add social signal');
198
- console.error(`Error: ${message}`);
199
- process.exitCode = error instanceof ApiError ? 2 : 1;
200
- }
201
- });
202
- // ─── social list ───
203
- social
204
- .command('list')
205
- .description('List recent social signals')
206
- .option('--token <symbol>', 'Filter by token symbol')
207
- .option('--platform <platform>', 'Filter by platform')
208
- .option('--hours <n>', 'Time window in hours', (v) => parseInt(v, 10), 24)
209
- .option('--limit <n>', 'Maximum number of results', (v) => parseInt(v, 10), 20)
210
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
211
- .action(async (options) => {
212
- try {
213
- const params = new URLSearchParams();
214
- if (options.token)
215
- params.set('tokenSymbol', options.token.toUpperCase());
216
- if (options.platform)
217
- params.set('platform', options.platform);
218
- params.set('hours', String(options.hours));
219
- params.set('limit', String(options.limit));
220
- const records = await apiRequest(`/api/v1/social/signals?${params.toString()}`);
221
- if (records.length === 0) {
222
- if (options.format === 'json') {
223
- console.log(JSON.stringify([], null, 2));
224
- }
225
- else {
226
- console.log('No signals found.');
227
- }
228
- return;
229
- }
230
- if (options.format === 'json') {
231
- console.log(JSON.stringify(records, null, 2));
232
- return;
233
- }
234
- // Print formatted table
235
- console.log('');
236
- console.log(padRight('Platform', 12) +
237
- padRight('Sentiment', 11) +
238
- padRight('Tier', 22) +
239
- padRight('Entities', 20) +
240
- padRight('Content', 40));
241
- console.log('-'.repeat(105));
242
- for (const s of records) {
243
- const sentimentStr = formatSentiment(s.sentiment);
244
- const entities = s.extractedEntities
245
- ? s.extractedEntities.join(', ')
246
- : '-';
247
- console.log(padRight(s.platform, 12) +
248
- padRight(sentimentStr, 11) +
249
- padRight(s.authorTier, 22) +
250
- padRight(truncate(entities, 18), 20) +
251
- truncate(s.content ?? '-', 38));
252
- }
253
- console.log('');
254
- console.log(`Total: ${records.length} signal(s)`);
255
- }
256
- catch (error) {
257
- const message = error instanceof Error ? error.message : String(error);
258
- logger.error({ error: message }, 'Failed to list signals');
259
- console.error(`Error: ${message}`);
260
- process.exitCode = error instanceof ApiError ? 2 : 1;
261
- }
262
- });
263
- // ─── social sentiment ───
264
- social
265
- .command('sentiment')
266
- .description('Show aggregated sentiment for a token')
267
- .requiredOption('--token <symbol>', 'Token symbol')
268
- .option('--hours <n>', 'Time window in hours', (v) => parseInt(v, 10), 24)
269
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
270
- .action(async (options) => {
271
- try {
272
- const tokenSymbol = options.token.toUpperCase();
273
- // Fetch signals and compute sentiment from them
274
- const params = new URLSearchParams();
275
- params.set('tokenSymbol', tokenSymbol);
276
- params.set('hours', String(options.hours));
277
- params.set('limit', '1000');
278
- const signals = await apiRequest(`/api/v1/social/signals?${params.toString()}`);
279
- if (signals.length === 0) {
280
- if (options.format === 'json') {
281
- console.log(JSON.stringify({ tokenSymbol, hours: options.hours, signalCount: 0, average: null, min: null, max: null }, null, 2));
282
- }
283
- else {
284
- console.log(`No signals found for ${tokenSymbol} in the last ${options.hours}h.`);
285
- }
286
- return;
287
- }
288
- // Compute sentiment from signals
289
- const sentiments = signals.map(s => s.sentiment);
290
- const avgSentiment = sentiments.reduce((a, b) => a + b, 0) / sentiments.length;
291
- const minSentiment = Math.min(...sentiments);
292
- const maxSentiment = Math.max(...sentiments);
293
- if (options.format === 'json') {
294
- console.log(JSON.stringify({ tokenSymbol, hours: options.hours, signalCount: signals.length, average: avgSentiment, min: minSentiment, max: maxSentiment }, null, 2));
295
- return;
296
- }
297
- console.log('');
298
- console.log(`Sentiment for ${tokenSymbol} (last ${options.hours}h):`);
299
- console.log(` Average: ${formatSentiment(avgSentiment)}`);
300
- console.log(` Signals: ${signals.length}`);
301
- console.log(` Min: ${formatSentiment(minSentiment)}`);
302
- console.log(` Max: ${formatSentiment(maxSentiment)}`);
303
- console.log('');
304
- }
305
- catch (error) {
306
- const message = error instanceof Error ? error.message : String(error);
307
- logger.error({ error: message }, 'Failed to get sentiment');
308
- console.error(`Error: ${message}`);
309
- process.exitCode = error instanceof ApiError ? 2 : 1;
310
- }
311
- });
312
- }
313
- // ─── Helpers ───
314
- function formatSentiment(value) {
315
- const sign = value >= 0 ? '+' : '';
316
- return `${sign}${value.toFixed(2)}`;
317
- }
318
- //# sourceMappingURL=social.js.map
@@ -1,29 +0,0 @@
1
- export interface SoulWizardAnswers {
2
- style: string;
3
- riskTolerance: string;
4
- assets: string[];
5
- timeHorizon: string;
6
- biases: string;
7
- }
8
- /**
9
- * Run the interactive SOUL wizard and return the generated SOUL text.
10
- * Throws if user aborts (Ctrl+C).
11
- */
12
- export declare function runSoulWizard(): Promise<{
13
- answers: SoulWizardAnswers;
14
- soulText: string;
15
- }>;
16
- /**
17
- * Upload a SOUL document to the trader's profile.
18
- */
19
- export declare function uploadSoul(traderName: string, soulText: string): Promise<void>;
20
- /**
21
- * Print the generated SOUL document with chalk styling.
22
- */
23
- export declare function displaySoul(soulText: string): void;
24
- /**
25
- * Run wizard + upload + display. Used by both onboarding and standalone command.
26
- * Returns true if SOUL was uploaded successfully.
27
- */
28
- export declare function runSoulWizardAndUpload(traderName: string): Promise<boolean>;
29
- //# sourceMappingURL=soul-wizard.d.ts.map
@@ -1,155 +0,0 @@
1
- // ─── SOUL Wizard ───
2
- //
3
- // Interactive wizard to generate a SOUL document from guided questions.
4
- // Shared between onboarding flow and standalone `trader soul-wizard` command.
5
- import chalk from 'chalk';
6
- import { apiRequest, ApiError } from '../api-client.js';
7
- // ─── Labels ───
8
- const STYLE_LABELS = {
9
- aggressive_momentum: 'Aggressive Momentum',
10
- conservative_value: 'Conservative Value',
11
- balanced: 'Balanced',
12
- degen: 'Degen / High Risk',
13
- macro: 'Macro / Fundamentals',
14
- };
15
- const RISK_LABELS = {
16
- low: 'Low (1-3% per trade)',
17
- medium: 'Medium (3-7%)',
18
- high: 'High (7-15%)',
19
- degen: 'Degen (15%+)',
20
- };
21
- const ASSET_LABELS = {
22
- crypto: 'Crypto',
23
- commodities: 'Commodities',
24
- equities: 'Equities',
25
- forex: 'Forex',
26
- };
27
- const HORIZON_LABELS = {
28
- scalping: 'Scalping (minutes)',
29
- day: 'Day trading (hours)',
30
- swing: 'Swing (days)',
31
- position: 'Position (weeks+)',
32
- };
33
- // ─── Wizard ───
34
- /**
35
- * Run the interactive SOUL wizard and return the generated SOUL text.
36
- * Throws if user aborts (Ctrl+C).
37
- */
38
- export async function runSoulWizard() {
39
- const { select, checkbox, input } = await import('@inquirer/prompts');
40
- const style = await select({
41
- message: 'What\'s your trading style?',
42
- choices: [
43
- { value: 'aggressive_momentum', name: 'Aggressive Momentum' },
44
- { value: 'conservative_value', name: 'Conservative Value' },
45
- { value: 'balanced', name: 'Balanced' },
46
- { value: 'degen', name: 'Degen / High Risk' },
47
- { value: 'macro', name: 'Macro / Fundamentals' },
48
- ],
49
- });
50
- const riskTolerance = await select({
51
- message: 'Risk tolerance?',
52
- choices: [
53
- { value: 'low', name: 'Low (1-3% per trade)' },
54
- { value: 'medium', name: 'Medium (3-7%)' },
55
- { value: 'high', name: 'High (7-15%)' },
56
- { value: 'degen', name: 'Degen (15%+)' },
57
- ],
58
- });
59
- const assets = await checkbox({
60
- message: 'What assets do you trade?',
61
- choices: [
62
- { value: 'crypto', name: 'Crypto' },
63
- { value: 'commodities', name: 'Commodities' },
64
- { value: 'equities', name: 'Equities' },
65
- { value: 'forex', name: 'Forex' },
66
- ],
67
- });
68
- const timeHorizon = await select({
69
- message: 'Time horizon?',
70
- choices: [
71
- { value: 'scalping', name: 'Scalping (minutes)' },
72
- { value: 'day', name: 'Day trading (hours)' },
73
- { value: 'swing', name: 'Swing (days)' },
74
- { value: 'position', name: 'Position (weeks+)' },
75
- ],
76
- });
77
- const biases = await input({
78
- message: 'Any biases to watch for? (optional, press Enter to skip)',
79
- });
80
- const answers = { style, riskTolerance, assets, timeHorizon, biases };
81
- const soulText = buildSoulDocument(answers);
82
- return { answers, soulText };
83
- }
84
- // ─── SOUL Document Builder ───
85
- function buildSoulDocument(answers) {
86
- const styleLabel = STYLE_LABELS[answers.style] ?? answers.style;
87
- const riskLabel = RISK_LABELS[answers.riskTolerance] ?? answers.riskTolerance;
88
- const assetLabels = answers.assets.map(a => ASSET_LABELS[a] ?? a).join(', ') || 'Not specified';
89
- const horizonLabel = HORIZON_LABELS[answers.timeHorizon] ?? answers.timeHorizon;
90
- const lines = [];
91
- lines.push(`Trading Style: ${styleLabel}`);
92
- lines.push(`Risk Tolerance: ${riskLabel}`);
93
- lines.push(`Asset Classes: ${assetLabels}`);
94
- lines.push(`Time Horizon: ${horizonLabel}`);
95
- if (answers.biases.trim()) {
96
- lines.push(`Known Biases: ${answers.biases.trim()}`);
97
- }
98
- lines.push('');
99
- lines.push(`This trader favors ${styleLabel.toLowerCase()} approaches with ${riskLabel.toLowerCase()} risk tolerance,`);
100
- lines.push(`primarily trading ${assetLabels.toLowerCase()}. They operate on a ${horizonLabel.toLowerCase()} timeframe.`);
101
- if (answers.biases.trim()) {
102
- lines.push(`Watch for: ${answers.biases.trim()}`);
103
- }
104
- return lines.join('\n');
105
- }
106
- // ─── Upload ───
107
- /**
108
- * Upload a SOUL document to the trader's profile.
109
- */
110
- export async function uploadSoul(traderName, soulText) {
111
- await apiRequest(`/api/v1/traders/${encodeURIComponent(traderName)}/soul`, {
112
- method: 'PUT',
113
- body: { document: soulText },
114
- });
115
- }
116
- // ─── Display ───
117
- /**
118
- * Print the generated SOUL document with chalk styling.
119
- */
120
- export function displaySoul(soulText) {
121
- console.log('');
122
- console.log(chalk.bold.cyan(' Generated SOUL Document'));
123
- console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
124
- console.log('');
125
- for (const line of soulText.split('\n')) {
126
- console.log(` ${chalk.white(line)}`);
127
- }
128
- console.log('');
129
- }
130
- // ─── Combined Flow ───
131
- /**
132
- * Run wizard + upload + display. Used by both onboarding and standalone command.
133
- * Returns true if SOUL was uploaded successfully.
134
- */
135
- export async function runSoulWizardAndUpload(traderName) {
136
- const { soulText } = await runSoulWizard();
137
- displaySoul(soulText);
138
- try {
139
- await uploadSoul(traderName, soulText);
140
- console.log(chalk.green(` \u2713 SOUL uploaded for trader "${traderName}"`));
141
- return true;
142
- }
143
- catch (error) {
144
- if (error instanceof ApiError) {
145
- console.log(chalk.yellow(` Could not upload SOUL: ${error.message}`));
146
- }
147
- else {
148
- const msg = error instanceof Error ? error.message : String(error);
149
- console.log(chalk.yellow(` Could not upload SOUL: ${msg}`));
150
- }
151
- console.log(chalk.dim(' You can upload it later: trading-boy trader soul <name> --file soul.md'));
152
- return false;
153
- }
154
- }
155
- //# sourceMappingURL=soul-wizard.js.map
@@ -1,44 +0,0 @@
1
- import { Command } from 'commander';
2
- interface AgentStrategy {
3
- id: string;
4
- agentId: string;
5
- traderId: string;
6
- tenantId: string;
7
- version: number;
8
- name: string;
9
- tokens: string[];
10
- setupTypes: string[];
11
- regimeBehavior: Record<string, unknown>;
12
- riskLimits: Record<string, unknown>;
13
- signalWeights: Record<string, number>;
14
- narrativePreferences: string[];
15
- active: boolean;
16
- createdAt: string;
17
- updatedAt: string;
18
- }
19
- interface StrategyListResponse {
20
- strategies: AgentStrategy[];
21
- total: number;
22
- limit: number;
23
- offset: number;
24
- }
25
- interface StrategyHistoryEntry {
26
- id: string;
27
- strategyId: string;
28
- version: number;
29
- name: string;
30
- tokens: string[];
31
- setupTypes: string[];
32
- changedAt: string;
33
- changedBy?: string;
34
- }
35
- interface StrategyHistoryResponse {
36
- strategyId: string;
37
- history: StrategyHistoryEntry[];
38
- }
39
- export declare function formatStrategyDetail(s: AgentStrategy): string;
40
- export declare function formatStrategyList(response: StrategyListResponse): string;
41
- export declare function formatHistoryList(response: StrategyHistoryResponse): string;
42
- export declare function registerStrategyCommand(program: Command): void;
43
- export {};
44
- //# sourceMappingURL=strategy-cmd.d.ts.map