@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,148 +0,0 @@
|
|
|
1
|
-
import { Option } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { createLogger } from '@trading-boy/core';
|
|
4
|
-
import { apiRequest, ApiError } from '../api-client.js';
|
|
5
|
-
import { padRight, truncate, formatDate, ensureRemote } from '../utils.js';
|
|
6
|
-
// ─── Logger ───
|
|
7
|
-
const logger = createLogger('cli-suggestions');
|
|
8
|
-
// ─── Formatters ───
|
|
9
|
-
export function formatSuggestionsList(data) {
|
|
10
|
-
const lines = [];
|
|
11
|
-
lines.push('');
|
|
12
|
-
lines.push(chalk.bold.cyan(' Suggestions'));
|
|
13
|
-
lines.push(chalk.gray(' ' + '─'.repeat(90)));
|
|
14
|
-
lines.push('');
|
|
15
|
-
if (data.suggestions.length === 0) {
|
|
16
|
-
lines.push(` ${chalk.dim('No suggestions found.')}`);
|
|
17
|
-
lines.push('');
|
|
18
|
-
return lines.join('\n');
|
|
19
|
-
}
|
|
20
|
-
// Header
|
|
21
|
-
lines.push(' ' +
|
|
22
|
-
padRight('ID', 14) +
|
|
23
|
-
padRight('Parameter', 30) +
|
|
24
|
-
padRight('Suggested', 16) +
|
|
25
|
-
padRight('Confidence', 12) +
|
|
26
|
-
padRight('Status', 12) +
|
|
27
|
-
'Date');
|
|
28
|
-
lines.push(' ' + '─'.repeat(90));
|
|
29
|
-
for (const s of data.suggestions) {
|
|
30
|
-
const id = truncate(s.id, 12);
|
|
31
|
-
const param = truncate(s.parameter, 28);
|
|
32
|
-
const value = truncate(String(s.suggested_value), 14);
|
|
33
|
-
const conf = `${(s.confidence * 100).toFixed(0)}%`;
|
|
34
|
-
const status = colorStatus(s.status);
|
|
35
|
-
const date = formatDate(s.created_at);
|
|
36
|
-
lines.push(' ' +
|
|
37
|
-
padRight(id, 14) +
|
|
38
|
-
padRight(param, 30) +
|
|
39
|
-
padRight(value, 16) +
|
|
40
|
-
padRight(conf, 12) +
|
|
41
|
-
padRight(status, 12) +
|
|
42
|
-
date);
|
|
43
|
-
}
|
|
44
|
-
lines.push('');
|
|
45
|
-
lines.push(` ${chalk.gray(`Showing ${data.suggestions.length} of ${data.count} suggestion(s)`)}`);
|
|
46
|
-
lines.push('');
|
|
47
|
-
return lines.join('\n');
|
|
48
|
-
}
|
|
49
|
-
function colorStatus(status) {
|
|
50
|
-
switch (status) {
|
|
51
|
-
case 'pending': return chalk.yellow(status);
|
|
52
|
-
case 'approved': return chalk.green(status);
|
|
53
|
-
case 'rejected': return chalk.red(status);
|
|
54
|
-
default: return chalk.dim(status);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// ─── Command Registration ───
|
|
58
|
-
export function registerSuggestionsCommand(program) {
|
|
59
|
-
const cmd = program
|
|
60
|
-
.command('suggestions')
|
|
61
|
-
.description('View and manage strategy improvement suggestions')
|
|
62
|
-
.action(() => {
|
|
63
|
-
cmd.help();
|
|
64
|
-
});
|
|
65
|
-
// suggestions list
|
|
66
|
-
cmd
|
|
67
|
-
.command('list')
|
|
68
|
-
.description('List strategy suggestions')
|
|
69
|
-
.option('--status <status>', 'Filter by status: pending, approved, rejected', 'pending')
|
|
70
|
-
.option('--strategy <id>', 'Filter by strategy ID')
|
|
71
|
-
.option('--limit <n>', 'Maximum results', parseInt, 20)
|
|
72
|
-
.option('--offset <n>', 'Pagination offset', parseInt, 0)
|
|
73
|
-
.addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
|
|
74
|
-
.action(async (options) => {
|
|
75
|
-
if (!(await ensureRemote()))
|
|
76
|
-
return;
|
|
77
|
-
try {
|
|
78
|
-
const params = new URLSearchParams();
|
|
79
|
-
params.set('status', options.status);
|
|
80
|
-
if (options.strategy)
|
|
81
|
-
params.set('strategyId', options.strategy);
|
|
82
|
-
params.set('limit', String(options.limit));
|
|
83
|
-
params.set('offset', String(options.offset));
|
|
84
|
-
const data = await apiRequest(`/api/v1/suggestions?${params.toString()}`);
|
|
85
|
-
if (options.format === 'json') {
|
|
86
|
-
console.log(JSON.stringify(data, null, 2));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
console.log(formatSuggestionsList(data));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
|
|
94
|
-
logger.error({ error: message }, 'Failed to list suggestions');
|
|
95
|
-
console.error(chalk.red(`Error: ${message}`));
|
|
96
|
-
process.exitCode = error instanceof ApiError ? 2 : 1;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
// suggestions approve <id>
|
|
100
|
-
cmd
|
|
101
|
-
.command('approve <id>')
|
|
102
|
-
.description('Approve a suggestion and auto-apply to strategy')
|
|
103
|
-
.addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
|
|
104
|
-
.action(async (id, options) => {
|
|
105
|
-
if (!(await ensureRemote()))
|
|
106
|
-
return;
|
|
107
|
-
try {
|
|
108
|
-
const data = await apiRequest(`/api/v1/suggestions/${encodeURIComponent(id)}/approve`, { method: 'POST' });
|
|
109
|
-
if (options.format === 'json') {
|
|
110
|
-
console.log(JSON.stringify(data, null, 2));
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
console.log(chalk.green(`\n ✓ Suggestion ${data.id} approved. Strategy ${data.strategyId} updated.\n`));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
|
|
118
|
-
logger.error({ error: message }, 'Failed to approve suggestion');
|
|
119
|
-
console.error(chalk.red(`Error: ${message}`));
|
|
120
|
-
process.exitCode = error instanceof ApiError ? 2 : 1;
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
// suggestions reject <id>
|
|
124
|
-
cmd
|
|
125
|
-
.command('reject <id>')
|
|
126
|
-
.description('Reject a suggestion')
|
|
127
|
-
.addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
|
|
128
|
-
.action(async (id, options) => {
|
|
129
|
-
if (!(await ensureRemote()))
|
|
130
|
-
return;
|
|
131
|
-
try {
|
|
132
|
-
const data = await apiRequest(`/api/v1/suggestions/${encodeURIComponent(id)}/reject`, { method: 'POST' });
|
|
133
|
-
if (options.format === 'json') {
|
|
134
|
-
console.log(JSON.stringify(data, null, 2));
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
console.log(chalk.red(`\n ✗ Suggestion ${data.id} rejected.\n`));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
|
|
142
|
-
logger.error({ error: message }, 'Failed to reject suggestion');
|
|
143
|
-
console.error(chalk.red(`Error: ${message}`));
|
|
144
|
-
process.exitCode = error instanceof ApiError ? 2 : 1;
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
//# sourceMappingURL=suggestions-cmd.js.map
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { Option } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { createLogger } from '@trading-boy/core';
|
|
4
|
-
import { apiRequest, ApiError } from '../api-client.js';
|
|
5
|
-
import { ensureRemote } from '../utils.js';
|
|
6
|
-
// ─── Logger ───
|
|
7
|
-
const logger = createLogger('cli-thesis');
|
|
8
|
-
// ─── BYOK Error Hint ───
|
|
9
|
-
const BYOK_HINT = `LLM API key required. Run: ${chalk.white('trading-boy config set-llm-key <key>')}`;
|
|
10
|
-
// ─── Formatters ───
|
|
11
|
-
function formatThesisOutput(response) {
|
|
12
|
-
const lines = [];
|
|
13
|
-
const e = response.extraction;
|
|
14
|
-
lines.push('');
|
|
15
|
-
lines.push(chalk.bold.cyan(` Thesis Extraction \u2014 ${response.decisionId}`));
|
|
16
|
-
lines.push(chalk.gray(' ' + '\u2500'.repeat(50)));
|
|
17
|
-
lines.push('');
|
|
18
|
-
if (e.direction) {
|
|
19
|
-
lines.push(` ${chalk.gray('Direction:')} ${chalk.white(e.direction)}`);
|
|
20
|
-
}
|
|
21
|
-
if (e.timeframe) {
|
|
22
|
-
lines.push(` ${chalk.gray('Timeframe:')} ${chalk.white(e.timeframe)}`);
|
|
23
|
-
}
|
|
24
|
-
if (e.keyLevels && e.keyLevels.length > 0) {
|
|
25
|
-
const levelsStr = e.keyLevels.map(l => `$${l.price} (${l.label})`).join(', ');
|
|
26
|
-
lines.push(` ${chalk.gray('Key Levels:')} ${chalk.white(levelsStr)}`);
|
|
27
|
-
}
|
|
28
|
-
if (e.catalysts && e.catalysts.length > 0) {
|
|
29
|
-
lines.push(` ${chalk.gray('Catalysts:')} ${chalk.white(e.catalysts.join(', '))}`);
|
|
30
|
-
}
|
|
31
|
-
if (e.riskFactors && e.riskFactors.length > 0) {
|
|
32
|
-
lines.push(` ${chalk.gray('Risk Factors:')} ${chalk.white(e.riskFactors.join(', '))}`);
|
|
33
|
-
}
|
|
34
|
-
if (e.confidence !== undefined) {
|
|
35
|
-
const confLabel = e.confidence >= 0.8 ? 'HIGH' : e.confidence >= 0.5 ? 'MEDIUM' : 'LOW';
|
|
36
|
-
lines.push(` ${chalk.gray('Conviction:')} ${chalk.white(confLabel)} (${(e.confidence * 100).toFixed(0)}%)`);
|
|
37
|
-
}
|
|
38
|
-
if (e.setupType) {
|
|
39
|
-
lines.push(` ${chalk.gray('Setup:')} ${chalk.white(e.setupType)}`);
|
|
40
|
-
}
|
|
41
|
-
if (e.emotionalTag) {
|
|
42
|
-
lines.push(` ${chalk.gray('Emotional Tag:')} ${chalk.white(e.emotionalTag)}`);
|
|
43
|
-
}
|
|
44
|
-
if (e.triggers && e.triggers.length > 0) {
|
|
45
|
-
lines.push(` ${chalk.gray('Triggers:')} ${chalk.white(e.triggers.join(', '))}`);
|
|
46
|
-
}
|
|
47
|
-
if (e.cleanedThesis) {
|
|
48
|
-
lines.push('');
|
|
49
|
-
lines.push(` ${chalk.gray('Cleaned Thesis:')}`);
|
|
50
|
-
lines.push(` ${chalk.white(e.cleanedThesis)}`);
|
|
51
|
-
}
|
|
52
|
-
if (e.commitments && e.commitments.length > 0) {
|
|
53
|
-
lines.push('');
|
|
54
|
-
lines.push(chalk.gray(' Commitments:'));
|
|
55
|
-
for (const c of e.commitments) {
|
|
56
|
-
lines.push(` ${chalk.dim('\u2022')} ${c.text}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (e.behavioralFlags && e.behavioralFlags.length > 0) {
|
|
60
|
-
lines.push('');
|
|
61
|
-
lines.push(` ${chalk.yellow('Behavioral Flags:')} ${e.behavioralFlags.join(', ')}`);
|
|
62
|
-
}
|
|
63
|
-
lines.push('');
|
|
64
|
-
return lines.join('\n');
|
|
65
|
-
}
|
|
66
|
-
// ─── Command Registration ───
|
|
67
|
-
export function registerThesisCommand(program) {
|
|
68
|
-
program
|
|
69
|
-
.command('thesis <decisionId>')
|
|
70
|
-
.description('Extract structured thesis from trade decision text (requires BYOK LLM key)')
|
|
71
|
-
.requiredOption('--text <thesis>', 'Thesis text to extract from')
|
|
72
|
-
.requiredOption('--trader <traderId>', 'Trader ID')
|
|
73
|
-
.option('--token <symbol>', 'Token symbol')
|
|
74
|
-
.option('--direction <dir>', 'Trade direction (LONG or SHORT)')
|
|
75
|
-
.option('--entry-price <n>', 'Entry price', parseFloat)
|
|
76
|
-
.addOption(new Option('--format <format>', 'Output format').choices(['text', 'json']).default('text'))
|
|
77
|
-
.action(async (decisionId, options) => {
|
|
78
|
-
if (!(await ensureRemote()))
|
|
79
|
-
return;
|
|
80
|
-
// Validate direction if provided
|
|
81
|
-
if (options.direction && !['LONG', 'SHORT'].includes(options.direction.toUpperCase())) {
|
|
82
|
-
console.error(chalk.red('Error: --direction must be LONG or SHORT'));
|
|
83
|
-
process.exitCode = 1;
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const body = {
|
|
87
|
-
text: options.text,
|
|
88
|
-
traderId: options.trader,
|
|
89
|
-
};
|
|
90
|
-
if (options.token)
|
|
91
|
-
body.tokenSymbol = options.token.toUpperCase();
|
|
92
|
-
if (options.direction)
|
|
93
|
-
body.direction = options.direction.toUpperCase();
|
|
94
|
-
if (options.entryPrice !== undefined)
|
|
95
|
-
body.entryPrice = options.entryPrice;
|
|
96
|
-
try {
|
|
97
|
-
const result = await apiRequest(`/api/v1/decisions/${encodeURIComponent(decisionId)}/extract-thesis`, { method: 'POST', body });
|
|
98
|
-
if (options.format === 'json') {
|
|
99
|
-
console.log(JSON.stringify(result, null, 2));
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
console.log(formatThesisOutput(result));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
if (error instanceof ApiError && error.status === 422) {
|
|
107
|
-
console.error(chalk.yellow(BYOK_HINT));
|
|
108
|
-
process.exitCode = 2;
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
if (error instanceof ApiError && error.status === 404) {
|
|
112
|
-
const body = error.body;
|
|
113
|
-
console.error(chalk.yellow(body?.error ?? 'Decision or trader not found.'));
|
|
114
|
-
process.exitCode = 2;
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
if (error instanceof ApiError && (error.status === 403 || error.status === 401)) {
|
|
118
|
-
console.error(chalk.yellow(error.message));
|
|
119
|
-
process.exitCode = 2;
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const message = error instanceof ApiError ? error.message : (error instanceof Error ? error.message : String(error));
|
|
123
|
-
logger.error({ error: message }, 'Thesis extraction failed');
|
|
124
|
-
console.error(chalk.red(`Error: ${message}`));
|
|
125
|
-
process.exitCode = error instanceof ApiError ? 2 : 1;
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=thesis-cmd.js.map
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
interface TraderRecord {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
alias?: string;
|
|
6
|
-
maxDrawdownPct?: number;
|
|
7
|
-
riskToleranceMax?: number;
|
|
8
|
-
walletAddresses?: string[];
|
|
9
|
-
createdAt: string;
|
|
10
|
-
updatedAt: string;
|
|
11
|
-
[key: string]: unknown;
|
|
12
|
-
}
|
|
13
|
-
interface TraderWalletRecord {
|
|
14
|
-
address: string;
|
|
15
|
-
chain: string;
|
|
16
|
-
linkedAt: string;
|
|
17
|
-
since?: string;
|
|
18
|
-
[key: string]: unknown;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Format a single trader record for display.
|
|
22
|
-
*/
|
|
23
|
-
export declare function formatTraderOutput(trader: TraderRecord, wallets?: TraderWalletRecord[]): string;
|
|
24
|
-
/**
|
|
25
|
-
* Format a list of traders for display.
|
|
26
|
-
*/
|
|
27
|
-
export declare function formatTraderListOutput(traders: TraderRecord[]): string;
|
|
28
|
-
export declare function registerTraderCommand(program: Command): void;
|
|
29
|
-
export {};
|
|
30
|
-
//# sourceMappingURL=trader.d.ts.map
|