@zhive/cli 0.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 +118 -0
- package/dist/agent/analysis.js +160 -0
- package/dist/agent/app.js +122 -0
- package/dist/agent/chat-prompt.js +65 -0
- package/dist/agent/commands/registry.js +12 -0
- package/dist/agent/components/AsciiTicker.js +81 -0
- package/dist/agent/components/CommandInput.js +65 -0
- package/dist/agent/components/HoneycombBoot.js +291 -0
- package/dist/agent/components/Spinner.js +37 -0
- package/dist/agent/config.js +75 -0
- package/dist/agent/edit-section.js +59 -0
- package/dist/agent/fetch-rules.js +21 -0
- package/dist/agent/helpers.js +22 -0
- package/dist/agent/hooks/useAgent.js +480 -0
- package/dist/agent/memory-prompt.js +47 -0
- package/dist/agent/model.js +92 -0
- package/dist/agent/objects.js +1 -0
- package/dist/agent/process-lifecycle.js +18 -0
- package/dist/agent/prompt.js +353 -0
- package/dist/agent/run-headless.js +189 -0
- package/dist/agent/skills/index.js +2 -0
- package/dist/agent/skills/skill-parser.js +149 -0
- package/dist/agent/skills/types.js +1 -0
- package/dist/agent/theme.js +41 -0
- package/dist/agent/tools/index.js +76 -0
- package/dist/agent/tools/market/client.js +41 -0
- package/dist/agent/tools/market/index.js +3 -0
- package/dist/agent/tools/market/tools.js +518 -0
- package/dist/agent/tools/mindshare/client.js +124 -0
- package/dist/agent/tools/mindshare/index.js +3 -0
- package/dist/agent/tools/mindshare/tools.js +563 -0
- package/dist/agent/tools/read-skill-tool.js +30 -0
- package/dist/agent/tools/ta/index.js +1 -0
- package/dist/agent/tools/ta/indicators.js +201 -0
- package/dist/agent/types.js +1 -0
- package/dist/agents.js +110 -0
- package/dist/ai-providers.js +66 -0
- package/dist/avatar.js +34 -0
- package/dist/backtest/default-backtest-data.js +200 -0
- package/dist/backtest/fetch.js +41 -0
- package/dist/backtest/import.js +106 -0
- package/dist/backtest/index.js +10 -0
- package/dist/backtest/results.js +113 -0
- package/dist/backtest/runner.js +134 -0
- package/dist/backtest/storage.js +11 -0
- package/dist/backtest/types.js +1 -0
- package/dist/commands/create/ai-generate.js +126 -0
- package/dist/commands/create/commands/index.js +10 -0
- package/dist/commands/create/generate.js +73 -0
- package/dist/commands/create/presets/data.js +225 -0
- package/dist/commands/create/presets/formatting.js +81 -0
- package/dist/commands/create/presets/index.js +3 -0
- package/dist/commands/create/presets/options.js +307 -0
- package/dist/commands/create/presets/types.js +1 -0
- package/dist/commands/create/presets.js +613 -0
- package/dist/commands/create/ui/CreateApp.js +172 -0
- package/dist/commands/create/ui/steps/ApiKeyStep.js +89 -0
- package/dist/commands/create/ui/steps/AvatarStep.js +16 -0
- package/dist/commands/create/ui/steps/DoneStep.js +14 -0
- package/dist/commands/create/ui/steps/IdentityStep.js +125 -0
- package/dist/commands/create/ui/steps/NameStep.js +148 -0
- package/dist/commands/create/ui/steps/ScaffoldStep.js +59 -0
- package/dist/commands/create/ui/steps/SoulStep.js +21 -0
- package/dist/commands/create/ui/steps/StrategyStep.js +20 -0
- package/dist/commands/create/ui/steps/StreamingGenerationStep.js +56 -0
- package/dist/commands/create/ui/validation.js +34 -0
- package/dist/commands/create/validate-api-key.js +27 -0
- package/dist/commands/install.js +50 -0
- package/dist/commands/list/commands/index.js +7 -0
- package/dist/commands/list/ui/ListApp.js +79 -0
- package/dist/commands/migrate-templates/commands/index.js +9 -0
- package/dist/commands/migrate-templates/migrate.js +87 -0
- package/dist/commands/migrate-templates/ui/MigrateApp.js +132 -0
- package/dist/commands/run/commands/index.js +17 -0
- package/dist/commands/run/run-headless.js +111 -0
- package/dist/commands/shared/theme.js +57 -0
- package/dist/commands/shared/welcome.js +304 -0
- package/dist/commands/start/commands/backtest.js +35 -0
- package/dist/commands/start/commands/index.js +62 -0
- package/dist/commands/start/commands/prediction.js +73 -0
- package/dist/commands/start/commands/skills.js +44 -0
- package/dist/commands/start/commands/skills.test.js +140 -0
- package/dist/commands/start/hooks/types.js +1 -0
- package/dist/commands/start/hooks/useAgent.js +177 -0
- package/dist/commands/start/hooks/useChat.js +266 -0
- package/dist/commands/start/hooks/usePollActivity.js +45 -0
- package/dist/commands/start/hooks/utils.js +152 -0
- package/dist/commands/start/services/backtest/default-backtest-data.js +200 -0
- package/dist/commands/start/services/backtest/fetch.js +42 -0
- package/dist/commands/start/services/backtest/import.js +109 -0
- package/dist/commands/start/services/backtest/index.js +10 -0
- package/dist/commands/start/services/backtest/results.js +113 -0
- package/dist/commands/start/services/backtest/runner.js +103 -0
- package/dist/commands/start/services/backtest/storage.js +11 -0
- package/dist/commands/start/services/backtest/types.js +1 -0
- package/dist/commands/start/services/command-registry.js +13 -0
- package/dist/commands/start/ui/AsciiTicker.js +81 -0
- package/dist/commands/start/ui/CommandInput.js +65 -0
- package/dist/commands/start/ui/HoneycombBoot.js +291 -0
- package/dist/commands/start/ui/PollText.js +23 -0
- package/dist/commands/start/ui/PredictionsPanel.js +88 -0
- package/dist/commands/start/ui/SelectAgentApp.js +93 -0
- package/dist/commands/start/ui/Spinner.js +29 -0
- package/dist/commands/start/ui/SpinnerContext.js +20 -0
- package/dist/commands/start/ui/app.js +36 -0
- package/dist/commands/start-all/AgentProcessManager.js +98 -0
- package/dist/commands/start-all/commands/index.js +24 -0
- package/dist/commands/start-all/ui/Dashboard.js +91 -0
- package/dist/components/AsciiTicker.js +81 -0
- package/dist/components/CharacterSummaryCard.js +33 -0
- package/dist/components/CodeBlock.js +11 -0
- package/dist/components/ColoredStats.js +18 -0
- package/dist/components/Header.js +10 -0
- package/dist/components/HoneycombLoader.js +190 -0
- package/dist/components/InputGuard.js +6 -0
- package/dist/components/MultiSelectPrompt.js +45 -0
- package/dist/components/SelectPrompt.js +20 -0
- package/dist/components/Spinner.js +16 -0
- package/dist/components/StepIndicator.js +31 -0
- package/dist/components/StreamingText.js +50 -0
- package/dist/components/TextPrompt.js +28 -0
- package/dist/components/stdout-spinner.js +48 -0
- package/dist/config.js +28 -0
- package/dist/create/CreateApp.js +153 -0
- package/dist/create/ai-generate.js +147 -0
- package/dist/create/generate.js +73 -0
- package/dist/create/steps/ApiKeyStep.js +97 -0
- package/dist/create/steps/AvatarStep.js +16 -0
- package/dist/create/steps/BioStep.js +14 -0
- package/dist/create/steps/DoneStep.js +14 -0
- package/dist/create/steps/IdentityStep.js +163 -0
- package/dist/create/steps/NameStep.js +71 -0
- package/dist/create/steps/ScaffoldStep.js +58 -0
- package/dist/create/steps/SoulStep.js +58 -0
- package/dist/create/steps/StrategyStep.js +58 -0
- package/dist/create/validate-api-key.js +47 -0
- package/dist/create/welcome.js +304 -0
- package/dist/index.js +60 -0
- package/dist/list/ListApp.js +79 -0
- package/dist/load-agent-env.js +30 -0
- package/dist/migrate-templates/MigrateApp.js +131 -0
- package/dist/migrate-templates/migrate.js +86 -0
- package/dist/presets.js +613 -0
- package/dist/shared/agent/agent-runtime.js +144 -0
- package/dist/shared/agent/analysis.js +171 -0
- package/dist/shared/agent/helpers.js +1 -0
- package/dist/shared/agent/prompts/chat-prompt.js +60 -0
- package/dist/shared/agent/prompts/megathread.js +202 -0
- package/dist/shared/agent/prompts/memory-prompt.js +47 -0
- package/dist/shared/agent/prompts/prompt.js +18 -0
- package/dist/shared/agent/skills/index.js +2 -0
- package/dist/shared/agent/skills/skill-parser.js +167 -0
- package/dist/shared/agent/skills/skill-parser.test.js +190 -0
- package/dist/shared/agent/skills/types.js +1 -0
- package/dist/shared/agent/tools/edit-section.js +60 -0
- package/dist/shared/agent/tools/execute-skill-tool.js +134 -0
- package/dist/shared/agent/tools/fetch-rules.js +22 -0
- package/dist/shared/agent/tools/formatting.js +48 -0
- package/dist/shared/agent/tools/index.js +87 -0
- package/dist/shared/agent/tools/market/client.js +41 -0
- package/dist/shared/agent/tools/market/index.js +3 -0
- package/dist/shared/agent/tools/market/tools.js +497 -0
- package/dist/shared/agent/tools/mindshare/client.js +124 -0
- package/dist/shared/agent/tools/mindshare/index.js +3 -0
- package/dist/shared/agent/tools/mindshare/tools.js +167 -0
- package/dist/shared/agent/tools/read-skill-tool.js +30 -0
- package/dist/shared/agent/tools/ta/index.js +1 -0
- package/dist/shared/agent/tools/ta/indicators.js +201 -0
- package/dist/shared/agent/types.js +1 -0
- package/dist/shared/agent/utils.js +43 -0
- package/dist/shared/config/agent.js +177 -0
- package/dist/shared/config/ai-providers.js +156 -0
- package/dist/shared/config/config.js +22 -0
- package/dist/shared/config/constant.js +8 -0
- package/dist/shared/config/env-loader.js +30 -0
- package/dist/shared/types.js +1 -0
- package/dist/start/AgentProcessManager.js +98 -0
- package/dist/start/Dashboard.js +92 -0
- package/dist/start/SelectAgentApp.js +81 -0
- package/dist/start/StartApp.js +189 -0
- package/dist/start/patch-headless.js +101 -0
- package/dist/start/patch-managed-mode.js +142 -0
- package/dist/start/start-command.js +24 -0
- package/dist/theme.js +54 -0
- package/package.json +68 -0
- package/templates/components/HoneycombBoot.tsx +343 -0
- package/templates/fetch-rules.ts +23 -0
- package/templates/skills/mindshare/SKILL.md +197 -0
- package/templates/skills/ta/SKILL.md +179 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const colors = {
|
|
3
|
+
honey: '#F5A623',
|
|
4
|
+
honeyDark: '#D4891A',
|
|
5
|
+
honeyBright: '#FFD700',
|
|
6
|
+
white: '#FFFFFF',
|
|
7
|
+
gray: '#A6A6A6',
|
|
8
|
+
grayDim: '#555555',
|
|
9
|
+
green: '#27C587',
|
|
10
|
+
red: '#E14B4B',
|
|
11
|
+
wax: '#C45C5C',
|
|
12
|
+
cyan: '#22D3EE',
|
|
13
|
+
hot: '#FB923C',
|
|
14
|
+
controversial: '#C084FC',
|
|
15
|
+
};
|
|
16
|
+
export const symbols = {
|
|
17
|
+
hive: '\u2B21', // ⬡
|
|
18
|
+
diamond: '\u25C6', // ◆
|
|
19
|
+
diamondOpen: '\u25C7', // ◇
|
|
20
|
+
dot: '\u25CF', // ●
|
|
21
|
+
spinner: ['\u25D0', '\u25D3', '\u25D1', '\u25D2'], // ◐ ◓ ◑ ◒
|
|
22
|
+
check: '\u2713', // ✓
|
|
23
|
+
arrow: '\u203A', // ›
|
|
24
|
+
circle: '\u25CB', // ○
|
|
25
|
+
cross: '\u2717', // ✗
|
|
26
|
+
};
|
|
27
|
+
export const border = {
|
|
28
|
+
horizontal: '\u2500', // ─
|
|
29
|
+
vertical: '\u2502', // │
|
|
30
|
+
topLeft: '\u250C', // ┌
|
|
31
|
+
topRight: '\u2510', // ┐
|
|
32
|
+
bottomLeft: '\u2514', // └
|
|
33
|
+
bottomRight: '\u2518', // ┘
|
|
34
|
+
teeLeft: '\u251C', // ├
|
|
35
|
+
teeRight: '\u2524', // ┤
|
|
36
|
+
};
|
|
37
|
+
export const animation = {
|
|
38
|
+
DATA_CHARS: '01▪▫░▒',
|
|
39
|
+
HEX_CHARS: '⬡⬢',
|
|
40
|
+
TICK_MS: 120,
|
|
41
|
+
HEX_W: 8,
|
|
42
|
+
HEX_H: 4,
|
|
43
|
+
};
|
|
44
|
+
export const styled = {
|
|
45
|
+
honey: (text) => chalk.hex(colors.honey)(text),
|
|
46
|
+
honeyBold: (text) => chalk.hex(colors.honey).bold(text),
|
|
47
|
+
white: (text) => chalk.white(text),
|
|
48
|
+
whiteBold: (text) => chalk.bold.white(text),
|
|
49
|
+
gray: (text) => chalk.gray(text),
|
|
50
|
+
dim: (text) => chalk.hex(colors.grayDim)(text),
|
|
51
|
+
green: (text) => chalk.hex(colors.green)(text),
|
|
52
|
+
red: (text) => chalk.hex(colors.red)(text),
|
|
53
|
+
wax: (text) => chalk.hex(colors.wax)(text),
|
|
54
|
+
cyan: (text) => chalk.hex(colors.cyan)(text),
|
|
55
|
+
hot: (text) => chalk.hex(colors.hot)(text),
|
|
56
|
+
controversial: (text) => chalk.hex(colors.controversial)(text),
|
|
57
|
+
};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
const HEX_W = 8;
|
|
3
|
+
const HEX_H = 4;
|
|
4
|
+
const DATA_CHARS = '01▪▫░▒';
|
|
5
|
+
const TICK_MS = 80;
|
|
6
|
+
const DURATION_MS = 3200;
|
|
7
|
+
const NUM_BEES = 4;
|
|
8
|
+
const NUM_STREAMS = 5;
|
|
9
|
+
const HONEY = '#F5A623';
|
|
10
|
+
const GREEN = '#27C587';
|
|
11
|
+
const DIM = '#555555';
|
|
12
|
+
const WHITE = '#FFFFFF';
|
|
13
|
+
const RED = '#E14B4B';
|
|
14
|
+
const SCRAMBLE_CHARS = '⬡⬢◆◇░▒!@#$%01';
|
|
15
|
+
const BOOT_MESSAGES = [
|
|
16
|
+
{ prefix: '⬡', text: 'Initializing creation studio...', frame: 18, color: HONEY },
|
|
17
|
+
{ prefix: '◆', text: 'Loading agent templates...', frame: 24, color: HONEY },
|
|
18
|
+
{ prefix: '◇', text: 'Connecting to hive network...', frame: 30, color: HONEY },
|
|
19
|
+
{ prefix: '✓', text: 'Ready', frame: 36, color: GREEN },
|
|
20
|
+
];
|
|
21
|
+
function isHexEdge(r, c) {
|
|
22
|
+
const rowInHex = ((r % HEX_H) + HEX_H) % HEX_H;
|
|
23
|
+
const isOddHex = Math.floor(r / HEX_H) % 2 === 1;
|
|
24
|
+
const colOffset = isOddHex ? HEX_W / 2 : 0;
|
|
25
|
+
const colInHex = (((c - colOffset) % HEX_W) + HEX_W) % HEX_W;
|
|
26
|
+
if (rowInHex === 0 || rowInHex === HEX_H - 1) {
|
|
27
|
+
return colInHex >= 2 && colInHex <= 5;
|
|
28
|
+
}
|
|
29
|
+
if (rowInHex === 1 || rowInHex === 2) {
|
|
30
|
+
return colInHex === 1 || colInHex === 6;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
export function showWelcome() {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const cols = process.stdout.columns || 60;
|
|
37
|
+
const gridRows = process.stdout.rows || 24;
|
|
38
|
+
let frame = 0;
|
|
39
|
+
// Init bees
|
|
40
|
+
const bees = [];
|
|
41
|
+
for (let i = 0; i < NUM_BEES; i++) {
|
|
42
|
+
bees.push({
|
|
43
|
+
r: Math.floor(Math.random() * gridRows),
|
|
44
|
+
c: Math.floor(Math.random() * cols),
|
|
45
|
+
vr: Math.random() > 0.5 ? 1 : -1,
|
|
46
|
+
vc: Math.random() > 0.5 ? 1 : -1,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// Init stream columns
|
|
50
|
+
const streamCols = [];
|
|
51
|
+
const spacing = Math.floor(cols / (NUM_STREAMS + 1));
|
|
52
|
+
for (let i = 1; i <= NUM_STREAMS; i++) {
|
|
53
|
+
streamCols.push(spacing * i);
|
|
54
|
+
}
|
|
55
|
+
let pulses = [];
|
|
56
|
+
// Title positioning
|
|
57
|
+
const title = '\u2B21 HIVE';
|
|
58
|
+
const subtitle = 'Agent Creation Studio';
|
|
59
|
+
const titleRow = Math.floor(gridRows / 2) - 1;
|
|
60
|
+
const subtitleRow = titleRow + 1;
|
|
61
|
+
const titleCol = Math.floor((cols - title.length) / 2);
|
|
62
|
+
const subtitleCol = Math.floor((cols - subtitle.length) / 2);
|
|
63
|
+
// Boot message row positions
|
|
64
|
+
const msgStartRow = subtitleRow + 2;
|
|
65
|
+
// Quiet zone around title + boot messages: no animation renders here
|
|
66
|
+
const PADDING_H = 3;
|
|
67
|
+
const PADDING_V = 1;
|
|
68
|
+
const longestMsg = BOOT_MESSAGES.reduce((max, m) => Math.max(max, m.prefix.length + 1 + m.text.length), 0);
|
|
69
|
+
const msgLeftEdge = Math.floor((cols - longestMsg) / 2);
|
|
70
|
+
const msgRightEdge = msgLeftEdge + longestMsg;
|
|
71
|
+
const quietLeft = Math.min(titleCol, subtitleCol, msgLeftEdge) - PADDING_H;
|
|
72
|
+
const quietRight = Math.max(titleCol + title.length, subtitleCol + subtitle.length, msgRightEdge) + PADDING_H;
|
|
73
|
+
const quietTop = titleRow - PADDING_V;
|
|
74
|
+
const quietBottom = msgStartRow + BOOT_MESSAGES.length + PADDING_V;
|
|
75
|
+
// Hide cursor
|
|
76
|
+
process.stdout.write('\x1b[?25l');
|
|
77
|
+
// Clear screen
|
|
78
|
+
process.stdout.write('\x1b[2J');
|
|
79
|
+
function renderFrame() {
|
|
80
|
+
// Move cursor to top-left
|
|
81
|
+
process.stdout.write('\x1b[H');
|
|
82
|
+
// Advance bees every other frame
|
|
83
|
+
if (frame > 0 && frame % 2 === 0) {
|
|
84
|
+
for (const bee of bees) {
|
|
85
|
+
bee.r += bee.vr;
|
|
86
|
+
bee.c += bee.vc;
|
|
87
|
+
if (bee.r <= 0 || bee.r >= gridRows - 1) {
|
|
88
|
+
bee.vr *= -1;
|
|
89
|
+
bee.r = Math.max(0, Math.min(gridRows - 1, bee.r));
|
|
90
|
+
}
|
|
91
|
+
if (bee.c <= 0 || bee.c >= cols - 1) {
|
|
92
|
+
bee.vc *= -1;
|
|
93
|
+
bee.c = Math.max(0, Math.min(cols - 1, bee.c));
|
|
94
|
+
}
|
|
95
|
+
if (Math.random() > 0.3) {
|
|
96
|
+
bee.vc = Math.random() > 0.5 ? 1 : -1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Spawn pulses
|
|
101
|
+
if (frame % 4 === 0) {
|
|
102
|
+
for (let i = 0; i < 3; i++) {
|
|
103
|
+
const pr = Math.floor(Math.random() * gridRows);
|
|
104
|
+
const pc = Math.floor(Math.random() * cols);
|
|
105
|
+
if (isHexEdge(pr, pc)) {
|
|
106
|
+
const pulseColors = [GREEN, RED, HONEY];
|
|
107
|
+
const color = pulseColors[Math.floor(Math.random() * pulseColors.length)];
|
|
108
|
+
pulses.push({ r: pr, c: pc, ttl: 8, color });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
pulses = pulses.filter((p) => p.ttl > 0).map((p) => ({ ...p, ttl: p.ttl - 1 }));
|
|
112
|
+
}
|
|
113
|
+
// Build grid: char + color pairs
|
|
114
|
+
const charGrid = [];
|
|
115
|
+
const colorGrid = [];
|
|
116
|
+
for (let r = 0; r < gridRows; r++) {
|
|
117
|
+
const chars = [];
|
|
118
|
+
const clrs = [];
|
|
119
|
+
for (let c = 0; c < cols; c++) {
|
|
120
|
+
// Skip animation in quiet zone around title
|
|
121
|
+
if (r >= quietTop && r <= quietBottom && c >= quietLeft && c < quietRight) {
|
|
122
|
+
chars.push(' ');
|
|
123
|
+
clrs.push(DIM);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const hexEdge = isHexEdge(r, c);
|
|
127
|
+
// Scanning wave
|
|
128
|
+
const scanRow = frame % (gridRows + 6);
|
|
129
|
+
const dist = Math.abs(r - scanRow);
|
|
130
|
+
if (hexEdge && dist === 0) {
|
|
131
|
+
chars.push('⬢');
|
|
132
|
+
clrs.push(HONEY);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (hexEdge && dist <= 1) {
|
|
136
|
+
chars.push('⬡');
|
|
137
|
+
clrs.push(HONEY);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Data streams
|
|
141
|
+
let isStream = false;
|
|
142
|
+
for (const sc of streamCols) {
|
|
143
|
+
if (c === sc) {
|
|
144
|
+
const streamOffset = (frame * 2 + sc) % (gridRows * 3);
|
|
145
|
+
const streamDist = (((r - streamOffset) % gridRows) + gridRows) % gridRows;
|
|
146
|
+
if (streamDist < 6) {
|
|
147
|
+
const charIdx = (frame + r) % DATA_CHARS.length;
|
|
148
|
+
const streamChar = DATA_CHARS[charIdx];
|
|
149
|
+
chars.push(streamChar);
|
|
150
|
+
if (streamDist === 0) {
|
|
151
|
+
clrs.push(WHITE);
|
|
152
|
+
}
|
|
153
|
+
else if (streamDist < 3) {
|
|
154
|
+
clrs.push(GREEN);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
clrs.push(DIM);
|
|
158
|
+
}
|
|
159
|
+
isStream = true;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (isStream)
|
|
165
|
+
continue;
|
|
166
|
+
// Default
|
|
167
|
+
if (hexEdge) {
|
|
168
|
+
chars.push('·');
|
|
169
|
+
clrs.push(DIM);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
chars.push(' ');
|
|
173
|
+
clrs.push(DIM);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
charGrid.push(chars);
|
|
177
|
+
colorGrid.push(clrs);
|
|
178
|
+
}
|
|
179
|
+
// Overlay pulses (skip quiet zone)
|
|
180
|
+
for (const pulse of pulses) {
|
|
181
|
+
if (pulse.r >= 0 && pulse.r < gridRows && pulse.c >= 0 && pulse.c < cols) {
|
|
182
|
+
const inQuietZone = pulse.r >= quietTop &&
|
|
183
|
+
pulse.r <= quietBottom &&
|
|
184
|
+
pulse.c >= quietLeft &&
|
|
185
|
+
pulse.c < quietRight;
|
|
186
|
+
if (inQuietZone)
|
|
187
|
+
continue;
|
|
188
|
+
const brightness = pulse.ttl / 8;
|
|
189
|
+
const cell = charGrid[pulse.r][pulse.c];
|
|
190
|
+
if (cell === '·' || cell === ' ') {
|
|
191
|
+
charGrid[pulse.r][pulse.c] = brightness > 0.5 ? '⬡' : '·';
|
|
192
|
+
colorGrid[pulse.r][pulse.c] = pulse.color;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Overlay bees (skip quiet zone)
|
|
197
|
+
for (const bee of bees) {
|
|
198
|
+
const br = Math.max(0, Math.min(gridRows - 1, Math.round(bee.r)));
|
|
199
|
+
const bc = Math.max(0, Math.min(cols - 1, Math.round(bee.c)));
|
|
200
|
+
const inQuietZone = br >= quietTop && br <= quietBottom && bc >= quietLeft && bc < quietRight;
|
|
201
|
+
if (!inQuietZone) {
|
|
202
|
+
charGrid[br][bc] = '◆';
|
|
203
|
+
colorGrid[br][bc] = HONEY;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Overlay title with scramble→reveal effect
|
|
207
|
+
const TITLE_START_FRAME = 6;
|
|
208
|
+
const TITLE_REVEAL_FRAMES = 8;
|
|
209
|
+
if (frame >= TITLE_START_FRAME && titleRow >= 0 && titleRow < gridRows) {
|
|
210
|
+
const scrambleProgress = Math.min(1, (frame - TITLE_START_FRAME) / TITLE_REVEAL_FRAMES);
|
|
211
|
+
for (let i = 0; i < title.length; i++) {
|
|
212
|
+
const tc = titleCol + i;
|
|
213
|
+
if (tc < 0 || tc >= cols)
|
|
214
|
+
continue;
|
|
215
|
+
const charThreshold = i / title.length;
|
|
216
|
+
if (charThreshold <= scrambleProgress) {
|
|
217
|
+
charGrid[titleRow][tc] = title[i];
|
|
218
|
+
colorGrid[titleRow][tc] = HONEY;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const scrambleIdx = Math.floor(Math.random() * SCRAMBLE_CHARS.length);
|
|
222
|
+
charGrid[titleRow][tc] = SCRAMBLE_CHARS[scrambleIdx];
|
|
223
|
+
colorGrid[titleRow][tc] = DIM;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Overlay subtitle with scramble→reveal (starts a few frames after title)
|
|
228
|
+
const SUB_START_FRAME = 10;
|
|
229
|
+
const SUB_REVEAL_FRAMES = 8;
|
|
230
|
+
if (frame >= SUB_START_FRAME && subtitleRow >= 0 && subtitleRow < gridRows) {
|
|
231
|
+
const scrambleProgress = Math.min(1, (frame - SUB_START_FRAME) / SUB_REVEAL_FRAMES);
|
|
232
|
+
for (let i = 0; i < subtitle.length; i++) {
|
|
233
|
+
const sc = subtitleCol + i;
|
|
234
|
+
if (sc < 0 || sc >= cols)
|
|
235
|
+
continue;
|
|
236
|
+
const charThreshold = i / subtitle.length;
|
|
237
|
+
if (charThreshold <= scrambleProgress) {
|
|
238
|
+
charGrid[subtitleRow][sc] = subtitle[i];
|
|
239
|
+
colorGrid[subtitleRow][sc] = DIM;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
const scrambleIdx = Math.floor(Math.random() * SCRAMBLE_CHARS.length);
|
|
243
|
+
charGrid[subtitleRow][sc] = SCRAMBLE_CHARS[scrambleIdx];
|
|
244
|
+
colorGrid[subtitleRow][sc] = DIM;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Overlay typewriter boot messages
|
|
249
|
+
for (let idx = 0; idx < BOOT_MESSAGES.length; idx++) {
|
|
250
|
+
const msg = BOOT_MESSAGES[idx];
|
|
251
|
+
if (frame < msg.frame)
|
|
252
|
+
continue;
|
|
253
|
+
const r = msgStartRow + idx;
|
|
254
|
+
if (r < 0 || r >= gridRows)
|
|
255
|
+
continue;
|
|
256
|
+
const fullText = `${msg.prefix} ${msg.text}`;
|
|
257
|
+
const msgCol = Math.floor((cols - fullText.length) / 2);
|
|
258
|
+
const visibleChars = Math.min(fullText.length, (frame - msg.frame) * 3);
|
|
259
|
+
for (let i = 0; i < visibleChars; i++) {
|
|
260
|
+
const c = msgCol + i;
|
|
261
|
+
if (c < 0 || c >= cols)
|
|
262
|
+
continue;
|
|
263
|
+
charGrid[r][c] = fullText[i];
|
|
264
|
+
colorGrid[r][c] = msg.color;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Render to stdout
|
|
268
|
+
let output = '';
|
|
269
|
+
for (let r = 0; r < gridRows; r++) {
|
|
270
|
+
let line = '';
|
|
271
|
+
let runColor = colorGrid[r][0];
|
|
272
|
+
let runChars = '';
|
|
273
|
+
for (let c = 0; c < cols; c++) {
|
|
274
|
+
const curColor = colorGrid[r][c];
|
|
275
|
+
const curChar = charGrid[r][c];
|
|
276
|
+
if (curColor === runColor) {
|
|
277
|
+
runChars += curChar;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
line += chalk.hex(runColor)(runChars);
|
|
281
|
+
runColor = curColor;
|
|
282
|
+
runChars = curChar;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (runChars.length > 0) {
|
|
286
|
+
line += chalk.hex(runColor)(runChars);
|
|
287
|
+
}
|
|
288
|
+
output += line;
|
|
289
|
+
if (r < gridRows - 1) {
|
|
290
|
+
output += '\n';
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
process.stdout.write(output);
|
|
294
|
+
frame++;
|
|
295
|
+
}
|
|
296
|
+
const timer = setInterval(renderFrame, TICK_MS);
|
|
297
|
+
setTimeout(() => {
|
|
298
|
+
clearInterval(timer);
|
|
299
|
+
// Clear screen, show cursor, move to top
|
|
300
|
+
process.stdout.write('\x1b[2J\x1b[H\x1b[?25h');
|
|
301
|
+
resolve();
|
|
302
|
+
}, DURATION_MS);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { HIVE_API_URL } from '../../../shared/config/constant.js';
|
|
2
|
+
import { fetchBacktestThreads } from '../services/backtest/fetch.js';
|
|
3
|
+
import { buildTextReport } from '../services/backtest/results.js';
|
|
4
|
+
import { runBacktest } from '../services/backtest/runner.js';
|
|
5
|
+
import { loadDefaultBacktest } from '../services/backtest/storage.js';
|
|
6
|
+
export const backtestSlashCommand = async (args, config, callbacks) => {
|
|
7
|
+
const commandArg = args.at(0);
|
|
8
|
+
const numThreads = commandArg ? parseInt(commandArg, 10) : null;
|
|
9
|
+
let data;
|
|
10
|
+
if (numThreads !== null && !isNaN(numThreads) && numThreads > 0) {
|
|
11
|
+
callbacks.onFetchStart?.(numThreads);
|
|
12
|
+
const fetchResult = await fetchBacktestThreads(numThreads, HIVE_API_URL);
|
|
13
|
+
if (fetchResult.success) {
|
|
14
|
+
data = fetchResult.data;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
callbacks.onFetchError?.(fetchResult.error);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// Use default dataset
|
|
21
|
+
if (!data) {
|
|
22
|
+
data = loadDefaultBacktest();
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const result = await runBacktest(data, config, {
|
|
26
|
+
onThreadStart: callbacks.onThreadStart,
|
|
27
|
+
onThreadComplete: callbacks.onThreadComplete,
|
|
28
|
+
});
|
|
29
|
+
const report = buildTextReport(result);
|
|
30
|
+
callbacks.onBacktestSuccess?.(report);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
callbacks.onBacktestError?.(err);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { render } from 'ink';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { App } from '../ui/app.js';
|
|
4
|
+
import { SelectAgentApp } from '../ui/SelectAgentApp.js';
|
|
5
|
+
import { showHoneycombBoot } from '../ui/HoneycombBoot.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { symbols } from '../../shared/theme.js';
|
|
8
|
+
import { loadAgentEnv } from '../../../shared/config/env-loader.js';
|
|
9
|
+
export const startCommand = async () => {
|
|
10
|
+
// Detect if cwd is an agent directory (has SOUL.md).
|
|
11
|
+
// When called via agent's "npm start", cwd is the agent dir.
|
|
12
|
+
const { access } = await import('fs/promises');
|
|
13
|
+
const { join } = await import('path');
|
|
14
|
+
const isAgentDir = await access(join(process.cwd(), 'SOUL.md'))
|
|
15
|
+
.then(() => true)
|
|
16
|
+
.catch(() => false);
|
|
17
|
+
if (isAgentDir) {
|
|
18
|
+
// Direct agent run — cwd is already the agent directory.
|
|
19
|
+
await loadAgentEnv();
|
|
20
|
+
setupProcessLifecycle();
|
|
21
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
22
|
+
await waitUntilExit();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Interactive agent selection
|
|
26
|
+
let selectedAgent = null;
|
|
27
|
+
const { waitUntilExit: waitForSelect } = render(React.createElement(SelectAgentApp, {
|
|
28
|
+
onSelect: (agent) => {
|
|
29
|
+
selectedAgent = agent;
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
32
|
+
await waitForSelect();
|
|
33
|
+
if (selectedAgent) {
|
|
34
|
+
const picked = selectedAgent;
|
|
35
|
+
await showHoneycombBoot(picked.name);
|
|
36
|
+
// Clear screen + scrollback so boot animation and agent picker
|
|
37
|
+
// don't appear when scrolling up in the agent TUI.
|
|
38
|
+
process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
|
|
39
|
+
process.chdir(picked.dir);
|
|
40
|
+
await loadAgentEnv();
|
|
41
|
+
setupProcessLifecycle();
|
|
42
|
+
const { waitUntilExit } = render(React.createElement(App));
|
|
43
|
+
await waitUntilExit();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const exitImmediately = (exitCode = 0) => {
|
|
48
|
+
process.exit(exitCode);
|
|
49
|
+
};
|
|
50
|
+
function setupProcessLifecycle() {
|
|
51
|
+
// Unhandled rejection handler
|
|
52
|
+
process.on('unhandledRejection', (reason) => {
|
|
53
|
+
const raw = reason instanceof Error ? reason.message : String(reason);
|
|
54
|
+
const message = raw.length > 200 ? raw.slice(0, 200) + '\u2026' : raw;
|
|
55
|
+
console.error(chalk.red(` ${symbols.cross} Unhandled: ${message}`));
|
|
56
|
+
});
|
|
57
|
+
// No alternate screen buffer — normal buffer allows terminal scrollback
|
|
58
|
+
// so users can scroll up to see historical poll activity.
|
|
59
|
+
// <Static> items from Ink flow into the scrollback naturally.
|
|
60
|
+
process.on('SIGINT', () => exitImmediately(0));
|
|
61
|
+
process.on('SIGTERM', () => exitImmediately(0));
|
|
62
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { credentialsPath, loadCredentials } from '@zhive/sdk';
|
|
2
|
+
import { HIVE_API_URL } from '../../../shared/config/constant.js';
|
|
3
|
+
import { extractErrorMessage } from '../../../shared/agent/utils.js';
|
|
4
|
+
import { styled } from '../../shared/theme.js';
|
|
5
|
+
export async function fetchMyPredictions(apiKey, limit = 10) {
|
|
6
|
+
try {
|
|
7
|
+
const url = `${HIVE_API_URL}/megathread-comment/me?limit=${limit}&onlyResolved=true`;
|
|
8
|
+
const response = await fetch(url, {
|
|
9
|
+
headers: { 'x-api-key': apiKey },
|
|
10
|
+
});
|
|
11
|
+
if (!response.ok) {
|
|
12
|
+
const errorText = await response.text();
|
|
13
|
+
return { success: false, error: `HTTP ${response.status}: ${errorText}` };
|
|
14
|
+
}
|
|
15
|
+
const result = (await response.json());
|
|
16
|
+
return { success: true, data: result.data };
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const message = extractErrorMessage(error);
|
|
20
|
+
return { success: false, error: message };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function formatPredictions(predictions) {
|
|
24
|
+
if (predictions.length === 0) {
|
|
25
|
+
return 'No resolved predictions yet. Make some predictions and wait for them to resolve!';
|
|
26
|
+
}
|
|
27
|
+
const rows = predictions.map((pred) => {
|
|
28
|
+
const sign = pred.conviction >= 0 ? '+' : '';
|
|
29
|
+
const conviction = `${sign}${pred.conviction.toFixed(1)}%`;
|
|
30
|
+
const outcome = getOutcomeStr(pred);
|
|
31
|
+
const date = new Date(pred.created_at).toLocaleDateString();
|
|
32
|
+
const roundStart = pred.round_id.split('@Z')[0];
|
|
33
|
+
const durationMs = new Date(pred.resolved_at).getTime() - new Date(roundStart).getTime();
|
|
34
|
+
const duration = { 3600000: '1h', 14400000: '4h', 86400000: '24h' }[durationMs] || '??';
|
|
35
|
+
return { name: pred.project_id, duration, conviction, outcome, date };
|
|
36
|
+
});
|
|
37
|
+
const maxName = Math.max(...rows.map((r) => r.name.length));
|
|
38
|
+
const maxOutcome = Math.max(...rows.map((r) => r.outcome.length));
|
|
39
|
+
const lines = [styled.honeyBold('Your Recent Predictions:'), ''];
|
|
40
|
+
for (const r of rows) {
|
|
41
|
+
const name = r.name.padEnd(maxName);
|
|
42
|
+
const conv = r.conviction.padStart(6);
|
|
43
|
+
const paddedOutcome = r.outcome.padEnd(maxOutcome);
|
|
44
|
+
const tag = r.outcome.includes('WIN') ? styled.green(paddedOutcome) : styled.red(paddedOutcome);
|
|
45
|
+
lines.push(` ${name} ${r.duration.padStart(3)} ${conv} ${tag} ${r.date}`);
|
|
46
|
+
}
|
|
47
|
+
return lines.join('\n');
|
|
48
|
+
}
|
|
49
|
+
function getOutcomeStr(pred) {
|
|
50
|
+
if (pred.honey > 0) {
|
|
51
|
+
return `[WIN] +${pred.honey.toFixed(2)} Honey`;
|
|
52
|
+
}
|
|
53
|
+
if (pred.wax > 0) {
|
|
54
|
+
return `[WIN] +${pred.wax.toFixed(2)} Wax`;
|
|
55
|
+
}
|
|
56
|
+
return '[LOSS]';
|
|
57
|
+
}
|
|
58
|
+
export async function predictionSlashCommand(agentName, callbacks) {
|
|
59
|
+
const filePath = credentialsPath(agentName);
|
|
60
|
+
const credentials = await loadCredentials(filePath);
|
|
61
|
+
if (!credentials?.apiKey) {
|
|
62
|
+
callbacks.onError?.('Agent not registered yet. Wait for agent to start.');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
callbacks.onFetchStart?.();
|
|
66
|
+
const result = await fetchMyPredictions(credentials.apiKey, 10);
|
|
67
|
+
if (!result.success) {
|
|
68
|
+
callbacks.onError?.(result.error);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const formatted = formatPredictions(result.data);
|
|
72
|
+
callbacks.onSuccess?.(formatted);
|
|
73
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import { getHiveDir } from '../../../shared/config/constant.js';
|
|
3
|
+
import { discoverSkills } from '../../../shared/agent/skills/skill-parser.js';
|
|
4
|
+
import { styled } from '../../shared/theme.js';
|
|
5
|
+
import { extractErrorMessage } from '../../../shared/agent/utils.js';
|
|
6
|
+
export async function fetchSkills(agentName) {
|
|
7
|
+
try {
|
|
8
|
+
const hiveDir = getHiveDir();
|
|
9
|
+
const skillsDir = path.join(hiveDir, 'agents', agentName, 'skills');
|
|
10
|
+
const skills = await discoverSkills(skillsDir);
|
|
11
|
+
return { success: true, data: skills };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const message = extractErrorMessage(error);
|
|
15
|
+
return { success: false, error: message };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function formatSkills(skills) {
|
|
19
|
+
if (skills.length === 0) {
|
|
20
|
+
return 'No skills loaded. Add skills to your agent\'s skills/ directory.';
|
|
21
|
+
}
|
|
22
|
+
const lines = [styled.honeyBold('Available Skills:'), ''];
|
|
23
|
+
for (const skill of skills) {
|
|
24
|
+
const nameDisplay = styled.honey(skill.metadata.name);
|
|
25
|
+
const descDisplay = skill.metadata.description;
|
|
26
|
+
lines.push(` ${nameDisplay}`);
|
|
27
|
+
lines.push(` ${descDisplay}`);
|
|
28
|
+
if (skill.metadata.compatibility) {
|
|
29
|
+
const compatDisplay = styled.dim(`[${skill.metadata.compatibility}]`);
|
|
30
|
+
lines.push(` ${compatDisplay}`);
|
|
31
|
+
}
|
|
32
|
+
lines.push('');
|
|
33
|
+
}
|
|
34
|
+
return lines.join('\n').trimEnd();
|
|
35
|
+
}
|
|
36
|
+
export async function skillsSlashCommand(agentName, callbacks) {
|
|
37
|
+
const result = await fetchSkills(agentName);
|
|
38
|
+
if (!result.success) {
|
|
39
|
+
callbacks.onError?.(result.error);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const formatted = formatSkills(result.data);
|
|
43
|
+
callbacks.onSuccess?.(formatted);
|
|
44
|
+
}
|