@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,172 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
import { Box, Text, useApp } from 'ink';
|
|
4
|
+
import { Header } from '../../../components/Header.js';
|
|
5
|
+
import { AsciiTicker } from '../../../components/AsciiTicker.js';
|
|
6
|
+
import { StepIndicator } from '../../../components/StepIndicator.js';
|
|
7
|
+
import { ApiKeyStep } from './steps/ApiKeyStep.js';
|
|
8
|
+
import { NameStep } from './steps/NameStep.js';
|
|
9
|
+
import { IdentityStep } from './steps/IdentityStep.js';
|
|
10
|
+
import { AvatarStep } from './steps/AvatarStep.js';
|
|
11
|
+
import { SoulStep } from './steps/SoulStep.js';
|
|
12
|
+
import { StrategyStep } from './steps/StrategyStep.js';
|
|
13
|
+
import { ScaffoldStep } from './steps/ScaffoldStep.js';
|
|
14
|
+
import { DoneStep } from './steps/DoneStep.js';
|
|
15
|
+
import { colors, symbols } from '../../shared/theme.js';
|
|
16
|
+
import { getProvider } from '../../../shared/config/ai-providers.js';
|
|
17
|
+
function ensureAvatarUrl(content, avatarUrl) {
|
|
18
|
+
const lines = content.split('\n');
|
|
19
|
+
const avatarIdx = lines.findIndex((l) => /^## Avatar/.test(l));
|
|
20
|
+
if (avatarIdx === -1) {
|
|
21
|
+
return content;
|
|
22
|
+
}
|
|
23
|
+
// Find the next section header after ## Avatar
|
|
24
|
+
let nextSectionIdx = lines.length;
|
|
25
|
+
for (let i = avatarIdx + 1; i < lines.length; i++) {
|
|
26
|
+
if (/^##?\s/.test(lines[i])) {
|
|
27
|
+
nextSectionIdx = i;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Replace the content between ## Avatar and next section with the raw URL
|
|
32
|
+
const before = lines.slice(0, avatarIdx + 1);
|
|
33
|
+
const after = lines.slice(nextSectionIdx);
|
|
34
|
+
const result = [...before, '', avatarUrl, '', ...after];
|
|
35
|
+
return result.join('\n');
|
|
36
|
+
}
|
|
37
|
+
function ensureSectionLine(content, sectionHeader, linePrefix, value) {
|
|
38
|
+
const lines = content.split('\n');
|
|
39
|
+
const sectionIdx = lines.findIndex((l) => new RegExp(`^##\\s+${sectionHeader}`).test(l));
|
|
40
|
+
if (sectionIdx === -1) {
|
|
41
|
+
// Section missing — append it at the end
|
|
42
|
+
return content + `\n\n## ${sectionHeader}\n\n${linePrefix} ${value}\n`;
|
|
43
|
+
}
|
|
44
|
+
// Find the next section header after this one
|
|
45
|
+
let nextSectionIdx = lines.length;
|
|
46
|
+
for (let i = sectionIdx + 1; i < lines.length; i++) {
|
|
47
|
+
if (/^##?\s/.test(lines[i])) {
|
|
48
|
+
nextSectionIdx = i;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Look for existing line with the prefix in this section
|
|
53
|
+
const escapedPrefix = linePrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
54
|
+
const prefixRegex = new RegExp(`^${escapedPrefix}\\s`);
|
|
55
|
+
const lineIdx = lines.findIndex((l, i) => i > sectionIdx && i < nextSectionIdx && prefixRegex.test(l));
|
|
56
|
+
if (lineIdx !== -1) {
|
|
57
|
+
// Replace the existing line
|
|
58
|
+
lines[lineIdx] = `${linePrefix} ${value}`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Insert after the section header (skip blank lines)
|
|
62
|
+
let insertIdx = sectionIdx + 1;
|
|
63
|
+
while (insertIdx < nextSectionIdx && lines[insertIdx].trim() === '') {
|
|
64
|
+
insertIdx++;
|
|
65
|
+
}
|
|
66
|
+
lines.splice(insertIdx, 0, `${linePrefix} ${value}`);
|
|
67
|
+
}
|
|
68
|
+
// Remove duplicate/malformed lines with the same prefix (e.g. "- Active timeframes" without value)
|
|
69
|
+
const loosePrefix = linePrefix.replace(/:$/, '');
|
|
70
|
+
const looseRegex = new RegExp(`^${loosePrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(\\s|$)`);
|
|
71
|
+
const canonicalLine = `${linePrefix} ${value}`;
|
|
72
|
+
for (let i = nextSectionIdx - 1; i > sectionIdx; i--) {
|
|
73
|
+
if (looseRegex.test(lines[i]) && lines[i] !== canonicalLine) {
|
|
74
|
+
lines.splice(i, 1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return lines.join('\n');
|
|
78
|
+
}
|
|
79
|
+
function ensureStrategyFields(content, sectors, sentiment, timeframes) {
|
|
80
|
+
const sectorsLine = sectors.length > 0 ? sectors.join(', ') : 'all categories';
|
|
81
|
+
const timeframesLine = timeframes.length > 0 ? timeframes.join(', ') : '1h, 4h, 24h';
|
|
82
|
+
let patched = ensureSectionLine(content, 'Sentiment', '- Bias:', sentiment);
|
|
83
|
+
patched = ensureSectionLine(patched, 'Sector Focus', '- Sectors:', sectorsLine);
|
|
84
|
+
patched = ensureSectionLine(patched, 'Timeframe', '- Active timeframes:', timeframesLine);
|
|
85
|
+
return patched;
|
|
86
|
+
}
|
|
87
|
+
const STEP_ORDER = [
|
|
88
|
+
'name',
|
|
89
|
+
'identity',
|
|
90
|
+
'avatar',
|
|
91
|
+
'api-key',
|
|
92
|
+
'soul',
|
|
93
|
+
'strategy',
|
|
94
|
+
'scaffold',
|
|
95
|
+
'done',
|
|
96
|
+
];
|
|
97
|
+
const STEP_LABELS = {
|
|
98
|
+
'api-key': 'API Key',
|
|
99
|
+
name: 'Name',
|
|
100
|
+
identity: 'Identity',
|
|
101
|
+
avatar: 'Avatar',
|
|
102
|
+
soul: 'Soul',
|
|
103
|
+
strategy: 'Strategy',
|
|
104
|
+
scaffold: 'Scaffold',
|
|
105
|
+
done: 'Done',
|
|
106
|
+
};
|
|
107
|
+
const STEP_DEFS = STEP_ORDER.map((s) => ({ key: s, label: STEP_LABELS[s] }));
|
|
108
|
+
export function CreateApp({ initialName }) {
|
|
109
|
+
const { exit } = useApp();
|
|
110
|
+
const [step, setStep] = useState(initialName ? 'identity' : 'name');
|
|
111
|
+
const [providerId, setProviderId] = useState(null);
|
|
112
|
+
const [apiKey, setApiKey] = useState('');
|
|
113
|
+
const [agentName, setAgentName] = useState(initialName ?? '');
|
|
114
|
+
const [bio, setBio] = useState('');
|
|
115
|
+
const [personality, setPersonality] = useState('');
|
|
116
|
+
const [tone, setTone] = useState('');
|
|
117
|
+
const [voiceStyle, setVoiceStyle] = useState('');
|
|
118
|
+
const [tradingStyle, setTradingStyle] = useState('');
|
|
119
|
+
const [sectors, setSectors] = useState([]);
|
|
120
|
+
const [sentiment, setSentiment] = useState('');
|
|
121
|
+
const [timeframes, setTimeframes] = useState([]);
|
|
122
|
+
const [avatarUrl, setAvatarUrl] = useState('');
|
|
123
|
+
const [soulContent, setSoulContent] = useState('');
|
|
124
|
+
const [strategyContent, setStrategyContent] = useState('');
|
|
125
|
+
const [resolvedProjectDir, setResolvedProjectDir] = useState('');
|
|
126
|
+
const [error, setError] = useState('');
|
|
127
|
+
const stepIndex = STEP_ORDER.indexOf(step);
|
|
128
|
+
const provider = providerId ? getProvider(providerId) : null;
|
|
129
|
+
const handleApiKey = useCallback((result) => {
|
|
130
|
+
setProviderId(result.providerId);
|
|
131
|
+
setApiKey(result.apiKey);
|
|
132
|
+
setStep('soul');
|
|
133
|
+
}, []);
|
|
134
|
+
const handleName = useCallback((name) => {
|
|
135
|
+
setAgentName(name);
|
|
136
|
+
setStep('identity');
|
|
137
|
+
}, []);
|
|
138
|
+
const handleIdentity = useCallback((result) => {
|
|
139
|
+
setPersonality(result.personality);
|
|
140
|
+
setTone(result.tone);
|
|
141
|
+
setVoiceStyle(result.voiceStyle);
|
|
142
|
+
setTradingStyle(result.tradingStyle);
|
|
143
|
+
setSectors(result.sectors);
|
|
144
|
+
setSentiment(result.sentiment);
|
|
145
|
+
setTimeframes(result.timeframes);
|
|
146
|
+
setBio(result.bio);
|
|
147
|
+
setStep('avatar');
|
|
148
|
+
}, []);
|
|
149
|
+
const handleAvatar = useCallback((value) => {
|
|
150
|
+
setAvatarUrl(value);
|
|
151
|
+
setStep('api-key');
|
|
152
|
+
}, []);
|
|
153
|
+
const handleSoul = useCallback((content) => {
|
|
154
|
+
const patched = ensureAvatarUrl(content, avatarUrl);
|
|
155
|
+
setSoulContent(patched);
|
|
156
|
+
setStep('strategy');
|
|
157
|
+
}, [avatarUrl]);
|
|
158
|
+
const handleStrategy = useCallback((content) => {
|
|
159
|
+
const patched = ensureStrategyFields(content, sectors, sentiment, timeframes);
|
|
160
|
+
setStrategyContent(patched);
|
|
161
|
+
setStep('scaffold');
|
|
162
|
+
}, [sectors, sentiment, timeframes]);
|
|
163
|
+
const handleScaffoldComplete = useCallback((projectDir) => {
|
|
164
|
+
setResolvedProjectDir(projectDir);
|
|
165
|
+
setStep('done');
|
|
166
|
+
}, []);
|
|
167
|
+
const handleScaffoldError = useCallback((message) => {
|
|
168
|
+
setError(message);
|
|
169
|
+
exit();
|
|
170
|
+
}, [exit]);
|
|
171
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsx(StepIndicator, { steps: STEP_DEFS, currentIndex: stepIndex }), step !== 'done' && (_jsx(Box, { marginBottom: 1, children: _jsx(AsciiTicker, { step: stepIndex + 1 }) })), step === 'api-key' && _jsx(ApiKeyStep, { onComplete: handleApiKey }), step === 'name' && _jsx(NameStep, { onComplete: handleName }), step === 'identity' && _jsx(IdentityStep, { agentName: agentName, onComplete: handleIdentity }), step === 'avatar' && _jsx(AvatarStep, { agentName: agentName, onComplete: handleAvatar }), step === 'soul' && providerId && (_jsx(SoulStep, { providerId: providerId, apiKey: apiKey, agentName: agentName, bio: bio, avatarUrl: avatarUrl, personality: personality, tone: tone, voiceStyle: voiceStyle, tradingStyle: tradingStyle, sectors: sectors, sentiment: sentiment, timeframes: timeframes, onComplete: handleSoul })), step === 'strategy' && providerId && (_jsx(StrategyStep, { providerId: providerId, apiKey: apiKey, agentName: agentName, bio: bio, personality: personality, tone: tone, voiceStyle: voiceStyle, tradingStyle: tradingStyle, sectors: sectors, sentiment: sentiment, timeframes: timeframes, onComplete: handleStrategy })), step === 'scaffold' && provider && (_jsx(ScaffoldStep, { projectName: agentName, provider: provider, apiKey: apiKey, soulContent: soulContent, strategyContent: strategyContent, onComplete: handleScaffoldComplete, onError: handleScaffoldError })), step === 'done' && _jsx(DoneStep, { projectDir: resolvedProjectDir }), error !== '' && (_jsx(Box, { marginTop: 1, marginLeft: 2, children: _jsxs(Text, { color: colors.red, children: [symbols.cross, " ", error] }) }))] }));
|
|
172
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { SelectPrompt } from '../../../../components/SelectPrompt.js';
|
|
5
|
+
import { TextPrompt } from '../../../../components/TextPrompt.js';
|
|
6
|
+
import { Spinner } from '../../../../components/Spinner.js';
|
|
7
|
+
import { colors, symbols } from '../../../shared/theme.js';
|
|
8
|
+
import { AI_PROVIDERS } from '../../../../shared/config/ai-providers.js';
|
|
9
|
+
import { validateApiKey } from '../../validate-api-key.js';
|
|
10
|
+
import { readConfig, writeConfig } from '../../../../shared/config/config.js';
|
|
11
|
+
import { apiKey as validateApiKeyFormat } from '../validation.js';
|
|
12
|
+
function maskKey(key) {
|
|
13
|
+
if (key.length <= 8) {
|
|
14
|
+
return '****';
|
|
15
|
+
}
|
|
16
|
+
const visible = key.slice(0, 4) + '...' + key.slice(-4);
|
|
17
|
+
return visible;
|
|
18
|
+
}
|
|
19
|
+
export function ApiKeyStep({ onComplete }) {
|
|
20
|
+
const [phase, setPhase] = useState('check-saved');
|
|
21
|
+
const [savedConfig, setSavedConfig] = useState(null);
|
|
22
|
+
const [providerId, setProviderId] = useState(null);
|
|
23
|
+
const [error, setError] = useState('');
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const loadConfig = async () => {
|
|
26
|
+
const config = await readConfig();
|
|
27
|
+
if (config) {
|
|
28
|
+
setSavedConfig(config);
|
|
29
|
+
setPhase('use-saved');
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
setPhase('select-provider');
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
void loadConfig();
|
|
36
|
+
}, []);
|
|
37
|
+
const providerItems = AI_PROVIDERS.map((p) => ({
|
|
38
|
+
label: p.label,
|
|
39
|
+
value: p.id,
|
|
40
|
+
description: p.envVar,
|
|
41
|
+
}));
|
|
42
|
+
const handleProviderSelect = (item) => {
|
|
43
|
+
setProviderId(item.value);
|
|
44
|
+
setPhase('enter-key');
|
|
45
|
+
};
|
|
46
|
+
const handleKeySubmit = async (key, selectedProviderId) => {
|
|
47
|
+
setPhase('validating');
|
|
48
|
+
setError('');
|
|
49
|
+
const result = await validateApiKey(selectedProviderId, key);
|
|
50
|
+
if (result === true) {
|
|
51
|
+
await writeConfig({ providerId: selectedProviderId, apiKey: key });
|
|
52
|
+
onComplete({ providerId: selectedProviderId, apiKey: key });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
setError(result);
|
|
56
|
+
setPhase('error');
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const handleUseSaved = async (item) => {
|
|
60
|
+
if (item.value === 'yes' && savedConfig) {
|
|
61
|
+
setPhase('validating');
|
|
62
|
+
const result = await validateApiKey(savedConfig.providerId, savedConfig.apiKey);
|
|
63
|
+
if (result === true) {
|
|
64
|
+
onComplete({ providerId: savedConfig.providerId, apiKey: savedConfig.apiKey });
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
setError(`Saved key is no longer valid: ${result}`);
|
|
68
|
+
setPhase('select-provider');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
setPhase('select-provider');
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const selectedProvider = providerId ? AI_PROVIDERS.find((p) => p.id === providerId) : null;
|
|
76
|
+
const savedProvider = savedConfig
|
|
77
|
+
? AI_PROVIDERS.find((p) => p.id === savedConfig.providerId)
|
|
78
|
+
: null;
|
|
79
|
+
return (_jsxs(Box, { flexDirection: "column", children: [phase === 'check-saved' && _jsx(Spinner, { label: "Checking for saved API key..." }), phase === 'use-saved' && savedConfig && savedProvider && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 2, children: _jsxs(Text, { color: colors.gray, children: [symbols.diamond, " Saved key: ", _jsx(Text, { color: colors.honey, children: savedProvider.label }), ' ', _jsxs(Text, { color: colors.grayDim, children: ["(", maskKey(savedConfig.apiKey), ")"] })] }) }), _jsx(SelectPrompt, { label: "Use saved API key?", items: [
|
|
80
|
+
{ label: 'Yes, use saved key', value: 'yes' },
|
|
81
|
+
{ label: 'No, enter a new key', value: 'no' },
|
|
82
|
+
], onSelect: (item) => {
|
|
83
|
+
void handleUseSaved(item);
|
|
84
|
+
} })] })), phase === 'select-provider' && (_jsxs(Box, { flexDirection: "column", children: [error !== '' && (_jsx(Box, { marginBottom: 1, marginLeft: 2, children: _jsxs(Text, { color: colors.red, children: [symbols.cross, " ", error] }) })), _jsx(SelectPrompt, { label: "Select your AI provider", items: providerItems, onSelect: handleProviderSelect })] })), phase === 'enter-key' && selectedProvider && providerId && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: colors.gray, children: [symbols.diamond, " Provider: ", _jsx(Text, { color: colors.honey, children: selectedProvider.label })] }) }), _jsx(TextPrompt, { label: `Enter your ${selectedProvider.envVar}`, placeholder: "sk-...", onSubmit: (key) => {
|
|
85
|
+
void handleKeySubmit(key, providerId);
|
|
86
|
+
}, validate: validateApiKeyFormat })] })), phase === 'validating' && _jsx(Spinner, { label: "Validating API key..." }), phase === 'error' && providerId && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: colors.red, children: [symbols.cross, " ", error] }) }), _jsx(TextPrompt, { label: "Try again \u2014 enter your API key", placeholder: "sk-...", onSubmit: (key) => {
|
|
87
|
+
void handleKeySubmit(key, providerId);
|
|
88
|
+
}, validate: validateApiKeyFormat })] }))] }));
|
|
89
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { TextPrompt } from '../../../../components/TextPrompt.js';
|
|
4
|
+
import { colors, symbols } from '../../../shared/theme.js';
|
|
5
|
+
export function AvatarStep({ agentName, onComplete }) {
|
|
6
|
+
const defaultUrl = `https://api.dicebear.com/9.x/bottts-neutral/svg?seed=${encodeURIComponent(agentName)}`;
|
|
7
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, marginLeft: 2, children: _jsxs(Text, { color: colors.gray, children: [symbols.diamond, " Default: ", _jsx(Text, { color: colors.honey, children: defaultUrl })] }) }), _jsx(TextPrompt, { label: "Avatar image URL (press Enter for default)", placeholder: defaultUrl, onSubmit: (val) => onComplete(val || defaultUrl), validate: (val) => {
|
|
8
|
+
if (!val) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (!val.startsWith('http://') && !val.startsWith('https://')) {
|
|
12
|
+
return 'Must start with http:// or https://';
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
} })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { Box, Text, useApp } from 'ink';
|
|
4
|
+
import { colors, symbols, border } from '../../../shared/theme.js';
|
|
5
|
+
export function DoneStep({ projectDir }) {
|
|
6
|
+
const { exit } = useApp();
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
exit();
|
|
9
|
+
}, []);
|
|
10
|
+
const termWidth = process.stdout.columns || 60;
|
|
11
|
+
const boxWidth = Math.min(termWidth - 4, 60);
|
|
12
|
+
const line = border.horizontal.repeat(boxWidth - 2);
|
|
13
|
+
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsx(Box, { children: _jsxs(Text, { color: colors.honey, children: [border.topLeft, line, border.topRight] }) }), _jsxs(Box, { children: [_jsx(Text, { color: colors.honey, children: border.vertical }), _jsx(Text, { children: " " }), _jsxs(Text, { color: colors.honey, bold: true, children: [symbols.hive, " Agent created successfully!"] }), _jsx(Text, { children: ' '.repeat(Math.max(0, boxWidth - 32)) }), _jsx(Text, { color: colors.honey, children: border.vertical })] }), _jsx(Box, { children: _jsxs(Text, { color: colors.honey, children: [border.bottomLeft, line, border.bottomRight] }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, marginLeft: 1, children: [_jsx(Text, { color: colors.white, bold: true, children: "Next steps:" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsxs(Text, { color: colors.gray, children: [' ', "1. ", _jsx(Text, { color: colors.white, children: "npx @zhive/cli@latest start" })] }) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: colors.grayDim, children: [' ', "Fine-tune SOUL.md and STRATEGY.md by chatting with your agent during"] }), _jsx(Text, { color: colors.grayDim, children: " a run, or edit them directly at:" }), _jsxs(Text, { color: colors.grayDim, children: [' ', _jsx(Text, { color: colors.white, children: projectDir })] })] })] })] }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { SelectPrompt } from '../../../../components/SelectPrompt.js';
|
|
5
|
+
import { MultiSelectPrompt, } from '../../../../components/MultiSelectPrompt.js';
|
|
6
|
+
import { TextPrompt } from '../../../../components/TextPrompt.js';
|
|
7
|
+
import { CharacterSummaryCard } from '../../../../components/CharacterSummaryCard.js';
|
|
8
|
+
import { PERSONALITY_OPTIONS, VOICE_OPTIONS, TRADING_STYLE_OPTIONS, PROJECT_CATEGORY_OPTIONS, SENTIMENT_OPTIONS, TIMEFRAME_OPTIONS, BIO_EXAMPLES, } from '../../presets/index.js';
|
|
9
|
+
import { colors, symbols } from '../../../shared/theme.js';
|
|
10
|
+
import { required, compose, maxLength } from '../validation.js';
|
|
11
|
+
function buildSelectItems(options, addCustom = false) {
|
|
12
|
+
const items = options.map((opt) => ({
|
|
13
|
+
label: opt.label,
|
|
14
|
+
value: opt.value,
|
|
15
|
+
description: opt.description,
|
|
16
|
+
}));
|
|
17
|
+
if (addCustom) {
|
|
18
|
+
items.push({ label: 'Custom...', value: '__custom__' });
|
|
19
|
+
}
|
|
20
|
+
return items;
|
|
21
|
+
}
|
|
22
|
+
const personalityItems = buildSelectItems(PERSONALITY_OPTIONS, true);
|
|
23
|
+
const voiceItems = buildSelectItems(VOICE_OPTIONS, true);
|
|
24
|
+
const tradingStyleItems = buildSelectItems(TRADING_STYLE_OPTIONS, true);
|
|
25
|
+
const categoryItems = buildSelectItems(PROJECT_CATEGORY_OPTIONS);
|
|
26
|
+
const sentimentItems = buildSelectItems(SENTIMENT_OPTIONS);
|
|
27
|
+
const timeframeItems = buildSelectItems(TIMEFRAME_OPTIONS);
|
|
28
|
+
export function IdentityStep({ agentName, onComplete }) {
|
|
29
|
+
const [subStep, setSubStep] = useState('personality');
|
|
30
|
+
const [personalityLabel, setPersonalityLabel] = useState('');
|
|
31
|
+
const [personality, setPersonality] = useState('');
|
|
32
|
+
const [tone, setTone] = useState('');
|
|
33
|
+
const [voiceStyle, setVoiceStyle] = useState('');
|
|
34
|
+
const [voiceLabel, setVoiceLabel] = useState('');
|
|
35
|
+
const [tradingStyle, setTradingStyle] = useState('');
|
|
36
|
+
const [tradingStyleLabel, setTradingStyleLabel] = useState('');
|
|
37
|
+
const [sectors, setSectors] = useState([]);
|
|
38
|
+
const [sectorsLabel, setSectorsLabel] = useState('');
|
|
39
|
+
const [sentiment, setSentiment] = useState('');
|
|
40
|
+
const [sentimentLabel, setSentimentLabel] = useState('');
|
|
41
|
+
const [timeframes, setTimeframes] = useState([]);
|
|
42
|
+
const [timeframesLabel, setTimeframesLabel] = useState('');
|
|
43
|
+
const handlePersonalitySelect = useCallback((item) => {
|
|
44
|
+
if (item.value === '__custom__') {
|
|
45
|
+
setSubStep('personality-custom');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const description = item.description ?? '';
|
|
49
|
+
const personalityValue = `${item.label} — ${description}`;
|
|
50
|
+
setPersonality(personalityValue);
|
|
51
|
+
setPersonalityLabel(item.label);
|
|
52
|
+
setSubStep('voice');
|
|
53
|
+
}, []);
|
|
54
|
+
const handlePersonalityCustom = useCallback((value) => {
|
|
55
|
+
setPersonality(value);
|
|
56
|
+
setPersonalityLabel(value);
|
|
57
|
+
setSubStep('voice');
|
|
58
|
+
}, []);
|
|
59
|
+
const handleVoiceSelect = useCallback((item) => {
|
|
60
|
+
if (item.value === '__custom__') {
|
|
61
|
+
setSubStep('voice-custom');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const voiceOption = VOICE_OPTIONS.find((v) => v.value === item.value);
|
|
65
|
+
setTone(voiceOption.tone);
|
|
66
|
+
setVoiceStyle(voiceOption.voiceStyle);
|
|
67
|
+
setVoiceLabel(item.label);
|
|
68
|
+
setSubStep('trading');
|
|
69
|
+
}, []);
|
|
70
|
+
const handleVoiceCustom = useCallback((value) => {
|
|
71
|
+
setTone(value);
|
|
72
|
+
setVoiceStyle(value);
|
|
73
|
+
setVoiceLabel(value);
|
|
74
|
+
setSubStep('trading');
|
|
75
|
+
}, []);
|
|
76
|
+
const handleTradingStyleSelect = useCallback((item) => {
|
|
77
|
+
if (item.value === '__custom__') {
|
|
78
|
+
setSubStep('trading-custom');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
setTradingStyle(item.value);
|
|
82
|
+
setTradingStyleLabel(item.label);
|
|
83
|
+
setSubStep('sectors');
|
|
84
|
+
}, []);
|
|
85
|
+
const handleTradingStyleCustom = useCallback((value) => {
|
|
86
|
+
setTradingStyle(value);
|
|
87
|
+
setTradingStyleLabel(value);
|
|
88
|
+
setSubStep('sectors');
|
|
89
|
+
}, []);
|
|
90
|
+
const handleSectors = useCallback((selected) => {
|
|
91
|
+
const values = selected.map((s) => s.value);
|
|
92
|
+
const labels = selected.map((s) => s.label);
|
|
93
|
+
setSectors(values);
|
|
94
|
+
const displayLabel = values.length === categoryItems.length ? 'All' : labels.join(', ');
|
|
95
|
+
setSectorsLabel(displayLabel);
|
|
96
|
+
setSubStep('sentiment');
|
|
97
|
+
}, []);
|
|
98
|
+
const handleSentimentSelect = useCallback((item) => {
|
|
99
|
+
setSentiment(item.value);
|
|
100
|
+
setSentimentLabel(item.label);
|
|
101
|
+
setSubStep('timeframe');
|
|
102
|
+
}, []);
|
|
103
|
+
const handleTimeframes = useCallback((selected) => {
|
|
104
|
+
const values = selected.map((s) => s.value);
|
|
105
|
+
const labels = selected.map((s) => s.label);
|
|
106
|
+
setTimeframes(values);
|
|
107
|
+
const displayLabel = values.length === timeframeItems.length ? 'All' : labels.join(', ');
|
|
108
|
+
setTimeframesLabel(displayLabel);
|
|
109
|
+
setSubStep('bio');
|
|
110
|
+
}, []);
|
|
111
|
+
const handleBio = useCallback((value) => {
|
|
112
|
+
const result = {
|
|
113
|
+
personality,
|
|
114
|
+
tone,
|
|
115
|
+
voiceStyle,
|
|
116
|
+
tradingStyle,
|
|
117
|
+
sectors,
|
|
118
|
+
sentiment,
|
|
119
|
+
timeframes,
|
|
120
|
+
bio: value,
|
|
121
|
+
};
|
|
122
|
+
onComplete(result);
|
|
123
|
+
}, [personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, onComplete]);
|
|
124
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(CharacterSummaryCard, { name: agentName, personality: personalityLabel || undefined, voice: voiceLabel || undefined, tradingStyle: tradingStyleLabel || undefined, sectors: sectorsLabel || undefined, sentiment: sentimentLabel || undefined, timeframe: timeframesLabel || undefined }), subStep === 'personality' && (_jsx(SelectPrompt, { label: "Choose a personality", items: personalityItems, onSelect: handlePersonalitySelect })), subStep === 'personality-custom' && (_jsx(TextPrompt, { label: "Describe your agent's personality", placeholder: "e.g. stoic realist with a dry wit", onSubmit: handlePersonalityCustom, validate: required('Personality') })), subStep === 'voice' && (_jsx(SelectPrompt, { label: "Choose a voice", items: voiceItems, onSelect: handleVoiceSelect })), subStep === 'voice-custom' && (_jsx(TextPrompt, { label: "Describe your agent's voice", placeholder: "e.g. writes like a bloomberg terminal on acid", onSubmit: handleVoiceCustom, validate: required('Voice') })), subStep === 'trading' && (_jsx(SelectPrompt, { label: "How does your agent evaluate signals?", items: tradingStyleItems, onSelect: handleTradingStyleSelect })), subStep === 'trading-custom' && (_jsx(TextPrompt, { label: "Describe your agent's trading style", placeholder: "e.g. combines on-chain data with sentiment analysis", onSubmit: handleTradingStyleCustom, validate: required('Trading style') })), subStep === 'sectors' && (_jsx(MultiSelectPrompt, { label: "Which categories should your agent trade?", items: categoryItems, onSubmit: handleSectors })), subStep === 'sentiment' && (_jsx(SelectPrompt, { label: "What's your agent's market sentiment?", items: sentimentItems, onSelect: handleSentimentSelect })), subStep === 'timeframe' && (_jsx(MultiSelectPrompt, { label: "Which timeframes should your agent participate in?", items: timeframeItems, onSubmit: handleTimeframes })), subStep === 'bio' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: [_jsxs(Text, { color: colors.grayDim, italic: true, children: [symbols.arrow, " Examples:"] }), BIO_EXAMPLES.map((example, i) => (_jsx(Box, { marginLeft: 2, marginTop: i > 0 ? 1 : 0, children: _jsxs(Text, { color: colors.grayDim, italic: true, children: [symbols.diamond, " ", `"${example}"`] }) }, i)))] }), _jsx(TextPrompt, { label: "Write your agent's bio", placeholder: `short bio for your ${personalityLabel} agent`, onSubmit: handleBio, maxLength: 1000, validate: compose(required('Bio'), maxLength(1000)) })] }))] }));
|
|
125
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import { TextPrompt } from '../../../../components/TextPrompt.js';
|
|
6
|
+
import { Spinner } from '../../../../components/Spinner.js';
|
|
7
|
+
import { colors, symbols } from '../../../shared/theme.js';
|
|
8
|
+
import { HIVE_API_URL } from '../../../../shared/config/constant.js';
|
|
9
|
+
import { agentName as validateAgentName } from '../validation.js';
|
|
10
|
+
const ADJECTIVES = [
|
|
11
|
+
'royal',
|
|
12
|
+
'golden',
|
|
13
|
+
'buzzy',
|
|
14
|
+
'honey',
|
|
15
|
+
'sweet',
|
|
16
|
+
'stung',
|
|
17
|
+
'waxed',
|
|
18
|
+
'bold',
|
|
19
|
+
'swift',
|
|
20
|
+
'wild',
|
|
21
|
+
'keen',
|
|
22
|
+
'warm',
|
|
23
|
+
'hazy',
|
|
24
|
+
'calm',
|
|
25
|
+
'busy',
|
|
26
|
+
'amber',
|
|
27
|
+
'pollen',
|
|
28
|
+
'nectar',
|
|
29
|
+
'floral',
|
|
30
|
+
'sunny',
|
|
31
|
+
'misty',
|
|
32
|
+
'fuzzy',
|
|
33
|
+
'striped',
|
|
34
|
+
'waggle',
|
|
35
|
+
'silent',
|
|
36
|
+
'fierce',
|
|
37
|
+
'humble',
|
|
38
|
+
'lunar',
|
|
39
|
+
'solar',
|
|
40
|
+
'bloomed',
|
|
41
|
+
'bullish',
|
|
42
|
+
'bearish',
|
|
43
|
+
'staked',
|
|
44
|
+
'minted',
|
|
45
|
+
'forked',
|
|
46
|
+
'based',
|
|
47
|
+
'degen',
|
|
48
|
+
'pumped',
|
|
49
|
+
'longed',
|
|
50
|
+
'shorted',
|
|
51
|
+
'bridged',
|
|
52
|
+
'pegged',
|
|
53
|
+
'hodl',
|
|
54
|
+
'mega',
|
|
55
|
+
'alpha',
|
|
56
|
+
'sigma',
|
|
57
|
+
'hyper',
|
|
58
|
+
'ultra',
|
|
59
|
+
'rapid',
|
|
60
|
+
'atomic',
|
|
61
|
+
];
|
|
62
|
+
const NOUNS = [
|
|
63
|
+
'bee',
|
|
64
|
+
'drone',
|
|
65
|
+
'queen',
|
|
66
|
+
'swarm',
|
|
67
|
+
'hive',
|
|
68
|
+
'comb',
|
|
69
|
+
'larva',
|
|
70
|
+
'pupa',
|
|
71
|
+
'sting',
|
|
72
|
+
'apiary',
|
|
73
|
+
'keeper',
|
|
74
|
+
'mead',
|
|
75
|
+
'pollen',
|
|
76
|
+
'nectar',
|
|
77
|
+
'propolis',
|
|
78
|
+
'colony',
|
|
79
|
+
'brood',
|
|
80
|
+
'waggle',
|
|
81
|
+
'cell',
|
|
82
|
+
'wax',
|
|
83
|
+
'bloom',
|
|
84
|
+
'blossom',
|
|
85
|
+
'hornet',
|
|
86
|
+
'bumble',
|
|
87
|
+
'worker',
|
|
88
|
+
'forager',
|
|
89
|
+
'scout',
|
|
90
|
+
'smoker',
|
|
91
|
+
'whale',
|
|
92
|
+
'bull',
|
|
93
|
+
'bear',
|
|
94
|
+
'shard',
|
|
95
|
+
'block',
|
|
96
|
+
'node',
|
|
97
|
+
'vault',
|
|
98
|
+
'ledger',
|
|
99
|
+
'oracle',
|
|
100
|
+
'miner',
|
|
101
|
+
'staker',
|
|
102
|
+
'bridge',
|
|
103
|
+
'token',
|
|
104
|
+
'chain',
|
|
105
|
+
'wick',
|
|
106
|
+
'candle',
|
|
107
|
+
'pump',
|
|
108
|
+
'moon',
|
|
109
|
+
'floor',
|
|
110
|
+
'whale',
|
|
111
|
+
];
|
|
112
|
+
function generateRandomName() {
|
|
113
|
+
const adjective = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
114
|
+
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)];
|
|
115
|
+
const number = Math.floor(Math.random() * 900) + 100;
|
|
116
|
+
const name = `${adjective}-${noun}-${number}`;
|
|
117
|
+
return name;
|
|
118
|
+
}
|
|
119
|
+
export function NameStep({ onComplete }) {
|
|
120
|
+
const [checking, setChecking] = useState(false);
|
|
121
|
+
const [error, setError] = useState('');
|
|
122
|
+
const placeholder = useMemo(() => generateRandomName(), []);
|
|
123
|
+
const handleSubmit = useCallback(async (name) => {
|
|
124
|
+
setChecking(true);
|
|
125
|
+
setError('');
|
|
126
|
+
try {
|
|
127
|
+
const apiUrl = HIVE_API_URL;
|
|
128
|
+
const response = await axios.get(`${apiUrl}/agent/check-name`, {
|
|
129
|
+
params: { name },
|
|
130
|
+
timeout: 3000,
|
|
131
|
+
});
|
|
132
|
+
if (!response.data.available) {
|
|
133
|
+
setError(`Name "${name}" is already taken`);
|
|
134
|
+
setChecking(false);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// best-effort: silently proceed if backend is unavailable
|
|
140
|
+
}
|
|
141
|
+
setChecking(false);
|
|
142
|
+
onComplete(name);
|
|
143
|
+
}, [onComplete]);
|
|
144
|
+
if (checking) {
|
|
145
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(Spinner, { label: "Checking name availability..." }) }));
|
|
146
|
+
}
|
|
147
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(TextPrompt, { label: "Enter your agent name", placeholder: placeholder, onSubmit: handleSubmit, validate: validateAgentName }), error !== '' && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: colors.red, children: [symbols.cross, " ", error] }) }))] }));
|
|
148
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { HoneycombLoader } from '../../../../components/HoneycombLoader.js';
|
|
5
|
+
import { colors, symbols } from '../../../shared/theme.js';
|
|
6
|
+
import { scaffoldProject } from '../../generate.js';
|
|
7
|
+
import { extractErrorMessage } from '../../../../shared/agent/utils.js';
|
|
8
|
+
export function ScaffoldStep({ projectName, provider, apiKey, soulContent, strategyContent, onComplete, onError, }) {
|
|
9
|
+
const [steps, setSteps] = useState([]);
|
|
10
|
+
const [currentLabel, setCurrentLabel] = useState('Starting...');
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
let cancelled = false;
|
|
13
|
+
const run = async () => {
|
|
14
|
+
await scaffoldProject(projectName, provider, apiKey, soulContent, strategyContent, {
|
|
15
|
+
onStep: (label) => {
|
|
16
|
+
if (cancelled)
|
|
17
|
+
return;
|
|
18
|
+
setSteps((prev) => {
|
|
19
|
+
if (prev.length > 0) {
|
|
20
|
+
const updated = [...prev];
|
|
21
|
+
updated[updated.length - 1] = { ...updated[updated.length - 1], done: true };
|
|
22
|
+
return [...updated, { label, done: false }];
|
|
23
|
+
}
|
|
24
|
+
return [{ label, done: false }];
|
|
25
|
+
});
|
|
26
|
+
setCurrentLabel(label);
|
|
27
|
+
},
|
|
28
|
+
onDone: (projectDir) => {
|
|
29
|
+
if (cancelled)
|
|
30
|
+
return;
|
|
31
|
+
setSteps((prev) => {
|
|
32
|
+
if (prev.length > 0) {
|
|
33
|
+
const updated = [...prev];
|
|
34
|
+
updated[updated.length - 1] = { ...updated[updated.length - 1], done: true };
|
|
35
|
+
return updated;
|
|
36
|
+
}
|
|
37
|
+
return prev;
|
|
38
|
+
});
|
|
39
|
+
onComplete(projectDir);
|
|
40
|
+
},
|
|
41
|
+
onError: (message) => {
|
|
42
|
+
if (cancelled)
|
|
43
|
+
return;
|
|
44
|
+
onError(message);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
run().catch((err) => {
|
|
49
|
+
if (cancelled)
|
|
50
|
+
return;
|
|
51
|
+
const message = extractErrorMessage(err);
|
|
52
|
+
onError(message);
|
|
53
|
+
});
|
|
54
|
+
return () => {
|
|
55
|
+
cancelled = true;
|
|
56
|
+
};
|
|
57
|
+
}, [projectName, provider, apiKey, soulContent, strategyContent, onComplete, onError]);
|
|
58
|
+
return (_jsxs(Box, { flexDirection: "column", children: [steps.map((step, i) => (_jsx(Box, { marginLeft: 2, children: step.done ? (_jsxs(Text, { color: colors.green, children: [symbols.check, " ", step.label] })) : (_jsx(HoneycombLoader, { label: step.label })) }, i))), steps.length === 0 && (_jsx(Box, { marginLeft: 2, children: _jsx(HoneycombLoader, { label: currentLabel }) }))] }));
|
|
59
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { streamSoul } from '../../ai-generate.js';
|
|
4
|
+
import { StreamingGenerationStep } from './StreamingGenerationStep.js';
|
|
5
|
+
export function SoulStep({ providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, onComplete, }) {
|
|
6
|
+
const createStream = useCallback((feedback) => streamSoul(providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, feedback), [
|
|
7
|
+
providerId,
|
|
8
|
+
apiKey,
|
|
9
|
+
agentName,
|
|
10
|
+
bio,
|
|
11
|
+
avatarUrl,
|
|
12
|
+
personality,
|
|
13
|
+
tone,
|
|
14
|
+
voiceStyle,
|
|
15
|
+
tradingStyle,
|
|
16
|
+
sectors,
|
|
17
|
+
sentiment,
|
|
18
|
+
timeframes,
|
|
19
|
+
]);
|
|
20
|
+
return (_jsx(StreamingGenerationStep, { title: "SOUL.md", createStream: createStream, onComplete: onComplete }));
|
|
21
|
+
}
|