@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,259 +0,0 @@
1
- import { Option } from 'commander';
2
- import chalk from 'chalk';
3
- import { NarrativeStatus, } from '@trading-boy/core';
4
- import { padRight, truncate } from '../utils.js';
5
- import { apiRequest, ApiError } from '../api-client.js';
6
- // ─── Helpers ───
7
- const VALID_STATUSES = Object.values(NarrativeStatus);
8
- // ─── Command Registration ───
9
- export function registerNarrativeCommand(program) {
10
- const narrative = program
11
- .command('narrative')
12
- .description('Manage market narratives');
13
- // ─── narrative create ───
14
- narrative
15
- .command('create <name>')
16
- .description('Create a new narrative')
17
- .option('--status <status>', `Initial status (${VALID_STATUSES.join(', ')})`, 'EMERGING')
18
- .option('--momentum <score>', 'Momentum score (0-100)', parseFloat, 0)
19
- .option('--description <desc>', 'Narrative description')
20
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
21
- .action(async (name, options) => {
22
- // Validate non-empty name
23
- if (!name.trim()) {
24
- console.error('Error: Narrative name cannot be empty');
25
- process.exitCode = 1;
26
- return;
27
- }
28
- // Validate status
29
- if (!VALID_STATUSES.includes(options.status)) {
30
- console.error(`Error: Invalid status "${options.status}". Valid values: ${VALID_STATUSES.join(', ')}`);
31
- process.exitCode = 1;
32
- return;
33
- }
34
- // Validate momentum
35
- if (isNaN(options.momentum) || options.momentum < 0 || options.momentum > 100) {
36
- console.error('Error: Momentum score must be a number between 0 and 100');
37
- process.exitCode = 1;
38
- return;
39
- }
40
- try {
41
- const result = await apiRequest('/api/v1/narratives', {
42
- method: 'POST',
43
- body: {
44
- name: name.trim(),
45
- status: options.status,
46
- momentum: options.momentum,
47
- description: options.description,
48
- },
49
- });
50
- if (options.format === 'json') {
51
- console.log(JSON.stringify(result, null, 2));
52
- }
53
- else {
54
- console.log(`Narrative created: id=${result.id}`);
55
- console.log(` Name: ${name}`);
56
- console.log(` Status: ${options.status}`);
57
- console.log(` Momentum: ${options.momentum}`);
58
- if (options.description) {
59
- console.log(` Description: ${options.description}`);
60
- }
61
- }
62
- }
63
- catch (error) {
64
- if (error instanceof ApiError && error.status === 409) {
65
- const body = error.body;
66
- console.error(`Error: Narrative "${name.trim()}" already exists${body?.id ? ` (id=${body.id})` : ''}. Use "narrative update" to modify it.`);
67
- }
68
- else {
69
- const message = error instanceof Error ? error.message : String(error);
70
- console.error(`Error: ${message}`);
71
- }
72
- process.exitCode = error instanceof ApiError ? 2 : 1;
73
- }
74
- });
75
- // ─── narrative update ───
76
- narrative
77
- .command('update <name>')
78
- .description('Update an existing narrative')
79
- .option('--status <status>', `New status (${VALID_STATUSES.join(', ')})`)
80
- .option('--momentum <score>', 'New momentum score (0-100)', parseFloat)
81
- .option('--description <desc>', 'New description')
82
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
83
- .action(async (name, options) => {
84
- // Validate status if provided
85
- if (options.status && !VALID_STATUSES.includes(options.status)) {
86
- console.error(`Error: Invalid status "${options.status}". Valid values: ${VALID_STATUSES.join(', ')}`);
87
- process.exitCode = 1;
88
- return;
89
- }
90
- // Validate momentum if provided
91
- if (options.momentum !== undefined && (isNaN(options.momentum) || options.momentum < 0 || options.momentum > 100)) {
92
- console.error('Error: Momentum score must be a number between 0 and 100');
93
- process.exitCode = 1;
94
- return;
95
- }
96
- // Must provide at least one update
97
- if (!options.status && options.momentum === undefined && !options.description) {
98
- console.error('Error: At least one of --status, --momentum, or --description must be provided');
99
- process.exitCode = 1;
100
- return;
101
- }
102
- try {
103
- const result = await apiRequest(`/api/v1/narratives/${encodeURIComponent(name)}`, {
104
- method: 'PATCH',
105
- body: {
106
- status: options.status,
107
- momentum: options.momentum,
108
- description: options.description,
109
- },
110
- });
111
- if (options.format === 'json') {
112
- console.log(JSON.stringify(result, null, 2));
113
- }
114
- else {
115
- console.log(`Narrative updated: ${name}`);
116
- console.log(` Status: ${result.status}`);
117
- console.log(` Momentum: ${result.momentumScore}`);
118
- if (result.description) {
119
- console.log(` Description: ${result.description}`);
120
- }
121
- }
122
- }
123
- catch (error) {
124
- if (error instanceof ApiError && error.status === 404) {
125
- console.error(`Error: Narrative "${name}" not found`);
126
- }
127
- else {
128
- const message = error instanceof Error ? error.message : String(error);
129
- console.error(`Error: ${message}`);
130
- }
131
- process.exitCode = error instanceof ApiError ? 2 : 1;
132
- }
133
- });
134
- // ─── narrative list ───
135
- narrative
136
- .command('list')
137
- .description('List narratives')
138
- .option('--status <status>', 'Filter by status')
139
- .option('--limit <n>', 'Maximum number of results', parseInt, 20)
140
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
141
- .action(async (options) => {
142
- // Validate status if provided
143
- if (options.status && !VALID_STATUSES.includes(options.status)) {
144
- console.error(`Error: Invalid status "${options.status}". Valid values: ${VALID_STATUSES.join(', ')}`);
145
- process.exitCode = 1;
146
- return;
147
- }
148
- try {
149
- const params = new URLSearchParams();
150
- if (options.status)
151
- params.set('status', options.status);
152
- if (options.limit)
153
- params.set('limit', String(options.limit));
154
- const qs = params.toString() ? `?${params.toString()}` : '';
155
- const result = await apiRequest(`/api/v1/narratives${qs}`);
156
- const records = result.narratives ?? [];
157
- if (records.length === 0) {
158
- console.log('No narratives found.');
159
- return;
160
- }
161
- if (options.format === 'json') {
162
- console.log(JSON.stringify(records, null, 2));
163
- return;
164
- }
165
- // Print formatted table (no token data available from this endpoint)
166
- console.log('');
167
- console.log(padRight('Name', 25) +
168
- padRight('Status', 12) +
169
- padRight('Momentum', 10));
170
- console.log('-'.repeat(47));
171
- for (const n of records) {
172
- console.log(padRight(truncate(n.name, 23), 25) +
173
- padRight(n.status, 12) +
174
- padRight(String(n.momentumScore), 10));
175
- }
176
- console.log('');
177
- console.log(`Total: ${records.length} narrative(s)`);
178
- }
179
- catch (error) {
180
- const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
181
- console.error(`Error: ${message}`);
182
- process.exitCode = error instanceof ApiError ? 2 : 1;
183
- }
184
- });
185
- // ─── narrative link ───
186
- narrative
187
- .command('link <token> <narrative>')
188
- .description('Link a token to a narrative')
189
- .option('--confidence <score>', 'Confidence score (0-1)', parseFloat, 0.5)
190
- .action(async (token, narrativeName) => {
191
- try {
192
- const result = await apiRequest(`/api/v1/narratives/${encodeURIComponent(narrativeName)}/link`, { method: 'POST', body: { tokenSymbol: token.toUpperCase() } });
193
- console.log(chalk.green(`\n ✓ Linked ${result.tokenSymbol} to narrative "${result.narrative}"\n`));
194
- }
195
- catch (error) {
196
- const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
197
- console.error(chalk.red(`Error: ${message}`));
198
- process.exitCode = error instanceof ApiError ? 2 : 1;
199
- }
200
- });
201
- // ─── narrative unlink ───
202
- narrative
203
- .command('unlink <token> <narrative>')
204
- .description('Unlink a token from a narrative')
205
- .action(async (token, narrativeName) => {
206
- try {
207
- const result = await apiRequest(`/api/v1/narratives/${encodeURIComponent(narrativeName)}/unlink`, { method: 'POST', body: { tokenSymbol: token.toUpperCase() } });
208
- console.log(chalk.green(`\n ✓ Unlinked ${result.tokenSymbol} from narrative "${result.narrative}"\n`));
209
- }
210
- catch (error) {
211
- const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
212
- console.error(chalk.red(`Error: ${message}`));
213
- process.exitCode = error instanceof ApiError ? 2 : 1;
214
- }
215
- });
216
- // ─── narrative show ───
217
- narrative
218
- .command('show <name>')
219
- .description('Show narrative details with linked tokens')
220
- .addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
221
- .action(async (name, options) => {
222
- try {
223
- const record = await apiRequest(`/api/v1/narratives/${encodeURIComponent(name)}`);
224
- if (options.format === 'json') {
225
- console.log(JSON.stringify(record, null, 2));
226
- }
227
- else {
228
- console.log('');
229
- console.log(`Narrative: ${record.name}`);
230
- console.log(` ID: ${record.id}`);
231
- console.log(` Status: ${record.status}`);
232
- console.log(` Momentum: ${record.momentumScore}`);
233
- if (record.description) {
234
- console.log(` Description: ${record.description}`);
235
- }
236
- if (record.firstDetected) {
237
- console.log(` First Detected: ${record.firstDetected}`);
238
- }
239
- if (record.peakDate) {
240
- console.log(` Peak Date: ${record.peakDate}`);
241
- }
242
- console.log('');
243
- console.log(' (Linked token details not yet available via API)');
244
- }
245
- }
246
- catch (error) {
247
- if (error instanceof ApiError && error.status === 404) {
248
- console.error(`Error: Narrative "${name}" not found`);
249
- }
250
- else {
251
- const message = error instanceof Error ? error.message : String(error);
252
- console.error(`Error: ${message}`);
253
- }
254
- process.exitCode = error instanceof ApiError ? 2 : 1;
255
- }
256
- });
257
- }
258
- // LinkOptions removed — link now uses API directly
259
- //# sourceMappingURL=narratives.js.map
@@ -1,7 +0,0 @@
1
- /**
2
- * Run the interactive onboarding wizard.
3
- * Called after subscribe completes successfully.
4
- * Gracefully handles Ctrl+C and skipped steps.
5
- */
6
- export declare function runOnboarding(): Promise<void>;
7
- //# sourceMappingURL=onboarding.d.ts.map
@@ -1,298 +0,0 @@
1
- // ─── Post-Subscribe Onboarding Wizard ───
2
- //
3
- // Guided setup after a new user subscribes. Walks through:
4
- // 1. Register a trader profile (name + risk tolerance)
5
- // 2. Identity setup (SOUL wizard)
6
- // 3. LLM provider — ChatGPT OAuth or BYOK API key
7
- // 4. Connect Telegram bot for daily summaries
8
- // 5. Agent runtime overview (scan intervals, autonomy levels)
9
- // 6. Quick reference cheat sheet
10
- import chalk from 'chalk';
11
- import { isRemoteMode, apiRequest, ApiError } from '../api-client.js';
12
- import { runSoulWizardAndUpload } from './soul-wizard.js';
13
- import { connectChatgpt } from './connect-chatgpt.js';
14
- import { connectClaude } from './connect-claude.js';
15
- // ─── Onboarding Flow ───
16
- /**
17
- * Run the interactive onboarding wizard.
18
- * Called after subscribe completes successfully.
19
- * Gracefully handles Ctrl+C and skipped steps.
20
- */
21
- export async function runOnboarding() {
22
- const { confirm, input } = await import('@inquirer/prompts');
23
- console.log('');
24
- console.log(chalk.bold.cyan(' Get Started'));
25
- console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
26
- console.log(chalk.dim(' Let\u2019s set up your account. You can skip any step.'));
27
- console.log('');
28
- // ─── Step 1: Register Trader ───
29
- let traderRegistered = false;
30
- let traderName = 'default';
31
- try {
32
- const wantsTrader = await confirm({
33
- message: 'Register your trader profile?',
34
- default: true,
35
- });
36
- if (wantsTrader) {
37
- const name = await input({
38
- message: 'Trader name (this will appear on the public leaderboard — use a pseudonym to stay anonymous)',
39
- default: 'default',
40
- validate: (v) => (v.trim().length > 0 ? true : 'Name cannot be empty'),
41
- });
42
- const maxDrawdown = await input({
43
- message: 'Max drawdown % (risk tolerance)',
44
- default: '15',
45
- validate: (v) => {
46
- const n = parseFloat(v);
47
- if (isNaN(n) || n <= 0 || n > 100)
48
- return 'Enter a number between 1 and 100';
49
- return true;
50
- },
51
- });
52
- try {
53
- if (await isRemoteMode()) {
54
- const result = await apiRequest('/api/v1/traders', {
55
- method: 'POST',
56
- body: { name: name.trim(), riskToleranceMax: parseFloat(maxDrawdown) },
57
- });
58
- console.log(chalk.green(` \u2713 Trader "${result.name}" registered (id: ${result.id})`));
59
- if (result.publicAlias) {
60
- console.log(chalk.dim(` Leaderboard alias: ${result.publicAlias}`));
61
- console.log(chalk.dim(' This alias is public on the leaderboard. Change it anytime:'));
62
- console.log(chalk.dim(' trading-boy trader set-alias <name> <new-alias>'));
63
- }
64
- traderName = name.trim();
65
- traderRegistered = true;
66
- }
67
- else {
68
- console.log(chalk.yellow(' Skipped \u2014 not connected to API. Run: trading-boy trader register'));
69
- }
70
- }
71
- catch (error) {
72
- if (error instanceof ApiError && error.status === 409) {
73
- console.log(chalk.green(' \u2713 Trader profile already exists.'));
74
- traderName = name.trim();
75
- traderRegistered = true;
76
- }
77
- else {
78
- const msg = error instanceof Error ? error.message : String(error);
79
- console.log(chalk.yellow(` Could not register trader: ${msg}`));
80
- console.log(chalk.dim(' You can do this later: trading-boy trader register --name "YourName"'));
81
- }
82
- }
83
- }
84
- else {
85
- console.log(chalk.dim(' Skipped. Run later: trading-boy trader register --name "YourName"'));
86
- }
87
- }
88
- catch (error) {
89
- if (isUserAbort(error))
90
- return;
91
- throw error;
92
- }
93
- console.log('');
94
- // ─── Step 2: Identity Setup ───
95
- if (traderRegistered) {
96
- try {
97
- const wantsIdentity = await confirm({
98
- message: 'Set up your trading identity? (interactive SOUL wizard)',
99
- default: true,
100
- });
101
- if (wantsIdentity) {
102
- console.log('');
103
- console.log(chalk.dim(' Your identity personalizes context — bias warnings, scope checks,'));
104
- console.log(chalk.dim(' and tailored synthesis based on who you are as a trader.'));
105
- console.log('');
106
- try {
107
- await runSoulWizardAndUpload(traderName);
108
- }
109
- catch (wizardError) {
110
- if (isUserAbort(wizardError))
111
- return;
112
- const msg = wizardError instanceof Error ? wizardError.message : String(wizardError);
113
- console.log(chalk.yellow(` Could not complete SOUL wizard: ${msg}`));
114
- console.log(chalk.dim(' You can do this later: trading-boy trader soul-wizard <name>'));
115
- }
116
- }
117
- else {
118
- console.log(chalk.dim(' Skipped. Run later: trading-boy trader soul-wizard <name>'));
119
- }
120
- }
121
- catch (error) {
122
- if (isUserAbort(error))
123
- return;
124
- throw error;
125
- }
126
- console.log('');
127
- }
128
- // ─── Step 3: LLM Provider ───
129
- try {
130
- console.log(chalk.bold.cyan(' LLM Provider (required for agents)'));
131
- console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
132
- console.log(chalk.dim(' Your agent needs an LLM to analyze markets and make decisions.'));
133
- console.log('');
134
- const { select } = await import('@inquirer/prompts');
135
- const llmChoice = await select({
136
- message: 'How do you want to power your agent?',
137
- choices: [
138
- {
139
- name: 'Use my Claude subscription (no API key needed)',
140
- value: 'claude',
141
- description: 'Sign in with your Anthropic account — uses your existing Claude Pro/Max/Team plan',
142
- },
143
- {
144
- name: 'Use my ChatGPT subscription (no API key needed)',
145
- value: 'chatgpt',
146
- description: 'Sign in with your OpenAI account — uses your existing ChatGPT Plus/Pro/Team plan',
147
- },
148
- {
149
- name: 'Bring my own API key (Anthropic, Gemini, OpenAI, etc.)',
150
- value: 'byok',
151
- description: 'Paste an API key from any supported provider',
152
- },
153
- {
154
- name: 'Skip for now',
155
- value: 'skip',
156
- },
157
- ],
158
- });
159
- if (llmChoice === 'claude') {
160
- try {
161
- await connectClaude();
162
- }
163
- catch (error) {
164
- const msg = error instanceof Error ? error.message : String(error);
165
- console.log(chalk.yellow(` Could not connect Claude: ${msg}`));
166
- console.log(chalk.dim(' Try later: trading-boy connect-claude'));
167
- }
168
- }
169
- else if (llmChoice === 'chatgpt') {
170
- try {
171
- await connectChatgpt();
172
- }
173
- catch (error) {
174
- const msg = error instanceof Error ? error.message : String(error);
175
- console.log(chalk.yellow(` Could not connect ChatGPT: ${msg}`));
176
- console.log(chalk.dim(' Try later: trading-boy connect-chatgpt'));
177
- }
178
- }
179
- else if (llmChoice === 'byok') {
180
- console.log('');
181
- console.log(chalk.dim(' Supported providers (auto-detected from key prefix):'));
182
- console.log('');
183
- console.log(` ${chalk.white('Anthropic')} ${chalk.dim('(default) — Claude Sonnet/Opus/Haiku')}`);
184
- console.log(` ${chalk.white('Gemini')} ${chalk.dim('— Gemini 2.5 Pro')}`);
185
- console.log(` ${chalk.white('OpenAI')} ${chalk.dim('— GPT-4o / GPT-4.1')}`);
186
- console.log(` ${chalk.white('OpenRouter')} ${chalk.dim('— Any model via OpenRouter')}`);
187
- console.log(` ${chalk.white('Ollama')} ${chalk.dim('— Local models')}`);
188
- console.log('');
189
- const llmKey = await input({
190
- message: 'Paste your API key',
191
- validate: (v) => (v.trim().length > 5 ? true : 'Key is too short'),
192
- });
193
- try {
194
- if (await isRemoteMode()) {
195
- const result = await apiRequest('/api/v1/llm-config', {
196
- method: 'PUT',
197
- body: { apiKey: llmKey.trim() },
198
- });
199
- console.log(chalk.green(` ✓ LLM key saved — ${result.provider} / ${result.model}`));
200
- console.log(chalk.dim(' Change model later: trading-boy config set-llm-key <key> --model <model>'));
201
- }
202
- else {
203
- console.log(chalk.yellow(' Skipped — not connected to API.'));
204
- }
205
- }
206
- catch (error) {
207
- const msg = error instanceof Error ? error.message : String(error);
208
- console.log(chalk.yellow(` Could not save LLM key: ${msg}`));
209
- console.log(chalk.dim(' Set it later: trading-boy config set-llm-key <your-api-key>'));
210
- }
211
- }
212
- else {
213
- console.log('');
214
- console.log(chalk.yellow(' ⚠ Without an LLM provider, agents can scan prices but cannot'));
215
- console.log(chalk.yellow(' analyze markets or make trade decisions.'));
216
- console.log(chalk.dim(' Set it later: trading-boy connect-claude'));
217
- console.log(chalk.dim(' Or ChatGPT: trading-boy connect-chatgpt'));
218
- console.log(chalk.dim(' Or BYOK: trading-boy config set-llm-key <your-api-key>'));
219
- }
220
- }
221
- catch (error) {
222
- if (isUserAbort(error))
223
- return;
224
- throw error;
225
- }
226
- console.log('');
227
- // ─── Step 4: Telegram Bot ───
228
- try {
229
- const wantsTelegram = await confirm({
230
- message: 'Connect Telegram for daily summaries?',
231
- default: true,
232
- });
233
- if (wantsTelegram) {
234
- console.log('');
235
- console.log(chalk.white(' Click to open the bot: ') + chalk.cyan.underline('https://t.me/TradingBoy1_Bot'));
236
- console.log(chalk.white(' Send ') + chalk.cyan('/start') + chalk.white(' and paste your API key to connect.'));
237
- console.log('');
238
- console.log(chalk.dim(' The bot will send you a daily trading summary at 08:00 UTC.'));
239
- console.log(chalk.dim(' You can also use /summary, /agents, /positions, /pause, and /soul.'));
240
- }
241
- else {
242
- console.log(chalk.dim(' Skipped. Connect anytime: ') + chalk.dim.underline('https://t.me/TradingBoy1_Bot'));
243
- }
244
- }
245
- catch (error) {
246
- if (isUserAbort(error))
247
- return;
248
- throw error;
249
- }
250
- console.log('');
251
- // ─── Step 5: Agent Runtime Overview ───
252
- console.log(chalk.bold.cyan(' How Agents Work'));
253
- console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
254
- console.log('');
255
- console.log(chalk.dim(' Once you create an agent, it runs continuously on our servers:'));
256
- console.log('');
257
- console.log(` ${chalk.white('Scan')} ${chalk.dim('Every 30 min by default — scans your watchlist for setups')}`);
258
- console.log(` ${chalk.white('Analyze')} ${chalk.dim('When a setup is found — deep context analysis via your LLM')}`);
259
- console.log(` ${chalk.white('Decide')} ${chalk.dim('After analysis — enter/exit/hold based on your strategy')}`);
260
- console.log(` ${chalk.white('Learn')} ${chalk.dim('After trades close — updates edge profile from outcomes')}`);
261
- console.log('');
262
- console.log(chalk.dim(' Scan interval controls how often your agent checks for setups.'));
263
- console.log(chalk.dim(' Lower intervals = more LLM calls = higher cost. Recommended: 30m.'));
264
- console.log(chalk.dim(' Change it: trading-boy agent update <name> --scan-interval 15m'));
265
- console.log('');
266
- console.log(chalk.dim(' Autonomy levels:'));
267
- console.log(` ${chalk.cyan('OBSERVE_ONLY')} ${chalk.dim('Scans and analyzes — takes no action')}`);
268
- console.log(` ${chalk.cyan('SUGGEST')} ${chalk.dim('Sends trade ideas to your Telegram')}`);
269
- console.log(` ${chalk.cyan('AUTO_WITH_APPROVAL')} ${chalk.dim('Proposes trades, waits for your OK')}`);
270
- console.log(` ${chalk.cyan('FULLY_AUTONOMOUS')} ${chalk.dim('Trades within your guardrails, no human in the loop')}`);
271
- console.log('');
272
- console.log(chalk.dim(' Create your first agent:'));
273
- console.log(` ${chalk.white('trading-boy agent create --help')}`);
274
- console.log('');
275
- // ─── Step 6: Quick Reference ───
276
- console.log(chalk.bold.cyan(' Quick Reference'));
277
- console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
278
- console.log('');
279
- console.log(` ${chalk.white('trading-boy context SOL')} ${chalk.dim('Full context for any token')}`);
280
- console.log(` ${chalk.white('trading-boy agent create')} ${chalk.dim('Create an autonomous agent')}`);
281
- console.log(` ${chalk.white('trading-boy agent list')} ${chalk.dim('View your running agents')}`);
282
- console.log(` ${chalk.white('trading-boy decisions')} ${chalk.dim('View trade history')}`);
283
- console.log(` ${chalk.white('trading-boy stats')} ${chalk.dim('Track performance')}`);
284
- console.log(` ${chalk.white('trading-boy narrative list')} ${chalk.dim('Active market narratives')}`);
285
- console.log(` ${chalk.white('trading-boy catalysts')} ${chalk.dim('Upcoming events')}`);
286
- if (traderRegistered) {
287
- console.log(` ${chalk.white('trading-boy edge')} ${chalk.dim('Your edge profile')}`);
288
- console.log(` ${chalk.white('trading-boy behavioral')} ${chalk.dim('Behavioral analysis')}`);
289
- }
290
- console.log('');
291
- console.log(chalk.dim(' Full docs: https://api.cabal.ventures/docs'));
292
- console.log('');
293
- }
294
- // ─── Helpers ───
295
- function isUserAbort(error) {
296
- return error instanceof Error && error.message.includes('User force closed');
297
- }
298
- //# sourceMappingURL=onboarding.js.map
@@ -1,32 +0,0 @@
1
- import { Command } from 'commander';
2
- interface TokenInfo {
3
- name: string | null;
4
- symbol: string;
5
- chains: string[];
6
- narratives: Array<{
7
- name: string;
8
- status: string;
9
- }>;
10
- }
11
- interface PriceInfo {
12
- price: number | null;
13
- change24h: number | null;
14
- lastUpdated: Date | null;
15
- }
16
- interface FundingInfo {
17
- fundingRate: number | null;
18
- lastUpdated: Date | null;
19
- }
20
- interface WhaleInfo {
21
- count: number;
22
- }
23
- export interface QueryResult {
24
- token: TokenInfo;
25
- price: PriceInfo;
26
- funding: FundingInfo;
27
- whaleActivity: WhaleInfo;
28
- }
29
- export declare function formatQueryOutput(result: QueryResult): string;
30
- export declare function registerQueryCommand(program: Command): void;
31
- export {};
32
- //# sourceMappingURL=query.d.ts.map