@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.
Files changed (189) hide show
  1. package/README.md +118 -0
  2. package/dist/agent/analysis.js +160 -0
  3. package/dist/agent/app.js +122 -0
  4. package/dist/agent/chat-prompt.js +65 -0
  5. package/dist/agent/commands/registry.js +12 -0
  6. package/dist/agent/components/AsciiTicker.js +81 -0
  7. package/dist/agent/components/CommandInput.js +65 -0
  8. package/dist/agent/components/HoneycombBoot.js +291 -0
  9. package/dist/agent/components/Spinner.js +37 -0
  10. package/dist/agent/config.js +75 -0
  11. package/dist/agent/edit-section.js +59 -0
  12. package/dist/agent/fetch-rules.js +21 -0
  13. package/dist/agent/helpers.js +22 -0
  14. package/dist/agent/hooks/useAgent.js +480 -0
  15. package/dist/agent/memory-prompt.js +47 -0
  16. package/dist/agent/model.js +92 -0
  17. package/dist/agent/objects.js +1 -0
  18. package/dist/agent/process-lifecycle.js +18 -0
  19. package/dist/agent/prompt.js +353 -0
  20. package/dist/agent/run-headless.js +189 -0
  21. package/dist/agent/skills/index.js +2 -0
  22. package/dist/agent/skills/skill-parser.js +149 -0
  23. package/dist/agent/skills/types.js +1 -0
  24. package/dist/agent/theme.js +41 -0
  25. package/dist/agent/tools/index.js +76 -0
  26. package/dist/agent/tools/market/client.js +41 -0
  27. package/dist/agent/tools/market/index.js +3 -0
  28. package/dist/agent/tools/market/tools.js +518 -0
  29. package/dist/agent/tools/mindshare/client.js +124 -0
  30. package/dist/agent/tools/mindshare/index.js +3 -0
  31. package/dist/agent/tools/mindshare/tools.js +563 -0
  32. package/dist/agent/tools/read-skill-tool.js +30 -0
  33. package/dist/agent/tools/ta/index.js +1 -0
  34. package/dist/agent/tools/ta/indicators.js +201 -0
  35. package/dist/agent/types.js +1 -0
  36. package/dist/agents.js +110 -0
  37. package/dist/ai-providers.js +66 -0
  38. package/dist/avatar.js +34 -0
  39. package/dist/backtest/default-backtest-data.js +200 -0
  40. package/dist/backtest/fetch.js +41 -0
  41. package/dist/backtest/import.js +106 -0
  42. package/dist/backtest/index.js +10 -0
  43. package/dist/backtest/results.js +113 -0
  44. package/dist/backtest/runner.js +134 -0
  45. package/dist/backtest/storage.js +11 -0
  46. package/dist/backtest/types.js +1 -0
  47. package/dist/commands/create/ai-generate.js +126 -0
  48. package/dist/commands/create/commands/index.js +10 -0
  49. package/dist/commands/create/generate.js +73 -0
  50. package/dist/commands/create/presets/data.js +225 -0
  51. package/dist/commands/create/presets/formatting.js +81 -0
  52. package/dist/commands/create/presets/index.js +3 -0
  53. package/dist/commands/create/presets/options.js +307 -0
  54. package/dist/commands/create/presets/types.js +1 -0
  55. package/dist/commands/create/presets.js +613 -0
  56. package/dist/commands/create/ui/CreateApp.js +172 -0
  57. package/dist/commands/create/ui/steps/ApiKeyStep.js +89 -0
  58. package/dist/commands/create/ui/steps/AvatarStep.js +16 -0
  59. package/dist/commands/create/ui/steps/DoneStep.js +14 -0
  60. package/dist/commands/create/ui/steps/IdentityStep.js +125 -0
  61. package/dist/commands/create/ui/steps/NameStep.js +148 -0
  62. package/dist/commands/create/ui/steps/ScaffoldStep.js +59 -0
  63. package/dist/commands/create/ui/steps/SoulStep.js +21 -0
  64. package/dist/commands/create/ui/steps/StrategyStep.js +20 -0
  65. package/dist/commands/create/ui/steps/StreamingGenerationStep.js +56 -0
  66. package/dist/commands/create/ui/validation.js +34 -0
  67. package/dist/commands/create/validate-api-key.js +27 -0
  68. package/dist/commands/install.js +50 -0
  69. package/dist/commands/list/commands/index.js +7 -0
  70. package/dist/commands/list/ui/ListApp.js +79 -0
  71. package/dist/commands/migrate-templates/commands/index.js +9 -0
  72. package/dist/commands/migrate-templates/migrate.js +87 -0
  73. package/dist/commands/migrate-templates/ui/MigrateApp.js +132 -0
  74. package/dist/commands/run/commands/index.js +17 -0
  75. package/dist/commands/run/run-headless.js +111 -0
  76. package/dist/commands/shared/theme.js +57 -0
  77. package/dist/commands/shared/welcome.js +304 -0
  78. package/dist/commands/start/commands/backtest.js +35 -0
  79. package/dist/commands/start/commands/index.js +62 -0
  80. package/dist/commands/start/commands/prediction.js +73 -0
  81. package/dist/commands/start/commands/skills.js +44 -0
  82. package/dist/commands/start/commands/skills.test.js +140 -0
  83. package/dist/commands/start/hooks/types.js +1 -0
  84. package/dist/commands/start/hooks/useAgent.js +177 -0
  85. package/dist/commands/start/hooks/useChat.js +266 -0
  86. package/dist/commands/start/hooks/usePollActivity.js +45 -0
  87. package/dist/commands/start/hooks/utils.js +152 -0
  88. package/dist/commands/start/services/backtest/default-backtest-data.js +200 -0
  89. package/dist/commands/start/services/backtest/fetch.js +42 -0
  90. package/dist/commands/start/services/backtest/import.js +109 -0
  91. package/dist/commands/start/services/backtest/index.js +10 -0
  92. package/dist/commands/start/services/backtest/results.js +113 -0
  93. package/dist/commands/start/services/backtest/runner.js +103 -0
  94. package/dist/commands/start/services/backtest/storage.js +11 -0
  95. package/dist/commands/start/services/backtest/types.js +1 -0
  96. package/dist/commands/start/services/command-registry.js +13 -0
  97. package/dist/commands/start/ui/AsciiTicker.js +81 -0
  98. package/dist/commands/start/ui/CommandInput.js +65 -0
  99. package/dist/commands/start/ui/HoneycombBoot.js +291 -0
  100. package/dist/commands/start/ui/PollText.js +23 -0
  101. package/dist/commands/start/ui/PredictionsPanel.js +88 -0
  102. package/dist/commands/start/ui/SelectAgentApp.js +93 -0
  103. package/dist/commands/start/ui/Spinner.js +29 -0
  104. package/dist/commands/start/ui/SpinnerContext.js +20 -0
  105. package/dist/commands/start/ui/app.js +36 -0
  106. package/dist/commands/start-all/AgentProcessManager.js +98 -0
  107. package/dist/commands/start-all/commands/index.js +24 -0
  108. package/dist/commands/start-all/ui/Dashboard.js +91 -0
  109. package/dist/components/AsciiTicker.js +81 -0
  110. package/dist/components/CharacterSummaryCard.js +33 -0
  111. package/dist/components/CodeBlock.js +11 -0
  112. package/dist/components/ColoredStats.js +18 -0
  113. package/dist/components/Header.js +10 -0
  114. package/dist/components/HoneycombLoader.js +190 -0
  115. package/dist/components/InputGuard.js +6 -0
  116. package/dist/components/MultiSelectPrompt.js +45 -0
  117. package/dist/components/SelectPrompt.js +20 -0
  118. package/dist/components/Spinner.js +16 -0
  119. package/dist/components/StepIndicator.js +31 -0
  120. package/dist/components/StreamingText.js +50 -0
  121. package/dist/components/TextPrompt.js +28 -0
  122. package/dist/components/stdout-spinner.js +48 -0
  123. package/dist/config.js +28 -0
  124. package/dist/create/CreateApp.js +153 -0
  125. package/dist/create/ai-generate.js +147 -0
  126. package/dist/create/generate.js +73 -0
  127. package/dist/create/steps/ApiKeyStep.js +97 -0
  128. package/dist/create/steps/AvatarStep.js +16 -0
  129. package/dist/create/steps/BioStep.js +14 -0
  130. package/dist/create/steps/DoneStep.js +14 -0
  131. package/dist/create/steps/IdentityStep.js +163 -0
  132. package/dist/create/steps/NameStep.js +71 -0
  133. package/dist/create/steps/ScaffoldStep.js +58 -0
  134. package/dist/create/steps/SoulStep.js +58 -0
  135. package/dist/create/steps/StrategyStep.js +58 -0
  136. package/dist/create/validate-api-key.js +47 -0
  137. package/dist/create/welcome.js +304 -0
  138. package/dist/index.js +60 -0
  139. package/dist/list/ListApp.js +79 -0
  140. package/dist/load-agent-env.js +30 -0
  141. package/dist/migrate-templates/MigrateApp.js +131 -0
  142. package/dist/migrate-templates/migrate.js +86 -0
  143. package/dist/presets.js +613 -0
  144. package/dist/shared/agent/agent-runtime.js +144 -0
  145. package/dist/shared/agent/analysis.js +171 -0
  146. package/dist/shared/agent/helpers.js +1 -0
  147. package/dist/shared/agent/prompts/chat-prompt.js +60 -0
  148. package/dist/shared/agent/prompts/megathread.js +202 -0
  149. package/dist/shared/agent/prompts/memory-prompt.js +47 -0
  150. package/dist/shared/agent/prompts/prompt.js +18 -0
  151. package/dist/shared/agent/skills/index.js +2 -0
  152. package/dist/shared/agent/skills/skill-parser.js +167 -0
  153. package/dist/shared/agent/skills/skill-parser.test.js +190 -0
  154. package/dist/shared/agent/skills/types.js +1 -0
  155. package/dist/shared/agent/tools/edit-section.js +60 -0
  156. package/dist/shared/agent/tools/execute-skill-tool.js +134 -0
  157. package/dist/shared/agent/tools/fetch-rules.js +22 -0
  158. package/dist/shared/agent/tools/formatting.js +48 -0
  159. package/dist/shared/agent/tools/index.js +87 -0
  160. package/dist/shared/agent/tools/market/client.js +41 -0
  161. package/dist/shared/agent/tools/market/index.js +3 -0
  162. package/dist/shared/agent/tools/market/tools.js +497 -0
  163. package/dist/shared/agent/tools/mindshare/client.js +124 -0
  164. package/dist/shared/agent/tools/mindshare/index.js +3 -0
  165. package/dist/shared/agent/tools/mindshare/tools.js +167 -0
  166. package/dist/shared/agent/tools/read-skill-tool.js +30 -0
  167. package/dist/shared/agent/tools/ta/index.js +1 -0
  168. package/dist/shared/agent/tools/ta/indicators.js +201 -0
  169. package/dist/shared/agent/types.js +1 -0
  170. package/dist/shared/agent/utils.js +43 -0
  171. package/dist/shared/config/agent.js +177 -0
  172. package/dist/shared/config/ai-providers.js +156 -0
  173. package/dist/shared/config/config.js +22 -0
  174. package/dist/shared/config/constant.js +8 -0
  175. package/dist/shared/config/env-loader.js +30 -0
  176. package/dist/shared/types.js +1 -0
  177. package/dist/start/AgentProcessManager.js +98 -0
  178. package/dist/start/Dashboard.js +92 -0
  179. package/dist/start/SelectAgentApp.js +81 -0
  180. package/dist/start/StartApp.js +189 -0
  181. package/dist/start/patch-headless.js +101 -0
  182. package/dist/start/patch-managed-mode.js +142 -0
  183. package/dist/start/start-command.js +24 -0
  184. package/dist/theme.js +54 -0
  185. package/package.json +68 -0
  186. package/templates/components/HoneycombBoot.tsx +343 -0
  187. package/templates/fetch-rules.ts +23 -0
  188. package/templates/skills/mindshare/SKILL.md +197 -0
  189. 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
+ }