@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,152 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { colors, symbols } from '../../shared/theme.js';
|
|
3
|
+
import { formatTime, formatTokenUsage } from '../../../shared/agent/utils.js';
|
|
4
|
+
import { HIVE_FRONTEND_URL } from '../../../shared/config/constant.js';
|
|
5
|
+
const time = (item) => chalk.gray.dim(`${formatTime(item.timestamp)} `);
|
|
6
|
+
const onlineActivityFormatter = {
|
|
7
|
+
getText(item) {
|
|
8
|
+
return `${item.name} agent online \u2014 "${item.bio}"`;
|
|
9
|
+
},
|
|
10
|
+
getDetail(_item) {
|
|
11
|
+
return undefined;
|
|
12
|
+
},
|
|
13
|
+
format(item) {
|
|
14
|
+
const text = this.getText(item);
|
|
15
|
+
return [` ${time(item)}${chalk.hex(colors.honey)(symbols.hive)} ${chalk.white(text)}`];
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
const idelActivityFormatter = {
|
|
19
|
+
getText(item) {
|
|
20
|
+
return item.text;
|
|
21
|
+
},
|
|
22
|
+
getDetail(_item) {
|
|
23
|
+
return undefined;
|
|
24
|
+
},
|
|
25
|
+
format(item) {
|
|
26
|
+
return [` ${time(item)}${chalk.gray(`${symbols.circle} ${this.getText(item)}`)}`];
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const errorActivityFormatter = {
|
|
30
|
+
getText(item) {
|
|
31
|
+
return item.errorMessage;
|
|
32
|
+
},
|
|
33
|
+
getDetail(_item) {
|
|
34
|
+
return undefined;
|
|
35
|
+
},
|
|
36
|
+
format(item) {
|
|
37
|
+
return [` ${time(item)}${chalk.hex(colors.red)(`${symbols.cross} ${this.getText(item)}`)}`];
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const megathreadPostedActivityFormatter = {
|
|
41
|
+
getText(item) {
|
|
42
|
+
const sign = item.conviction >= 0 ? '+' : '';
|
|
43
|
+
return `[${sign}${item.conviction.toFixed(2)}%] "${item.summary}"`;
|
|
44
|
+
},
|
|
45
|
+
getDetail(item) {
|
|
46
|
+
return item.id.split('@')[0];
|
|
47
|
+
},
|
|
48
|
+
format(item) {
|
|
49
|
+
const lines = [];
|
|
50
|
+
const pad = ' '.repeat(13);
|
|
51
|
+
const cColor = colors.controversial;
|
|
52
|
+
const url = `${HIVE_FRONTEND_URL}/c/${item.projectId}/megathread/${item.timeframe}`;
|
|
53
|
+
const result = this.getText(item);
|
|
54
|
+
lines.push(`${pad}${chalk.hex(cColor)(symbols.diamond)} ${chalk.white(result)}`);
|
|
55
|
+
lines.push(`${' '.repeat(15)}${chalk.gray.dim(`url: ${url}`)}`);
|
|
56
|
+
return lines;
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
const megathreadErrorActivityFormatter = {
|
|
60
|
+
getText(item) {
|
|
61
|
+
return item.errorMessage;
|
|
62
|
+
},
|
|
63
|
+
getDetail(item) {
|
|
64
|
+
return item.id.split('@')[0];
|
|
65
|
+
},
|
|
66
|
+
format(item) {
|
|
67
|
+
const pad = ' '.repeat(13);
|
|
68
|
+
return [`${pad}${chalk.hex(colors.red)(`${symbols.cross} ${this.getText(item)}`)}`];
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
const megathreadActivityFormatter = {
|
|
72
|
+
getText(item) {
|
|
73
|
+
const projectTag = `c/${item.projectId}`;
|
|
74
|
+
return `${projectTag} \u00B7 ${item.timeframe} round`;
|
|
75
|
+
},
|
|
76
|
+
getDetail(item) {
|
|
77
|
+
return item.id.split('@')[0];
|
|
78
|
+
},
|
|
79
|
+
format(item) {
|
|
80
|
+
const mainLine = ` ${time(item)}${chalk.hex(colors.controversial)(symbols.hive)} ${chalk.hex(colors.controversial)(this.getText(item))}`;
|
|
81
|
+
const lines = [mainLine];
|
|
82
|
+
switch (item.status) {
|
|
83
|
+
case 'skipped': {
|
|
84
|
+
lines[0] += chalk.hex(colors.honey)(` ${symbols.diamondOpen} skipped`);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case 'posted': {
|
|
88
|
+
lines.push(...megathreadPostedActivityFormatter.format(item));
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'error': {
|
|
92
|
+
lines.push(...megathreadErrorActivityFormatter.format(item));
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (item.tokenUsage) {
|
|
99
|
+
const { input, output, tools } = formatTokenUsage(item.tokenUsage);
|
|
100
|
+
lines.push(`${' '.repeat(15)}${chalk.gray.dim(`${input} \u00b7 ${output}`)}`);
|
|
101
|
+
if (tools !== null) {
|
|
102
|
+
const toolCountInfo = `${tools} (${item.tokenUsage.toolCalls} calls)`;
|
|
103
|
+
lines.push(`${' '.repeat(15)}${chalk.gray.dim(toolCountInfo)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return lines;
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
export const activityFormatter = {
|
|
110
|
+
getText(item) {
|
|
111
|
+
switch (item.type) {
|
|
112
|
+
case 'error':
|
|
113
|
+
return errorActivityFormatter.getText(item);
|
|
114
|
+
case 'idle':
|
|
115
|
+
return idelActivityFormatter.getText(item);
|
|
116
|
+
case 'megathread':
|
|
117
|
+
return megathreadActivityFormatter.getText(item);
|
|
118
|
+
case 'online':
|
|
119
|
+
return onlineActivityFormatter.getText(item);
|
|
120
|
+
default:
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
getDetail(item) {
|
|
125
|
+
switch (item.type) {
|
|
126
|
+
case 'error':
|
|
127
|
+
return errorActivityFormatter.getDetail(item);
|
|
128
|
+
case 'idle':
|
|
129
|
+
return idelActivityFormatter.getDetail(item);
|
|
130
|
+
case 'megathread':
|
|
131
|
+
return megathreadActivityFormatter.getDetail(item);
|
|
132
|
+
case 'online':
|
|
133
|
+
return onlineActivityFormatter.getDetail(item);
|
|
134
|
+
default:
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
format(item) {
|
|
139
|
+
switch (item.type) {
|
|
140
|
+
case 'error':
|
|
141
|
+
return errorActivityFormatter.format(item);
|
|
142
|
+
case 'idle':
|
|
143
|
+
return idelActivityFormatter.format(item);
|
|
144
|
+
case 'megathread':
|
|
145
|
+
return megathreadActivityFormatter.format(item);
|
|
146
|
+
case 'online':
|
|
147
|
+
return onlineActivityFormatter.format(item);
|
|
148
|
+
default:
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default backtest dataset bundled with the CLI.
|
|
3
|
+
* Contains 10 threads from Bitcoin, Ethereum, Solana, and Dogecoin.
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_BACKTEST_DATA = {
|
|
6
|
+
metadata: {
|
|
7
|
+
id: 'default',
|
|
8
|
+
name: 'Default Backtest Dataset',
|
|
9
|
+
created_at: '2026-02-26T00:00:00Z',
|
|
10
|
+
},
|
|
11
|
+
threads: [
|
|
12
|
+
{
|
|
13
|
+
project_id: 'ethereum',
|
|
14
|
+
project_name: 'Ethereum',
|
|
15
|
+
project_symbol: '$ETH',
|
|
16
|
+
project_categories: [
|
|
17
|
+
'smart-contract-platform',
|
|
18
|
+
'layer-1',
|
|
19
|
+
'ethereum-ecosystem',
|
|
20
|
+
'proof-of-stake-pos',
|
|
21
|
+
'world-liberty-financial-portfolio',
|
|
22
|
+
],
|
|
23
|
+
project_description: 'Ethereum is a global, open-source platform for decentralized applications.',
|
|
24
|
+
text: 'Balaji Srinivasan describes a "Global Privacy Era" as crypto\'s third phase, where the next decade of Web3 focuses on protecting user data and financial sovereignty through strong encryption rather than scalability or speed. Ethereum is highlighted as part of this shift from fully transparent ledgers to more confidential, programmable computation.',
|
|
25
|
+
timestamp: '2025-12-31T20:00:00Z',
|
|
26
|
+
price_on_fetch: 2969.01,
|
|
27
|
+
price_on_eval: 2971.55,
|
|
28
|
+
citations: [{ title: '2006719380713869499' }, { title: '2006683920881037680' }],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
project_id: 'solana',
|
|
32
|
+
project_name: 'Solana',
|
|
33
|
+
project_symbol: '$SOL',
|
|
34
|
+
project_categories: [
|
|
35
|
+
'smart-contract-platform',
|
|
36
|
+
'solana-ecosystem',
|
|
37
|
+
'layer-1',
|
|
38
|
+
'alleged-sec-securities',
|
|
39
|
+
'proof-of-stake-pos',
|
|
40
|
+
'made-in-usa',
|
|
41
|
+
'coinlist-launchpad',
|
|
42
|
+
],
|
|
43
|
+
project_description: 'Solana is a high-performance Layer 1 blockchain designed for mass adoption by providing a fast, secure, and low-cost environment for decentralized applications.',
|
|
44
|
+
text: 'ORE partners with PrivacyCash to launch an official shielded pool on Solana, enabling live private transfers of ORE as a native store-of-value token. Builders also announce Pandora OS v2.0 with stealth transfers and one-time unlinkable addresses on Solana mainnet, signaling major new privacy initiatives on the network.',
|
|
45
|
+
timestamp: '2026-01-01T01:00:00Z',
|
|
46
|
+
price_on_fetch: 124.98,
|
|
47
|
+
price_on_eval: 124.94,
|
|
48
|
+
citations: [{ title: '2006787547519918102' }, { title: '2006787600028410119' }],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
project_id: 'solana',
|
|
52
|
+
project_name: 'Solana',
|
|
53
|
+
project_symbol: '$SOL',
|
|
54
|
+
project_categories: [
|
|
55
|
+
'smart-contract-platform',
|
|
56
|
+
'solana-ecosystem',
|
|
57
|
+
'layer-1',
|
|
58
|
+
'alleged-sec-securities',
|
|
59
|
+
'proof-of-stake-pos',
|
|
60
|
+
'made-in-usa',
|
|
61
|
+
'coinlist-launchpad',
|
|
62
|
+
],
|
|
63
|
+
project_description: 'Solana is a high-performance Layer 1 blockchain designed for mass adoption by providing a fast, secure, and low-cost environment for decentralized applications.',
|
|
64
|
+
text: 'Solana is introducing the c-spl confidential token standard in Q1 2026, enabling encrypted balances and native private transfers. This privacy infrastructure targets institutional adoption by allowing banks and enterprises to conduct confidential onchain transactions, potentially unlocking complex financial instruments for the $16B in Solana stablecoins.',
|
|
65
|
+
timestamp: '2026-01-01T06:00:00Z',
|
|
66
|
+
price_on_fetch: 125.06,
|
|
67
|
+
price_on_eval: 124.43,
|
|
68
|
+
citations: [{ title: '2006857900543848485' }, { title: '2006862849327435958' }],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
project_id: 'bitcoin',
|
|
72
|
+
project_name: 'Bitcoin',
|
|
73
|
+
project_symbol: '$BTC',
|
|
74
|
+
project_categories: [
|
|
75
|
+
'smart-contract-platform',
|
|
76
|
+
'layer-1',
|
|
77
|
+
'proof-of-work-pow',
|
|
78
|
+
'bitcoin-ecosystem',
|
|
79
|
+
],
|
|
80
|
+
project_description: "Bitcoin is the world's first decentralized cryptocurrency, created in 2009 by the pseudonymous Satoshi Nakamoto.",
|
|
81
|
+
text: 'BlackRock transferred 1,134 BTC (~$101.4M) and 7,255 ETH (~$22.1M) to Coinbase/ Coinbase Prime and is described as selling millions in crypto ahead of a key PMI data release. The move coincides with $2.2B in BTC and ETH options expiry, drawing market attention to potential selling pressure on Bitcoin and Ethereum.',
|
|
82
|
+
timestamp: '2026-01-01T19:00:00Z',
|
|
83
|
+
price_on_fetch: 88053,
|
|
84
|
+
price_on_eval: 88266,
|
|
85
|
+
citations: [{ title: '2007064336708354389' }, { title: '2007066963671924967' }],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
project_id: 'solana',
|
|
89
|
+
project_name: 'Solana',
|
|
90
|
+
project_symbol: '$SOL',
|
|
91
|
+
project_categories: [
|
|
92
|
+
'smart-contract-platform',
|
|
93
|
+
'solana-ecosystem',
|
|
94
|
+
'layer-1',
|
|
95
|
+
'alleged-sec-securities',
|
|
96
|
+
'proof-of-stake-pos',
|
|
97
|
+
'made-in-usa',
|
|
98
|
+
'coinlist-launchpad',
|
|
99
|
+
],
|
|
100
|
+
project_description: 'Solana is a high-performance Layer 1 blockchain designed for mass adoption by providing a fast, secure, and low-cost environment for decentralized applications.',
|
|
101
|
+
text: 'Tweets highlight Solana\'s active memecoin culture, with users trading and promoting tokens like $KITKAT, $wif, SolanaWhale, and Epileptic, and tools such as MemeMax and 24/7 "Solana Memecoin Hunting" communities emerging. References to Trump\'s 2025 Solana memecoin and expectations for 2026 ("Make Solana Memecoins great again") show sustained speculative interest and growing infrastructure around Solana memecoin trading.',
|
|
102
|
+
timestamp: '2026-01-02T01:00:00Z',
|
|
103
|
+
price_on_fetch: 126.59,
|
|
104
|
+
price_on_eval: 127.47,
|
|
105
|
+
citations: [{ title: '2007142205451055298' }, { title: '2007150298876522740' }],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
project_id: 'dogecoin',
|
|
109
|
+
project_name: 'Dogecoin',
|
|
110
|
+
project_symbol: '$DOGE',
|
|
111
|
+
project_categories: [
|
|
112
|
+
'smart-contract-platform',
|
|
113
|
+
'meme-token',
|
|
114
|
+
'dog-themed-coins',
|
|
115
|
+
'elon-musk-inspired-coins',
|
|
116
|
+
'proof-of-work-pow',
|
|
117
|
+
'4chan-themed',
|
|
118
|
+
],
|
|
119
|
+
project_description: 'Dogecoin is a cryptocurrency based on the popular "Doge" Internet meme and features a Shiba Inu on its logo.',
|
|
120
|
+
text: 'Tweets highlight growing focus on a proposed Bitwise Dogecoin ETF (ticker "BWOW"), emphasizing that it carries high risk, significant volatility, and potential for complete loss of investment, and is not registered under the 1940 Act. Market chatter also notes a January 9 final decision deadline for a Dogecoin ETF and rising Dogecoin price and open interest into 2026.',
|
|
121
|
+
timestamp: '2026-01-02T07:00:00Z',
|
|
122
|
+
price_on_fetch: 0.128493,
|
|
123
|
+
price_on_eval: 0.132792,
|
|
124
|
+
citations: [{ title: '2007168051129840065' }, { title: '2007118652018196634' }],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
project_id: 'bitcoin',
|
|
128
|
+
project_name: 'Bitcoin',
|
|
129
|
+
project_symbol: '$BTC',
|
|
130
|
+
project_categories: [
|
|
131
|
+
'smart-contract-platform',
|
|
132
|
+
'layer-1',
|
|
133
|
+
'proof-of-work-pow',
|
|
134
|
+
'bitcoin-ecosystem',
|
|
135
|
+
],
|
|
136
|
+
project_description: "Bitcoin is the world's first decentralized cryptocurrency, created in 2009 by the pseudonymous Satoshi Nakamoto.",
|
|
137
|
+
text: 'Bitcoin users mark Proof of Keys Day, coinciding with the 17th anniversary of the Genesis Block, by urging holders to withdraw BTC from exchanges into cold storage and verify self-custody. Tweets emphasize the slogan "Not your keys, not your coins" and frame the day as a security checkup for Bitcoin holdings.',
|
|
138
|
+
timestamp: '2026-01-02T15:00:00Z',
|
|
139
|
+
price_on_fetch: 89551,
|
|
140
|
+
price_on_eval: 90310,
|
|
141
|
+
citations: [{ title: '2007362498282901908' }, { title: '2007373924133417089' }],
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
project_id: 'solana',
|
|
145
|
+
project_name: 'Solana',
|
|
146
|
+
project_symbol: '$SOL',
|
|
147
|
+
project_categories: [
|
|
148
|
+
'smart-contract-platform',
|
|
149
|
+
'solana-ecosystem',
|
|
150
|
+
'layer-1',
|
|
151
|
+
'alleged-sec-securities',
|
|
152
|
+
'proof-of-stake-pos',
|
|
153
|
+
'made-in-usa',
|
|
154
|
+
'coinlist-launchpad',
|
|
155
|
+
],
|
|
156
|
+
project_description: 'Solana is a high-performance Layer 1 blockchain designed for mass adoption by providing a fast, secure, and low-cost environment for decentralized applications.',
|
|
157
|
+
text: "Circle mints $750M USDC on Solana, marking the first injection of fresh USDC stablecoin liquidity on the network in 2026. This follows $56.25B USDC minted on Solana in 2025, reinforcing Solana's growing role as a major stablecoin and DeFi liquidity hub.",
|
|
158
|
+
timestamp: '2026-01-02T17:00:00Z',
|
|
159
|
+
price_on_fetch: 130.55,
|
|
160
|
+
price_on_eval: 131.54,
|
|
161
|
+
citations: [{ title: '2007386708032270424' }, { title: '2007383683783963093' }],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
project_id: 'ethereum',
|
|
165
|
+
project_name: 'Ethereum',
|
|
166
|
+
project_symbol: '$ETH',
|
|
167
|
+
project_categories: [
|
|
168
|
+
'smart-contract-platform',
|
|
169
|
+
'layer-1',
|
|
170
|
+
'ethereum-ecosystem',
|
|
171
|
+
'proof-of-stake-pos',
|
|
172
|
+
'world-liberty-financial-portfolio',
|
|
173
|
+
],
|
|
174
|
+
project_description: 'Ethereum is a global, open-source platform for decentralized applications.',
|
|
175
|
+
text: 'Ethereum spot ETFs record $174M in net inflows on Jan. 2, their strongest day since early December, after about $2B in outflows from November through December. Products from Grayscale and BlackRock lead the renewed institutional demand, signaling a shift back to risk-on sentiment for ETH in early 2026.',
|
|
176
|
+
timestamp: '2026-01-03T02:00:00Z',
|
|
177
|
+
price_on_fetch: 3129.52,
|
|
178
|
+
price_on_eval: 3114.78,
|
|
179
|
+
citations: [{ title: '2007536719055167799' }, { title: '2007492243502858607' }],
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
project_id: 'ethereum',
|
|
183
|
+
project_name: 'Ethereum',
|
|
184
|
+
project_symbol: '$ETH',
|
|
185
|
+
project_categories: [
|
|
186
|
+
'smart-contract-platform',
|
|
187
|
+
'layer-1',
|
|
188
|
+
'ethereum-ecosystem',
|
|
189
|
+
'proof-of-stake-pos',
|
|
190
|
+
'world-liberty-financial-portfolio',
|
|
191
|
+
],
|
|
192
|
+
project_description: 'Ethereum is a global, open-source platform for decentralized applications.',
|
|
193
|
+
text: 'Ethereum set a new all-time high with about 2.2-2.23 million transactions processed in a single day around Dec 29, 2025, with several subsequent days near that level. This record onchain activity indicates strong and growing network demand and utility across DeFi, NFTs, and emerging L2 ecosystems amid ongoing upgrades.',
|
|
194
|
+
timestamp: '2026-01-03T03:00:00Z',
|
|
195
|
+
price_on_fetch: 3125.17,
|
|
196
|
+
price_on_eval: 3110.91,
|
|
197
|
+
citations: [{ title: '2007529962350207036' }, { title: '2007525811075665958' }],
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { HiveClient } from '@zhive/sdk';
|
|
2
|
+
import { extractErrorMessage } from '../../../../shared/agent/utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetches locked threads from the API and converts them to BacktestData format.
|
|
5
|
+
* Only threads with price_on_eval are included (guaranteed by the API).
|
|
6
|
+
*/
|
|
7
|
+
export async function fetchBacktestThreads(limit, baseUrl) {
|
|
8
|
+
try {
|
|
9
|
+
const client = new HiveClient(baseUrl);
|
|
10
|
+
const threads = await client.getLockedThreads(limit);
|
|
11
|
+
const backtestThreads = threads
|
|
12
|
+
.filter((t) => t.price_on_eval !== undefined && t.price_on_eval !== null)
|
|
13
|
+
.map((t) => ({
|
|
14
|
+
project_id: t.project_id,
|
|
15
|
+
project_name: t.project_name,
|
|
16
|
+
project_symbol: t.project_symbol,
|
|
17
|
+
project_categories: t.project_categories,
|
|
18
|
+
project_description: t.project_description,
|
|
19
|
+
text: t.text,
|
|
20
|
+
timestamp: t.timestamp,
|
|
21
|
+
price_on_fetch: t.price_on_fetch,
|
|
22
|
+
price_on_eval: t.price_on_eval,
|
|
23
|
+
citations: t.citations,
|
|
24
|
+
}));
|
|
25
|
+
if (backtestThreads.length === 0) {
|
|
26
|
+
return { success: false, error: 'No resolved threads with price data found' };
|
|
27
|
+
}
|
|
28
|
+
const data = {
|
|
29
|
+
metadata: {
|
|
30
|
+
id: `api-${Date.now()}`,
|
|
31
|
+
name: `API fetch (${backtestThreads.length} threads)`,
|
|
32
|
+
created_at: new Date().toISOString(),
|
|
33
|
+
},
|
|
34
|
+
threads: backtestThreads,
|
|
35
|
+
};
|
|
36
|
+
return { success: true, data };
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const message = extractErrorMessage(error);
|
|
40
|
+
return { success: false, error: message };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { extractErrorMessage } from '../../../../shared/agent/utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Schema for validating imported JSON file.
|
|
6
|
+
*/
|
|
7
|
+
const citationSchema = z.object({
|
|
8
|
+
url: z.string().optional(),
|
|
9
|
+
title: z.string(),
|
|
10
|
+
});
|
|
11
|
+
const importThreadSchema = z.object({
|
|
12
|
+
project_id: z.string().min(1, 'project_id is required'),
|
|
13
|
+
project_name: z.string().min(1, 'project_name is required'),
|
|
14
|
+
text: z.string().min(1, 'text is required'),
|
|
15
|
+
timestamp: z.string().optional(),
|
|
16
|
+
price_on_fetch: z.number().positive('price_on_fetch must be positive'),
|
|
17
|
+
price_on_eval: z.number().positive('price_on_eval must be positive'),
|
|
18
|
+
project_symbol: z.string().optional(),
|
|
19
|
+
project_categories: z.array(z.string()).optional(),
|
|
20
|
+
project_description: z.string().optional(),
|
|
21
|
+
citations: z.array(citationSchema).optional(),
|
|
22
|
+
});
|
|
23
|
+
const importFileSchema = z.object({
|
|
24
|
+
name: z.string().optional(),
|
|
25
|
+
threads: z.array(importThreadSchema).min(1, 'At least one thread is required'),
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* Import and validate a backtest JSON file.
|
|
29
|
+
*/
|
|
30
|
+
export async function importBacktestFile(filePath) {
|
|
31
|
+
// Check if file exists
|
|
32
|
+
const exists = await fs.pathExists(filePath);
|
|
33
|
+
if (!exists) {
|
|
34
|
+
return { success: false, error: `File not found: ${filePath}` };
|
|
35
|
+
}
|
|
36
|
+
// Read file content
|
|
37
|
+
let content;
|
|
38
|
+
try {
|
|
39
|
+
content = await fs.readJson(filePath);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const message = extractErrorMessage(err);
|
|
43
|
+
return { success: false, error: `Failed to parse JSON: ${message}` };
|
|
44
|
+
}
|
|
45
|
+
// Validate structure
|
|
46
|
+
const parseResult = importFileSchema.safeParse(content);
|
|
47
|
+
if (!parseResult.success) {
|
|
48
|
+
const issues = parseResult.error.issues
|
|
49
|
+
.map((issue) => `${issue.path.join('.')}: ${issue.message}`)
|
|
50
|
+
.join('; ');
|
|
51
|
+
return { success: false, error: `Validation failed: ${issues}` };
|
|
52
|
+
}
|
|
53
|
+
const importData = parseResult.data;
|
|
54
|
+
// Convert to BacktestThread format
|
|
55
|
+
const threads = importData.threads.map((t) => convertImportThread(t));
|
|
56
|
+
return {
|
|
57
|
+
success: true,
|
|
58
|
+
data: {
|
|
59
|
+
name: importData.name,
|
|
60
|
+
threads,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Convert an import thread to a BacktestThread.
|
|
66
|
+
*/
|
|
67
|
+
function convertImportThread(input) {
|
|
68
|
+
const thread = {
|
|
69
|
+
project_id: input.project_id,
|
|
70
|
+
project_name: input.project_name,
|
|
71
|
+
project_symbol: input.project_symbol,
|
|
72
|
+
project_categories: input.project_categories,
|
|
73
|
+
project_description: input.project_description,
|
|
74
|
+
text: input.text,
|
|
75
|
+
timestamp: input.timestamp ?? new Date().toISOString(),
|
|
76
|
+
price_on_fetch: input.price_on_fetch,
|
|
77
|
+
price_on_eval: input.price_on_eval,
|
|
78
|
+
citations: input.citations ?? [],
|
|
79
|
+
};
|
|
80
|
+
return thread;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate a single thread input (for interactive mode).
|
|
84
|
+
*/
|
|
85
|
+
export function validateThreadInput(input) {
|
|
86
|
+
const errors = [];
|
|
87
|
+
if (!input.project_id || input.project_id.trim() === '') {
|
|
88
|
+
errors.push('project_id is required');
|
|
89
|
+
}
|
|
90
|
+
if (!input.project_name || input.project_name.trim() === '') {
|
|
91
|
+
errors.push('project_name is required');
|
|
92
|
+
}
|
|
93
|
+
if (!input.text || input.text.trim() === '') {
|
|
94
|
+
errors.push('text is required');
|
|
95
|
+
}
|
|
96
|
+
if (typeof input.price_on_fetch !== 'number' || input.price_on_fetch <= 0) {
|
|
97
|
+
errors.push('price_on_fetch must be a positive number');
|
|
98
|
+
}
|
|
99
|
+
if (typeof input.price_on_eval !== 'number' || input.price_on_eval <= 0) {
|
|
100
|
+
errors.push('price_on_eval must be a positive number');
|
|
101
|
+
}
|
|
102
|
+
return errors;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Create a BacktestThread from validated input.
|
|
106
|
+
*/
|
|
107
|
+
export function createThread(input) {
|
|
108
|
+
return convertImportThread(input);
|
|
109
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Import
|
|
2
|
+
export { importBacktestFile, validateThreadInput, createThread } from './import.js';
|
|
3
|
+
// Storage
|
|
4
|
+
export { DEFAULT_BACKTEST_ID, loadDefaultBacktest } from './storage.js';
|
|
5
|
+
// Fetch
|
|
6
|
+
export { fetchBacktestThreads } from './fetch.js';
|
|
7
|
+
// Runner
|
|
8
|
+
export { runBacktest } from './runner.js';
|
|
9
|
+
// Results
|
|
10
|
+
export { formatConviction, formatPercentage, getDirectionIndicator, formatThreadResult, formatSummary, getAccuracyGrade, buildTextReport, } from './results.js';
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a number with sign for display.
|
|
3
|
+
*/
|
|
4
|
+
export function formatConviction(value) {
|
|
5
|
+
const sign = value >= 0 ? '+' : '';
|
|
6
|
+
const formatted = `${sign}${value.toFixed(2)}%`;
|
|
7
|
+
return formatted;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Format a percentage for display.
|
|
11
|
+
*/
|
|
12
|
+
export function formatPercentage(value) {
|
|
13
|
+
const formatted = `${value.toFixed(1)}%`;
|
|
14
|
+
return formatted;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get direction indicator.
|
|
18
|
+
*/
|
|
19
|
+
export function getDirectionIndicator(conviction) {
|
|
20
|
+
if (conviction > 0) {
|
|
21
|
+
return 'bullish';
|
|
22
|
+
}
|
|
23
|
+
if (conviction < 0) {
|
|
24
|
+
return 'bearish';
|
|
25
|
+
}
|
|
26
|
+
return 'neutral';
|
|
27
|
+
}
|
|
28
|
+
export function formatThreadResult(result) {
|
|
29
|
+
if (result.skipped) {
|
|
30
|
+
return {
|
|
31
|
+
index: result.thread_index + 1,
|
|
32
|
+
projectName: result.project_name,
|
|
33
|
+
predicted: 'SKIP',
|
|
34
|
+
actual: formatConviction(result.actual_price_change_percent),
|
|
35
|
+
direction: 'skipped',
|
|
36
|
+
error: '-',
|
|
37
|
+
summary: '(skipped)',
|
|
38
|
+
thread_text: result.thread_text,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const directionLabel = result.direction_correct ? 'correct' : 'incorrect';
|
|
42
|
+
return {
|
|
43
|
+
index: result.thread_index + 1,
|
|
44
|
+
projectName: result.project_name,
|
|
45
|
+
predicted: formatConviction(result.predicted_conviction),
|
|
46
|
+
actual: formatConviction(result.actual_price_change_percent),
|
|
47
|
+
direction: directionLabel,
|
|
48
|
+
error: result.absolute_error !== null ? result.absolute_error.toFixed(2) : '-',
|
|
49
|
+
summary: result.predicted_summary.slice(0, 200) + (result.predicted_summary.length > 200 ? '...' : ''),
|
|
50
|
+
thread_text: result.thread_text.slice(0, 100) + (result.thread_text.length > 100 ? '...' : ''),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function formatSummary(result) {
|
|
54
|
+
return {
|
|
55
|
+
agentName: result.agent_name,
|
|
56
|
+
backtestId: result.backtest_id,
|
|
57
|
+
totalThreads: result.total_threads,
|
|
58
|
+
threadsPredicted: result.threads_predicted,
|
|
59
|
+
threadsSkipped: result.threads_skipped,
|
|
60
|
+
directionAccuracy: formatPercentage(result.direction_accuracy),
|
|
61
|
+
meanAbsoluteError: result.mean_absolute_error.toFixed(2),
|
|
62
|
+
runAt: new Date(result.run_at).toLocaleString(),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get accuracy grade based on direction accuracy percentage.
|
|
67
|
+
*/
|
|
68
|
+
export function getAccuracyGrade(accuracy) {
|
|
69
|
+
if (accuracy >= 70) {
|
|
70
|
+
return { grade: 'A', color: 'green' };
|
|
71
|
+
}
|
|
72
|
+
if (accuracy >= 60) {
|
|
73
|
+
return { grade: 'B', color: 'green' };
|
|
74
|
+
}
|
|
75
|
+
if (accuracy >= 50) {
|
|
76
|
+
return { grade: 'C', color: 'honey' };
|
|
77
|
+
}
|
|
78
|
+
if (accuracy >= 40) {
|
|
79
|
+
return { grade: 'D', color: 'red' };
|
|
80
|
+
}
|
|
81
|
+
return { grade: 'F', color: 'red' };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build a text report of the backtest results.
|
|
85
|
+
*/
|
|
86
|
+
export function buildTextReport(result) {
|
|
87
|
+
const lines = [];
|
|
88
|
+
const summary = formatSummary(result);
|
|
89
|
+
lines.push(`Backtest Results: ${summary.backtestId}`);
|
|
90
|
+
lines.push(`Agent: ${summary.agentName}`);
|
|
91
|
+
lines.push(`Run at: ${summary.runAt}`);
|
|
92
|
+
lines.push('');
|
|
93
|
+
lines.push('--- Summary ---');
|
|
94
|
+
lines.push(`Total threads: ${summary.totalThreads}`);
|
|
95
|
+
lines.push(`Predictions made: ${summary.threadsPredicted}`);
|
|
96
|
+
lines.push(`Skipped: ${summary.threadsSkipped}`);
|
|
97
|
+
lines.push(`Direction accuracy: ${summary.directionAccuracy}`);
|
|
98
|
+
lines.push(`Mean absolute error: ${summary.meanAbsoluteError}`);
|
|
99
|
+
lines.push('');
|
|
100
|
+
lines.push('--- Per-Thread Results ---');
|
|
101
|
+
for (const threadResult of result.thread_results) {
|
|
102
|
+
const formatted = formatThreadResult(threadResult);
|
|
103
|
+
const directionSymbol = formatted.direction === 'correct'
|
|
104
|
+
? '[OK]'
|
|
105
|
+
: formatted.direction === 'skipped'
|
|
106
|
+
? '[--]'
|
|
107
|
+
: '[XX]';
|
|
108
|
+
lines.push(`#${formatted.index} ${formatted.projectName}: Predicted ${formatted.predicted}, Actual ${formatted.actual} ${directionSymbol}`);
|
|
109
|
+
lines.push(`\tThread: ${formatted.thread_text}`);
|
|
110
|
+
lines.push(`\tSummary: ${formatted.summary}`);
|
|
111
|
+
}
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}
|