@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.
- package/LICENSE +22 -0
- package/README.md +64 -29
- package/dist/api-client.d.ts +4 -7
- package/dist/api-client.js +8 -13
- package/dist/cli.bundle.js +2314 -33711
- package/dist/credentials.js +1 -1
- package/dist/index.d.ts +0 -28
- package/dist/index.js +0 -24
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +12 -0
- package/dist/utils.js +3 -3
- package/package.json +30 -16
- package/dist/cli.d.ts +0 -5
- package/dist/cli.js +0 -157
- package/dist/commands/agent-cmd.d.ts +0 -9
- package/dist/commands/agent-cmd.js +0 -567
- package/dist/commands/audit.d.ts +0 -18
- package/dist/commands/audit.js +0 -73
- package/dist/commands/behavioral.d.ts +0 -73
- package/dist/commands/behavioral.js +0 -349
- package/dist/commands/benchmark-cmd.d.ts +0 -3
- package/dist/commands/benchmark-cmd.js +0 -191
- package/dist/commands/billing.d.ts +0 -12
- package/dist/commands/billing.js +0 -142
- package/dist/commands/catalysts.d.ts +0 -17
- package/dist/commands/catalysts.js +0 -151
- package/dist/commands/coaching-cmd.d.ts +0 -16
- package/dist/commands/coaching-cmd.js +0 -222
- package/dist/commands/config-cmd.d.ts +0 -30
- package/dist/commands/config-cmd.js +0 -515
- package/dist/commands/connect-chatgpt.d.ts +0 -5
- package/dist/commands/connect-chatgpt.js +0 -293
- package/dist/commands/connect-claude.d.ts +0 -5
- package/dist/commands/connect-claude.js +0 -280
- package/dist/commands/context.d.ts +0 -41
- package/dist/commands/context.js +0 -405
- package/dist/commands/cron-cmd.d.ts +0 -3
- package/dist/commands/cron-cmd.js +0 -305
- package/dist/commands/decisions.d.ts +0 -57
- package/dist/commands/decisions.js +0 -364
- package/dist/commands/edge-cmd.d.ts +0 -78
- package/dist/commands/edge-cmd.js +0 -183
- package/dist/commands/edge-guard-cmd.d.ts +0 -36
- package/dist/commands/edge-guard-cmd.js +0 -169
- package/dist/commands/events.d.ts +0 -3
- package/dist/commands/events.js +0 -117
- package/dist/commands/infra.d.ts +0 -24
- package/dist/commands/infra.js +0 -137
- package/dist/commands/journal.d.ts +0 -3
- package/dist/commands/journal.js +0 -302
- package/dist/commands/login.d.ts +0 -18
- package/dist/commands/login.js +0 -127
- package/dist/commands/logout.d.ts +0 -8
- package/dist/commands/logout.js +0 -108
- package/dist/commands/narratives.d.ts +0 -3
- package/dist/commands/narratives.js +0 -259
- package/dist/commands/onboarding.d.ts +0 -7
- package/dist/commands/onboarding.js +0 -281
- package/dist/commands/query.d.ts +0 -32
- package/dist/commands/query.js +0 -135
- package/dist/commands/replay-cmd.d.ts +0 -43
- package/dist/commands/replay-cmd.js +0 -184
- package/dist/commands/review.d.ts +0 -3
- package/dist/commands/review.js +0 -443
- package/dist/commands/risk.d.ts +0 -47
- package/dist/commands/risk.js +0 -158
- package/dist/commands/social.d.ts +0 -43
- package/dist/commands/social.js +0 -318
- package/dist/commands/soul-wizard.d.ts +0 -29
- package/dist/commands/soul-wizard.js +0 -155
- package/dist/commands/strategy-cmd.d.ts +0 -44
- package/dist/commands/strategy-cmd.js +0 -335
- package/dist/commands/subscribe.d.ts +0 -78
- package/dist/commands/subscribe.js +0 -552
- package/dist/commands/suggestions-cmd.d.ts +0 -24
- package/dist/commands/suggestions-cmd.js +0 -148
- package/dist/commands/thesis-cmd.d.ts +0 -3
- package/dist/commands/thesis-cmd.js +0 -129
- package/dist/commands/trader.d.ts +0 -30
- package/dist/commands/trader.js +0 -971
- package/dist/commands/watch.d.ts +0 -16
- package/dist/commands/watch.js +0 -104
- package/dist/commands/whoami.d.ts +0 -14
- 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,281 +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
|
-
// ─── Onboarding Flow ───
|
|
15
|
-
/**
|
|
16
|
-
* Run the interactive onboarding wizard.
|
|
17
|
-
* Called after subscribe completes successfully.
|
|
18
|
-
* Gracefully handles Ctrl+C and skipped steps.
|
|
19
|
-
*/
|
|
20
|
-
export async function runOnboarding() {
|
|
21
|
-
const { confirm, input } = await import('@inquirer/prompts');
|
|
22
|
-
console.log('');
|
|
23
|
-
console.log(chalk.bold.cyan(' Get Started'));
|
|
24
|
-
console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
|
|
25
|
-
console.log(chalk.dim(' Let\u2019s set up your account. You can skip any step.'));
|
|
26
|
-
console.log('');
|
|
27
|
-
// ─── Step 1: Register Trader ───
|
|
28
|
-
let traderRegistered = false;
|
|
29
|
-
let traderName = 'default';
|
|
30
|
-
try {
|
|
31
|
-
const wantsTrader = await confirm({
|
|
32
|
-
message: 'Register your trader profile?',
|
|
33
|
-
default: true,
|
|
34
|
-
});
|
|
35
|
-
if (wantsTrader) {
|
|
36
|
-
const name = await input({
|
|
37
|
-
message: 'Trader name (this will appear on the public leaderboard — use a pseudonym to stay anonymous)',
|
|
38
|
-
default: 'default',
|
|
39
|
-
validate: (v) => (v.trim().length > 0 ? true : 'Name cannot be empty'),
|
|
40
|
-
});
|
|
41
|
-
const maxDrawdown = await input({
|
|
42
|
-
message: 'Max drawdown % (risk tolerance)',
|
|
43
|
-
default: '15',
|
|
44
|
-
validate: (v) => {
|
|
45
|
-
const n = parseFloat(v);
|
|
46
|
-
if (isNaN(n) || n <= 0 || n > 100)
|
|
47
|
-
return 'Enter a number between 1 and 100';
|
|
48
|
-
return true;
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
try {
|
|
52
|
-
if (await isRemoteMode()) {
|
|
53
|
-
const result = await apiRequest('/api/v1/traders', {
|
|
54
|
-
method: 'POST',
|
|
55
|
-
body: { name: name.trim(), riskToleranceMax: parseFloat(maxDrawdown) },
|
|
56
|
-
});
|
|
57
|
-
console.log(chalk.green(` \u2713 Trader "${result.name}" registered (id: ${result.id})`));
|
|
58
|
-
if (result.publicAlias) {
|
|
59
|
-
console.log(chalk.dim(` Leaderboard alias: ${result.publicAlias}`));
|
|
60
|
-
console.log(chalk.dim(' This alias is public on the leaderboard. Change it anytime:'));
|
|
61
|
-
console.log(chalk.dim(' trading-boy trader set-alias <name> <new-alias>'));
|
|
62
|
-
}
|
|
63
|
-
traderName = name.trim();
|
|
64
|
-
traderRegistered = true;
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
console.log(chalk.yellow(' Skipped \u2014 not connected to API. Run: trading-boy trader register'));
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
if (error instanceof ApiError && error.status === 409) {
|
|
72
|
-
console.log(chalk.green(' \u2713 Trader profile already exists.'));
|
|
73
|
-
traderName = name.trim();
|
|
74
|
-
traderRegistered = true;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
78
|
-
console.log(chalk.yellow(` Could not register trader: ${msg}`));
|
|
79
|
-
console.log(chalk.dim(' You can do this later: trading-boy trader register --name "YourName"'));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
console.log(chalk.dim(' Skipped. Run later: trading-boy trader register --name "YourName"'));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
if (isUserAbort(error))
|
|
89
|
-
return;
|
|
90
|
-
throw error;
|
|
91
|
-
}
|
|
92
|
-
console.log('');
|
|
93
|
-
// ─── Step 2: Identity Setup ───
|
|
94
|
-
if (traderRegistered) {
|
|
95
|
-
try {
|
|
96
|
-
const wantsIdentity = await confirm({
|
|
97
|
-
message: 'Set up your trading identity? (interactive SOUL wizard)',
|
|
98
|
-
default: true,
|
|
99
|
-
});
|
|
100
|
-
if (wantsIdentity) {
|
|
101
|
-
console.log('');
|
|
102
|
-
console.log(chalk.dim(' Your identity personalizes context — bias warnings, scope checks,'));
|
|
103
|
-
console.log(chalk.dim(' and tailored synthesis based on who you are as a trader.'));
|
|
104
|
-
console.log('');
|
|
105
|
-
try {
|
|
106
|
-
await runSoulWizardAndUpload(traderName);
|
|
107
|
-
}
|
|
108
|
-
catch (wizardError) {
|
|
109
|
-
if (isUserAbort(wizardError))
|
|
110
|
-
return;
|
|
111
|
-
const msg = wizardError instanceof Error ? wizardError.message : String(wizardError);
|
|
112
|
-
console.log(chalk.yellow(` Could not complete SOUL wizard: ${msg}`));
|
|
113
|
-
console.log(chalk.dim(' You can do this later: trading-boy trader soul-wizard <name>'));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
console.log(chalk.dim(' Skipped. Run later: trading-boy trader soul-wizard <name>'));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
if (isUserAbort(error))
|
|
122
|
-
return;
|
|
123
|
-
throw error;
|
|
124
|
-
}
|
|
125
|
-
console.log('');
|
|
126
|
-
}
|
|
127
|
-
// ─── Step 3: LLM Provider ───
|
|
128
|
-
try {
|
|
129
|
-
console.log(chalk.bold.cyan(' LLM Provider (required for agents)'));
|
|
130
|
-
console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
|
|
131
|
-
console.log(chalk.dim(' Your agent needs an LLM to analyze markets and make decisions.'));
|
|
132
|
-
console.log('');
|
|
133
|
-
const { select } = await import('@inquirer/prompts');
|
|
134
|
-
const llmChoice = await select({
|
|
135
|
-
message: 'How do you want to power your agent?',
|
|
136
|
-
choices: [
|
|
137
|
-
{
|
|
138
|
-
name: 'Use my ChatGPT subscription (no API key needed)',
|
|
139
|
-
value: 'chatgpt',
|
|
140
|
-
description: 'Sign in with your OpenAI account — uses your existing ChatGPT Plus/Pro/Team plan',
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
name: 'Bring my own API key (Anthropic, Gemini, OpenAI, etc.)',
|
|
144
|
-
value: 'byok',
|
|
145
|
-
description: 'Paste an API key from any supported provider',
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
name: 'Skip for now',
|
|
149
|
-
value: 'skip',
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
});
|
|
153
|
-
if (llmChoice === 'chatgpt') {
|
|
154
|
-
try {
|
|
155
|
-
await connectChatgpt();
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
159
|
-
console.log(chalk.yellow(` Could not connect ChatGPT: ${msg}`));
|
|
160
|
-
console.log(chalk.dim(' Try later: trading-boy connect-chatgpt'));
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else if (llmChoice === 'byok') {
|
|
164
|
-
console.log('');
|
|
165
|
-
console.log(chalk.dim(' Supported providers (auto-detected from key prefix):'));
|
|
166
|
-
console.log('');
|
|
167
|
-
console.log(` ${chalk.white('Anthropic')} ${chalk.dim('(default) — Claude Sonnet/Opus/Haiku')}`);
|
|
168
|
-
console.log(` ${chalk.white('Gemini')} ${chalk.dim('— Gemini 2.5 Pro')}`);
|
|
169
|
-
console.log(` ${chalk.white('OpenAI')} ${chalk.dim('— GPT-4o / GPT-4.1')}`);
|
|
170
|
-
console.log(` ${chalk.white('OpenRouter')} ${chalk.dim('— Any model via OpenRouter')}`);
|
|
171
|
-
console.log(` ${chalk.white('Ollama')} ${chalk.dim('— Local models')}`);
|
|
172
|
-
console.log('');
|
|
173
|
-
const llmKey = await input({
|
|
174
|
-
message: 'Paste your API key',
|
|
175
|
-
validate: (v) => (v.trim().length > 5 ? true : 'Key is too short'),
|
|
176
|
-
});
|
|
177
|
-
try {
|
|
178
|
-
if (await isRemoteMode()) {
|
|
179
|
-
const result = await apiRequest('/api/v1/llm-config', {
|
|
180
|
-
method: 'PUT',
|
|
181
|
-
body: { apiKey: llmKey.trim() },
|
|
182
|
-
});
|
|
183
|
-
console.log(chalk.green(` ✓ LLM key saved — ${result.provider} / ${result.model}`));
|
|
184
|
-
console.log(chalk.dim(' Change model later: trading-boy config set-llm-key <key> --model <model>'));
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
console.log(chalk.yellow(' Skipped — not connected to API.'));
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
192
|
-
console.log(chalk.yellow(` Could not save LLM key: ${msg}`));
|
|
193
|
-
console.log(chalk.dim(' Set it later: trading-boy config set-llm-key <your-api-key>'));
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
console.log('');
|
|
198
|
-
console.log(chalk.yellow(' ⚠ Without an LLM provider, agents can scan prices but cannot'));
|
|
199
|
-
console.log(chalk.yellow(' analyze markets or make trade decisions.'));
|
|
200
|
-
console.log(chalk.dim(' Set it later: trading-boy connect-chatgpt'));
|
|
201
|
-
console.log(chalk.dim(' Or BYOK: trading-boy config set-llm-key <your-api-key>'));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
if (isUserAbort(error))
|
|
206
|
-
return;
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
|
-
console.log('');
|
|
210
|
-
// ─── Step 4: Telegram Bot ───
|
|
211
|
-
try {
|
|
212
|
-
const wantsTelegram = await confirm({
|
|
213
|
-
message: 'Connect Telegram for daily summaries?',
|
|
214
|
-
default: true,
|
|
215
|
-
});
|
|
216
|
-
if (wantsTelegram) {
|
|
217
|
-
console.log('');
|
|
218
|
-
console.log(chalk.white(' Click to open the bot: ') + chalk.cyan.underline('https://t.me/TradingBoy1_Bot'));
|
|
219
|
-
console.log(chalk.white(' Send ') + chalk.cyan('/start') + chalk.white(' and paste your API key to connect.'));
|
|
220
|
-
console.log('');
|
|
221
|
-
console.log(chalk.dim(' The bot will send you a daily trading summary at 08:00 UTC.'));
|
|
222
|
-
console.log(chalk.dim(' You can also use /summary, /agents, /positions, /pause, and /soul.'));
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
console.log(chalk.dim(' Skipped. Connect anytime: ') + chalk.dim.underline('https://t.me/TradingBoy1_Bot'));
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
catch (error) {
|
|
229
|
-
if (isUserAbort(error))
|
|
230
|
-
return;
|
|
231
|
-
throw error;
|
|
232
|
-
}
|
|
233
|
-
console.log('');
|
|
234
|
-
// ─── Step 5: Agent Runtime Overview ───
|
|
235
|
-
console.log(chalk.bold.cyan(' How Agents Work'));
|
|
236
|
-
console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
|
|
237
|
-
console.log('');
|
|
238
|
-
console.log(chalk.dim(' Once you create an agent, it runs continuously on our servers:'));
|
|
239
|
-
console.log('');
|
|
240
|
-
console.log(` ${chalk.white('Scan')} ${chalk.dim('Every 30 min by default — scans your watchlist for setups')}`);
|
|
241
|
-
console.log(` ${chalk.white('Analyze')} ${chalk.dim('When a setup is found — deep context analysis via your LLM')}`);
|
|
242
|
-
console.log(` ${chalk.white('Decide')} ${chalk.dim('After analysis — enter/exit/hold based on your strategy')}`);
|
|
243
|
-
console.log(` ${chalk.white('Learn')} ${chalk.dim('After trades close — updates edge profile from outcomes')}`);
|
|
244
|
-
console.log('');
|
|
245
|
-
console.log(chalk.dim(' Scan interval controls how often your agent checks for setups.'));
|
|
246
|
-
console.log(chalk.dim(' Lower intervals = more LLM calls = higher cost. Recommended: 30m.'));
|
|
247
|
-
console.log(chalk.dim(' Change it: trading-boy agent update <name> --scan-interval 15m'));
|
|
248
|
-
console.log('');
|
|
249
|
-
console.log(chalk.dim(' Autonomy levels:'));
|
|
250
|
-
console.log(` ${chalk.cyan('OBSERVE_ONLY')} ${chalk.dim('Scans and analyzes — takes no action')}`);
|
|
251
|
-
console.log(` ${chalk.cyan('SUGGEST')} ${chalk.dim('Sends trade ideas to your Telegram')}`);
|
|
252
|
-
console.log(` ${chalk.cyan('AUTO_WITH_APPROVAL')} ${chalk.dim('Proposes trades, waits for your OK')}`);
|
|
253
|
-
console.log(` ${chalk.cyan('FULLY_AUTONOMOUS')} ${chalk.dim('Trades within your guardrails, no human in the loop')}`);
|
|
254
|
-
console.log('');
|
|
255
|
-
console.log(chalk.dim(' Create your first agent:'));
|
|
256
|
-
console.log(` ${chalk.white('trading-boy agent create --help')}`);
|
|
257
|
-
console.log('');
|
|
258
|
-
// ─── Step 6: Quick Reference ───
|
|
259
|
-
console.log(chalk.bold.cyan(' Quick Reference'));
|
|
260
|
-
console.log(chalk.gray(' ' + '\u2500'.repeat(50)));
|
|
261
|
-
console.log('');
|
|
262
|
-
console.log(` ${chalk.white('trading-boy context SOL')} ${chalk.dim('Full context for any token')}`);
|
|
263
|
-
console.log(` ${chalk.white('trading-boy agent create')} ${chalk.dim('Create an autonomous agent')}`);
|
|
264
|
-
console.log(` ${chalk.white('trading-boy agent list')} ${chalk.dim('View your running agents')}`);
|
|
265
|
-
console.log(` ${chalk.white('trading-boy decisions')} ${chalk.dim('View trade history')}`);
|
|
266
|
-
console.log(` ${chalk.white('trading-boy stats')} ${chalk.dim('Track performance')}`);
|
|
267
|
-
console.log(` ${chalk.white('trading-boy narrative list')} ${chalk.dim('Active market narratives')}`);
|
|
268
|
-
console.log(` ${chalk.white('trading-boy catalysts')} ${chalk.dim('Upcoming events')}`);
|
|
269
|
-
if (traderRegistered) {
|
|
270
|
-
console.log(` ${chalk.white('trading-boy edge')} ${chalk.dim('Your edge profile')}`);
|
|
271
|
-
console.log(` ${chalk.white('trading-boy behavioral')} ${chalk.dim('Behavioral analysis')}`);
|
|
272
|
-
}
|
|
273
|
-
console.log('');
|
|
274
|
-
console.log(chalk.dim(' Full docs: https://api.cabal.ventures/docs'));
|
|
275
|
-
console.log('');
|
|
276
|
-
}
|
|
277
|
-
// ─── Helpers ───
|
|
278
|
-
function isUserAbort(error) {
|
|
279
|
-
return error instanceof Error && error.message.includes('User force closed');
|
|
280
|
-
}
|
|
281
|
-
//# sourceMappingURL=onboarding.js.map
|
package/dist/commands/query.d.ts
DELETED
|
@@ -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
|