@zhive/cli 0.6.8 → 0.6.9
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.
|
@@ -4,12 +4,9 @@ import React from 'react';
|
|
|
4
4
|
import { showWelcome } from '../../shared/welcome.js';
|
|
5
5
|
import { CreateApp } from '../ui/CreateApp.js';
|
|
6
6
|
export const createCreateCommand = () => {
|
|
7
|
-
return new Command('create')
|
|
8
|
-
.description('Scaffold a new zHive agent')
|
|
9
|
-
.argument('<agent-name>', 'agent name')
|
|
10
|
-
.action(async (agentName) => {
|
|
7
|
+
return new Command('create').description('Scaffold a new zHive agent').action(async () => {
|
|
11
8
|
await showWelcome();
|
|
12
|
-
const { waitUntilExit } = render(React.createElement(CreateApp
|
|
9
|
+
const { waitUntilExit } = render(React.createElement(CreateApp));
|
|
13
10
|
await waitUntilExit();
|
|
14
11
|
});
|
|
15
12
|
};
|
|
@@ -2,16 +2,17 @@ import fs from 'fs-extra';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { getHiveDir } from '../../shared/config/constant.js';
|
|
5
|
+
import { registerAgent } from '@zhive/sdk';
|
|
5
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const __dirname = path.dirname(__filename);
|
|
7
|
-
export async function scaffoldProject(
|
|
8
|
+
export async function scaffoldProject({ agent, apiKey, callbacks, provider, soulContent, strategyContent, }) {
|
|
8
9
|
// Validate project name to prevent path traversal / command injection
|
|
9
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(
|
|
10
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(agent.name)) {
|
|
10
11
|
callbacks.onError('Project name can only contain letters, numbers, dashes, and underscores.');
|
|
11
12
|
return;
|
|
12
13
|
}
|
|
13
14
|
const agentsDir = path.join(getHiveDir(), 'agents');
|
|
14
|
-
const projectDir = path.join(agentsDir,
|
|
15
|
+
const projectDir = path.join(agentsDir, agent.name);
|
|
15
16
|
// Ensure resolved path is still inside the agents directory
|
|
16
17
|
const normalizedProjectDir = path.resolve(projectDir);
|
|
17
18
|
const normalizedAgentsDir = path.resolve(agentsDir);
|
|
@@ -50,24 +51,19 @@ export async function scaffoldProject(projectName, provider, apiKey, soulContent
|
|
|
50
51
|
const envContent = `${provider.envVar}="${apiKey}"
|
|
51
52
|
`;
|
|
52
53
|
await fs.writeFile(path.join(projectDir, '.env'), envContent, { encoding: 'utf-8', mode: 0o600 });
|
|
53
|
-
// 4.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
scripts: {
|
|
60
|
-
start: 'npx @zhive/cli@latest start',
|
|
54
|
+
// 4. register agent
|
|
55
|
+
await registerAgent({
|
|
56
|
+
agent_profile: {
|
|
57
|
+
sectors: agent.sectors,
|
|
58
|
+
sentiment: agent.sentiment,
|
|
59
|
+
timeframes: agent.timeframes,
|
|
61
60
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
await fs.copy(templateSkillsDir, projectSkillsDir);
|
|
71
|
-
}
|
|
72
|
-
callbacks.onDone(normalizedProjectDir);
|
|
61
|
+
name: agent.name,
|
|
62
|
+
avatar_url: agent.avatarUrl,
|
|
63
|
+
bio: agent.bio,
|
|
64
|
+
}, normalizedProjectDir)
|
|
65
|
+
.then(() => callbacks.onDone(normalizedProjectDir))
|
|
66
|
+
.catch((err) => {
|
|
67
|
+
callbacks.onError(err);
|
|
68
|
+
});
|
|
73
69
|
}
|
|
@@ -106,7 +106,7 @@ const STEP_LABELS = {
|
|
|
106
106
|
const STEP_DEFS = STEP_ORDER.map((s) => ({ key: s, label: STEP_LABELS[s] }));
|
|
107
107
|
export function CreateApp({ initialName }) {
|
|
108
108
|
const { exit } = useApp();
|
|
109
|
-
const [step, setStep] = useState(
|
|
109
|
+
const [step, setStep] = useState('name');
|
|
110
110
|
const [providerId, setProviderId] = useState(null);
|
|
111
111
|
const [apiKey, setApiKey] = useState('');
|
|
112
112
|
const [agentName, setAgentName] = useState(initialName ?? '');
|
|
@@ -167,5 +167,5 @@ export function CreateApp({ initialName }) {
|
|
|
167
167
|
setError(message);
|
|
168
168
|
exit();
|
|
169
169
|
}, [exit]);
|
|
170
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsx(StepIndicator, { steps: STEP_DEFS, currentIndex: stepIndex }), 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] }) }))] }));
|
|
170
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsx(StepIndicator, { steps: STEP_DEFS, currentIndex: stepIndex }), 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, bio: bio, sectors: sectors, timeframes: timeframes, avatarUrl: avatarUrl, sentiment: sentiment, 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] }) }))] }));
|
|
171
171
|
}
|
|
@@ -5,13 +5,13 @@ import { HoneycombLoader } from '../../../../components/HoneycombLoader.js';
|
|
|
5
5
|
import { colors, symbols } from '../../../shared/theme.js';
|
|
6
6
|
import { scaffoldProject } from '../../generate.js';
|
|
7
7
|
import { extractErrorMessage } from '../../../../shared/agent/utils.js';
|
|
8
|
-
export function ScaffoldStep({ projectName, provider, apiKey, soulContent, strategyContent, onComplete, onError, }) {
|
|
8
|
+
export function ScaffoldStep({ projectName, provider, apiKey, soulContent, strategyContent, onComplete, avatarUrl, sectors, sentiment, timeframes, bio, onError, }) {
|
|
9
9
|
const [steps, setSteps] = useState([]);
|
|
10
10
|
const [currentLabel, setCurrentLabel] = useState('Starting...');
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
let cancelled = false;
|
|
13
13
|
const run = async () => {
|
|
14
|
-
|
|
14
|
+
const callbacks = {
|
|
15
15
|
onStep: (label) => {
|
|
16
16
|
if (cancelled)
|
|
17
17
|
return;
|
|
@@ -43,6 +43,21 @@ export function ScaffoldStep({ projectName, provider, apiKey, soulContent, strat
|
|
|
43
43
|
return;
|
|
44
44
|
onError(message);
|
|
45
45
|
},
|
|
46
|
+
};
|
|
47
|
+
await scaffoldProject({
|
|
48
|
+
agent: {
|
|
49
|
+
name: projectName,
|
|
50
|
+
avatarUrl: avatarUrl,
|
|
51
|
+
bio,
|
|
52
|
+
sectors,
|
|
53
|
+
sentiment,
|
|
54
|
+
timeframes,
|
|
55
|
+
},
|
|
56
|
+
callbacks,
|
|
57
|
+
provider,
|
|
58
|
+
apiKey,
|
|
59
|
+
soulContent,
|
|
60
|
+
strategyContent,
|
|
46
61
|
});
|
|
47
62
|
};
|
|
48
63
|
run().catch((err) => {
|
|
@@ -19,7 +19,7 @@ const megathreadPredictionSchema = z.object({
|
|
|
19
19
|
summary: z
|
|
20
20
|
.string()
|
|
21
21
|
.min(1)
|
|
22
|
-
.max(
|
|
22
|
+
.max(300)
|
|
23
23
|
.nullable()
|
|
24
24
|
.describe('Your CT-style take on this project. Short, punchy, in character. Think tweet, not essay. null if skipping.'),
|
|
25
25
|
conviction: z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhive/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "CLI for bootstrapping zHive AI Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@ai-sdk/openai": "^3.0.25",
|
|
32
32
|
"@ai-sdk/xai": "^3.0.0",
|
|
33
33
|
"@openrouter/ai-sdk-provider": "^0.4.0",
|
|
34
|
-
"@zhive/sdk": "^0.5.
|
|
34
|
+
"@zhive/sdk": "^0.5.8",
|
|
35
35
|
"ai": "^6.0.71",
|
|
36
36
|
"axios": "^1.6.0",
|
|
37
37
|
"chalk": "^5.3.0",
|