@spfunctions/cli 1.4.4 → 1.5.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.
- package/README.md +205 -48
- package/dist/cache.d.ts +6 -0
- package/dist/cache.js +31 -0
- package/dist/cache.test.d.ts +1 -0
- package/dist/cache.test.js +73 -0
- package/dist/client.test.d.ts +1 -0
- package/dist/client.test.js +89 -0
- package/dist/commands/agent.js +594 -106
- package/dist/commands/book.d.ts +17 -0
- package/dist/commands/book.js +220 -0
- package/dist/commands/dashboard.d.ts +6 -3
- package/dist/commands/dashboard.js +53 -22
- package/dist/commands/liquidity.d.ts +2 -0
- package/dist/commands/liquidity.js +128 -43
- package/dist/commands/performance.js +9 -2
- package/dist/commands/positions.js +50 -0
- package/dist/commands/scan.d.ts +1 -0
- package/dist/commands/scan.js +66 -15
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +71 -6
- package/dist/commands/telegram.d.ts +15 -0
- package/dist/commands/telegram.js +125 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +9 -0
- package/dist/config.test.d.ts +1 -0
- package/dist/config.test.js +138 -0
- package/dist/index.js +107 -9
- package/dist/polymarket.d.ts +237 -0
- package/dist/polymarket.js +353 -0
- package/dist/polymarket.test.d.ts +1 -0
- package/dist/polymarket.test.js +424 -0
- package/dist/telegram/agent-bridge.d.ts +15 -0
- package/dist/telegram/agent-bridge.js +368 -0
- package/dist/telegram/bot.d.ts +10 -0
- package/dist/telegram/bot.js +297 -0
- package/dist/telegram/commands.d.ts +11 -0
- package/dist/telegram/commands.js +120 -0
- package/dist/telegram/format.d.ts +11 -0
- package/dist/telegram/format.js +51 -0
- package/dist/telegram/format.test.d.ts +1 -0
- package/dist/telegram/format.test.js +73 -0
- package/dist/telegram/poller.d.ts +6 -0
- package/dist/telegram/poller.js +32 -0
- package/dist/topics.d.ts +3 -0
- package/dist/topics.js +65 -7
- package/dist/topics.test.d.ts +1 -0
- package/dist/topics.test.js +131 -0
- package/dist/tui/border.d.ts +33 -0
- package/dist/tui/border.js +87 -0
- package/dist/tui/chart.d.ts +19 -0
- package/dist/tui/chart.js +117 -0
- package/dist/tui/dashboard.d.ts +9 -0
- package/dist/tui/dashboard.js +814 -0
- package/dist/tui/layout.d.ts +16 -0
- package/dist/tui/layout.js +41 -0
- package/dist/tui/screen.d.ts +33 -0
- package/dist/tui/screen.js +102 -0
- package/dist/tui/state.d.ts +40 -0
- package/dist/tui/state.js +36 -0
- package/dist/tui/widgets/commandbar.d.ts +8 -0
- package/dist/tui/widgets/commandbar.js +82 -0
- package/dist/tui/widgets/detail.d.ts +9 -0
- package/dist/tui/widgets/detail.js +151 -0
- package/dist/tui/widgets/edges.d.ts +4 -0
- package/dist/tui/widgets/edges.js +34 -0
- package/dist/tui/widgets/liquidity.d.ts +9 -0
- package/dist/tui/widgets/liquidity.js +142 -0
- package/dist/tui/widgets/orders.d.ts +4 -0
- package/dist/tui/widgets/orders.js +37 -0
- package/dist/tui/widgets/portfolio.d.ts +4 -0
- package/dist/tui/widgets/portfolio.js +59 -0
- package/dist/tui/widgets/signals.d.ts +4 -0
- package/dist/tui/widgets/signals.js +31 -0
- package/dist/tui/widgets/statusbar.d.ts +8 -0
- package/dist/tui/widgets/statusbar.js +72 -0
- package/dist/tui/widgets/thesis.d.ts +4 -0
- package/dist/tui/widgets/thesis.js +66 -0
- package/dist/tui/widgets/trade.d.ts +9 -0
- package/dist/tui/widgets/trade.js +117 -0
- package/dist/tui/widgets/upcoming.d.ts +4 -0
- package/dist/tui/widgets/upcoming.js +41 -0
- package/dist/tui/widgets/whatif.d.ts +7 -0
- package/dist/tui/widgets/whatif.js +113 -0
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +111 -0
- package/package.json +6 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Border drawing — thin box-drawing characters
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CLR = exports.bgRgb = exports.rgb = void 0;
|
|
7
|
+
exports.drawBorder = drawBorder;
|
|
8
|
+
exports.drawHDivider = drawHDivider;
|
|
9
|
+
exports.fit = fit;
|
|
10
|
+
exports.sparkline = sparkline;
|
|
11
|
+
// 24-bit RGB ANSI helpers
|
|
12
|
+
const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
|
|
13
|
+
exports.rgb = rgb;
|
|
14
|
+
const bgRgb = (r, g, b) => `\x1b[48;2;${r};${g};${b}m`;
|
|
15
|
+
exports.bgRgb = bgRgb;
|
|
16
|
+
// Color palette (matching landing page: emerald on near-black)
|
|
17
|
+
exports.CLR = {
|
|
18
|
+
border: (0, exports.rgb)(63, 63, 70), // zinc-700
|
|
19
|
+
borderDim: (0, exports.rgb)(39, 39, 42), // zinc-800
|
|
20
|
+
title: (0, exports.rgb)(161, 161, 170), // zinc-400
|
|
21
|
+
text: (0, exports.rgb)(212, 212, 216), // zinc-300
|
|
22
|
+
dim: (0, exports.rgb)(113, 113, 122), // zinc-500
|
|
23
|
+
veryDim: (0, exports.rgb)(63, 63, 70), // zinc-700
|
|
24
|
+
emerald: (0, exports.rgb)(16, 185, 129), // emerald-500
|
|
25
|
+
green: (0, exports.rgb)(52, 211, 153), // emerald-400
|
|
26
|
+
red: (0, exports.rgb)(239, 68, 68), // red-500
|
|
27
|
+
yellow: (0, exports.rgb)(250, 204, 21), // yellow-400
|
|
28
|
+
white: (0, exports.rgb)(244, 244, 245), // zinc-100
|
|
29
|
+
bg: (0, exports.bgRgb)(10, 10, 10), // #0a0a0a
|
|
30
|
+
bgPanel: (0, exports.bgRgb)(13, 13, 13), // #0d0d0d
|
|
31
|
+
};
|
|
32
|
+
/** Draw a bordered box with title */
|
|
33
|
+
function drawBorder(screen, region, title) {
|
|
34
|
+
const { row, col, width, height } = region;
|
|
35
|
+
if (width < 3 || height < 3)
|
|
36
|
+
return;
|
|
37
|
+
const fg = exports.CLR.borderDim;
|
|
38
|
+
// Top
|
|
39
|
+
screen.write(row, col, '┌', fg);
|
|
40
|
+
for (let c = col + 1; c < col + width - 1; c++)
|
|
41
|
+
screen.write(row, c, '─', fg);
|
|
42
|
+
screen.write(row, col + width - 1, '┐', fg);
|
|
43
|
+
// Title
|
|
44
|
+
if (title) {
|
|
45
|
+
screen.write(row, col + 2, ` ${title} `, exports.CLR.title);
|
|
46
|
+
}
|
|
47
|
+
// Sides
|
|
48
|
+
for (let r = row + 1; r < row + height - 1; r++) {
|
|
49
|
+
screen.write(r, col, '│', fg);
|
|
50
|
+
screen.write(r, col + width - 1, '│', fg);
|
|
51
|
+
}
|
|
52
|
+
// Bottom
|
|
53
|
+
screen.write(row + height - 1, col, '└', fg);
|
|
54
|
+
for (let c = col + 1; c < col + width - 1; c++)
|
|
55
|
+
screen.write(row + height - 1, c, '─', fg);
|
|
56
|
+
screen.write(row + height - 1, col + width - 1, '┘', fg);
|
|
57
|
+
}
|
|
58
|
+
/** Draw a horizontal divider across a region at a relative row */
|
|
59
|
+
function drawHDivider(screen, region, relRow) {
|
|
60
|
+
const r = region.row + relRow;
|
|
61
|
+
const fg = exports.CLR.borderDim;
|
|
62
|
+
screen.write(r, region.col, '├', fg);
|
|
63
|
+
for (let c = region.col + 1; c < region.col + region.width - 1; c++)
|
|
64
|
+
screen.write(r, c, '─', fg);
|
|
65
|
+
screen.write(r, region.col + region.width - 1, '┤', fg);
|
|
66
|
+
}
|
|
67
|
+
/** Pad/truncate string to exact width */
|
|
68
|
+
function fit(s, width, align = 'left') {
|
|
69
|
+
if (s.length > width)
|
|
70
|
+
return s.slice(0, width - 1) + '…';
|
|
71
|
+
if (align === 'right')
|
|
72
|
+
return s.padStart(width);
|
|
73
|
+
return s.padEnd(width);
|
|
74
|
+
}
|
|
75
|
+
/** Build sparkline from values */
|
|
76
|
+
function sparkline(values, colorFn) {
|
|
77
|
+
if (values.length === 0)
|
|
78
|
+
return [];
|
|
79
|
+
const min = Math.min(...values);
|
|
80
|
+
const max = Math.max(...values);
|
|
81
|
+
const range = max - min || 1;
|
|
82
|
+
const blocks = '▁▂▃▄▅▆▇█';
|
|
83
|
+
return values.map(v => {
|
|
84
|
+
const idx = Math.round(((v - min) / range) * 7);
|
|
85
|
+
return { text: blocks[idx], fg: colorFn ? colorFn(v) : exports.CLR.dim };
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ASCII area chart using block characters
|
|
3
|
+
*
|
|
4
|
+
* Uses ▁▂▃▄▅▆▇█ to draw a filled area chart that fills the width.
|
|
5
|
+
* Much cleaner than box-drawing line charts for small datasets.
|
|
6
|
+
*/
|
|
7
|
+
import type { ScreenBuffer } from './screen.js';
|
|
8
|
+
/**
|
|
9
|
+
* Draw an area chart at the given position.
|
|
10
|
+
*
|
|
11
|
+
* @param screen - ScreenBuffer to write to
|
|
12
|
+
* @param row - Top-left row of chart area
|
|
13
|
+
* @param col - Left column (after Y-axis labels)
|
|
14
|
+
* @param width - Total width including Y-axis labels
|
|
15
|
+
* @param height - Total height including X-axis row
|
|
16
|
+
* @param values - Data points (raw numbers)
|
|
17
|
+
* @param labels - Optional X-axis labels
|
|
18
|
+
*/
|
|
19
|
+
export declare function drawChart(screen: ScreenBuffer, row: number, col: number, width: number, height: number, values: number[], labels?: string[]): void;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ASCII area chart using block characters
|
|
4
|
+
*
|
|
5
|
+
* Uses ▁▂▃▄▅▆▇█ to draw a filled area chart that fills the width.
|
|
6
|
+
* Much cleaner than box-drawing line charts for small datasets.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.drawChart = drawChart;
|
|
10
|
+
const border_js_1 = require("./border.js");
|
|
11
|
+
/**
|
|
12
|
+
* Draw an area chart at the given position.
|
|
13
|
+
*
|
|
14
|
+
* @param screen - ScreenBuffer to write to
|
|
15
|
+
* @param row - Top-left row of chart area
|
|
16
|
+
* @param col - Left column (after Y-axis labels)
|
|
17
|
+
* @param width - Total width including Y-axis labels
|
|
18
|
+
* @param height - Total height including X-axis row
|
|
19
|
+
* @param values - Data points (raw numbers)
|
|
20
|
+
* @param labels - Optional X-axis labels
|
|
21
|
+
*/
|
|
22
|
+
function drawChart(screen, row, col, width, height, values, labels) {
|
|
23
|
+
if (values.length === 0 || width < 10 || height < 4)
|
|
24
|
+
return;
|
|
25
|
+
const yLabelWidth = 8;
|
|
26
|
+
const chartWidth = width - yLabelWidth - 1;
|
|
27
|
+
const chartHeight = height - 2; // reserve bottom for x-axis + labels
|
|
28
|
+
if (chartWidth < 4 || chartHeight < 2)
|
|
29
|
+
return;
|
|
30
|
+
const min = Math.min(...values);
|
|
31
|
+
const max = Math.max(...values);
|
|
32
|
+
const range = max - min || 1;
|
|
33
|
+
// Interpolate values to fill chart width
|
|
34
|
+
const interpolated = [];
|
|
35
|
+
for (let c = 0; c < chartWidth; c++) {
|
|
36
|
+
const t = (c / (chartWidth - 1)) * (values.length - 1);
|
|
37
|
+
const lo = Math.floor(t);
|
|
38
|
+
const hi = Math.min(lo + 1, values.length - 1);
|
|
39
|
+
const frac = t - lo;
|
|
40
|
+
interpolated.push(values[lo] * (1 - frac) + values[hi] * frac);
|
|
41
|
+
}
|
|
42
|
+
// Y-axis: show 3 labels (top, zero if in range, bottom)
|
|
43
|
+
const chartCol = col + yLabelWidth + 1;
|
|
44
|
+
const yLabels = [
|
|
45
|
+
{ row: 0, value: max },
|
|
46
|
+
{ row: chartHeight - 1, value: min },
|
|
47
|
+
];
|
|
48
|
+
// Add zero line if range crosses zero
|
|
49
|
+
let zeroChartRow = -1;
|
|
50
|
+
if (min < 0 && max > 0) {
|
|
51
|
+
zeroChartRow = Math.round((max / range) * (chartHeight - 1));
|
|
52
|
+
if (zeroChartRow > 0 && zeroChartRow < chartHeight - 1) {
|
|
53
|
+
yLabels.push({ row: zeroChartRow, value: 0 });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Draw Y-axis
|
|
57
|
+
for (let r = 0; r < chartHeight; r++) {
|
|
58
|
+
screen.write(row + r, col + yLabelWidth, '│', border_js_1.CLR.borderDim);
|
|
59
|
+
}
|
|
60
|
+
for (const yl of yLabels) {
|
|
61
|
+
const fmt = Math.abs(yl.value) >= 100
|
|
62
|
+
? `$${(yl.value >= 0 ? '+' : '') + yl.value.toFixed(0)}`
|
|
63
|
+
: `$${(yl.value >= 0 ? '+' : '') + yl.value.toFixed(1)}`;
|
|
64
|
+
screen.write(row + yl.row, col, fmt.padStart(yLabelWidth), border_js_1.CLR.dim);
|
|
65
|
+
}
|
|
66
|
+
// Zero line (dashed)
|
|
67
|
+
if (zeroChartRow >= 0 && zeroChartRow < chartHeight) {
|
|
68
|
+
for (let c = 0; c < chartWidth; c++) {
|
|
69
|
+
screen.write(row + zeroChartRow, chartCol + c, '╌', border_js_1.CLR.veryDim);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Draw area chart using block characters
|
|
73
|
+
// Each column: compute how high the bar should go
|
|
74
|
+
const blocks = ' ▁▂▃▄▅▆▇█';
|
|
75
|
+
for (let c = 0; c < chartWidth; c++) {
|
|
76
|
+
const val = interpolated[c];
|
|
77
|
+
// Normalize to 0..1 (0=min, 1=max)
|
|
78
|
+
const norm = (val - min) / range;
|
|
79
|
+
// Height in sub-rows (chartHeight * 8 granularity levels)
|
|
80
|
+
const barHeight = norm * chartHeight * 8;
|
|
81
|
+
const color = val >= 0 ? border_js_1.CLR.green : border_js_1.CLR.red;
|
|
82
|
+
// Fill from bottom up
|
|
83
|
+
for (let r = chartHeight - 1; r >= 0; r--) {
|
|
84
|
+
const rowFromBottom = chartHeight - 1 - r;
|
|
85
|
+
const fillLevel = barHeight - rowFromBottom * 8;
|
|
86
|
+
if (fillLevel >= 8) {
|
|
87
|
+
// Full block
|
|
88
|
+
screen.write(row + r, chartCol + c, '█', color);
|
|
89
|
+
}
|
|
90
|
+
else if (fillLevel > 0) {
|
|
91
|
+
// Partial block
|
|
92
|
+
const idx = Math.round(Math.max(1, Math.min(fillLevel, 8)));
|
|
93
|
+
screen.write(row + r, chartCol + c, blocks[idx], color);
|
|
94
|
+
}
|
|
95
|
+
// else: empty (space), already default
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// X-axis
|
|
99
|
+
const xRow = row + chartHeight;
|
|
100
|
+
screen.write(xRow, col + yLabelWidth, '└', border_js_1.CLR.borderDim);
|
|
101
|
+
for (let c = 0; c < chartWidth; c++) {
|
|
102
|
+
screen.write(xRow, chartCol + c, '─', border_js_1.CLR.borderDim);
|
|
103
|
+
}
|
|
104
|
+
// X-axis labels
|
|
105
|
+
if (labels && labels.length > 0) {
|
|
106
|
+
const labelRow = row + chartHeight + 1;
|
|
107
|
+
const numLabels = Math.min(labels.length, 6);
|
|
108
|
+
for (let i = 0; i < numLabels; i++) {
|
|
109
|
+
const srcIdx = Math.round(i * (labels.length - 1) / Math.max(numLabels - 1, 1));
|
|
110
|
+
const xPos = chartCol + Math.round(srcIdx * (chartWidth - 1) / Math.max(labels.length - 1, 1));
|
|
111
|
+
const label = labels[srcIdx] || '';
|
|
112
|
+
if (xPos >= chartCol && xPos + label.length < col + width) {
|
|
113
|
+
screen.write(labelRow, xPos, label.slice(0, 5), border_js_1.CLR.dim);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI Dashboard Engine — main loop
|
|
3
|
+
*
|
|
4
|
+
* Manages the render loop, data loading, keypress handling, and mode transitions.
|
|
5
|
+
* This is NOT the commander entry point — see commands/dashboard.ts for that.
|
|
6
|
+
*/
|
|
7
|
+
import { type DashboardState } from './state.js';
|
|
8
|
+
export declare function loadAllData(state: DashboardState): Promise<void>;
|
|
9
|
+
export declare function startDashboard(): Promise<void>;
|