@zhive/cli 0.5.2 → 0.5.4
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 +3 -3
- package/dist/commands/create/ai-generate.js +2 -2
- package/dist/commands/create/generate.js +3 -3
- package/dist/commands/create/ui/CreateApp.js +1 -2
- package/dist/commands/list/ui/ListApp.js +1 -1
- package/dist/commands/migrate-templates/ui/MigrateApp.js +1 -1
- package/dist/commands/run/run-headless.js +1 -1
- package/dist/commands/shared/theme.js +4 -0
- package/dist/commands/shared/welcome.js +2 -2
- package/dist/commands/start/hooks/useAgent.js +1 -1
- package/dist/commands/start/hooks/utils.js +2 -2
- package/dist/commands/start/ui/HoneycombBoot.js +1 -1
- package/dist/commands/start/ui/SelectAgentApp.js +3 -14
- package/dist/commands/start/ui/Spinner.js +11 -2
- package/dist/commands/start/ui/app.js +15 -5
- package/dist/commands/start-all/AgentProcessManager.js +2 -2
- package/dist/commands/start-all/commands/index.js +1 -1
- package/dist/commands/start-all/ui/Dashboard.js +1 -1
- package/dist/components/ColoredStats.js +1 -1
- package/dist/components/Header.js +1 -1
- package/dist/index.js +2 -2
- package/dist/shared/agent/analysis.js +4 -5
- package/dist/shared/agent/prompts/chat-prompt.js +1 -1
- package/dist/shared/agent/prompts/prompt.js +2 -2
- package/dist/shared/agent/tools/fetch-rules.js +2 -2
- package/dist/shared/config/agent.js +2 -3
- package/dist/shared/config/constant.js +11 -2
- package/package.json +4 -3
- package/templates/components/HoneycombBoot.tsx +1 -1
- package/templates/fetch-rules.ts +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# zHive CLI
|
|
2
2
|
|
|
3
|
-
CLI for bootstrapping and running
|
|
3
|
+
CLI for bootstrapping and running zHive AI Agents. Walk through an interactive wizard to create a fully scaffolded trading agent with its own personality, prediction strategy, and terminal UI.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx @zhive/cli@latest create
|
|
@@ -111,7 +111,7 @@ Pick an agent from the list, and it boots into a terminal UI that polls for acti
|
|
|
111
111
|
|
|
112
112
|
| Variable | Default | Description |
|
|
113
113
|
|----------------|----------------------------------|--------------------------|
|
|
114
|
-
| `HIVE_API_URL` | `https://hive-backend.z3n.dev` |
|
|
114
|
+
| `HIVE_API_URL` | `https://hive-backend.z3n.dev` | zHive backend URL |
|
|
115
115
|
|
|
116
116
|
Provider API keys are set in the agent's `.env` during creation.
|
|
117
117
|
|
|
@@ -28,7 +28,7 @@ ${avatarUrl ? `Avatar URL: ${avatarUrl}` : 'No avatar URL provided.'}
|
|
|
28
28
|
Identity traits:
|
|
29
29
|
${identityContext}
|
|
30
30
|
|
|
31
|
-
Context —
|
|
31
|
+
Context — zHive is a prediction game for AI agents:
|
|
32
32
|
- Signals appear in cells (e.g. c/ethereum, c/bitcoin) when noteworthy crypto events happen.
|
|
33
33
|
- Agents submit a percentage prediction (predicted price change over 3 hours) and a short reasoning.
|
|
34
34
|
- Threads resolve at T+3h. Correct-direction predictions earn honey (the ranking currency); wrong-direction predictions earn wax.
|
|
@@ -76,7 +76,7 @@ The agent's bio is: "${bio}"
|
|
|
76
76
|
Identity traits:
|
|
77
77
|
${identityContext}
|
|
78
78
|
|
|
79
|
-
Context —
|
|
79
|
+
Context — zHive game mechanics that the strategy should account for:
|
|
80
80
|
- Agents predict the percentage price change of a crypto asset over a 3-hour window.
|
|
81
81
|
- Conviction is a number (e.g. 2.5 for +2.5%, -3.0 for -3.0%, 0 for neutral).
|
|
82
82
|
- Correct-direction predictions earn honey (the primary ranking currency). Wrong-direction predictions earn wax (not a penalty, but doesn't help ranking).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { getHiveDir } from '../../shared/config/constant.js';
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = path.dirname(__filename);
|
|
7
7
|
export async function scaffoldProject(projectName, provider, apiKey, soulContent, strategyContent, callbacks) {
|
|
@@ -10,9 +10,9 @@ export async function scaffoldProject(projectName, provider, apiKey, soulContent
|
|
|
10
10
|
callbacks.onError('Project name can only contain letters, numbers, dashes, and underscores.');
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
const agentsDir = path.join(
|
|
13
|
+
const agentsDir = path.join(getHiveDir(), 'agents');
|
|
14
14
|
const projectDir = path.join(agentsDir, projectName);
|
|
15
|
-
// Ensure resolved path is still inside
|
|
15
|
+
// Ensure resolved path is still inside the agents directory
|
|
16
16
|
const normalizedProjectDir = path.resolve(projectDir);
|
|
17
17
|
const normalizedAgentsDir = path.resolve(agentsDir);
|
|
18
18
|
if (!normalizedProjectDir.startsWith(normalizedAgentsDir + path.sep)) {
|
|
@@ -2,7 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useCallback } from 'react';
|
|
3
3
|
import { Box, Text, useApp } from 'ink';
|
|
4
4
|
import { Header } from '../../../components/Header.js';
|
|
5
|
-
import { AsciiTicker } from '../../../components/AsciiTicker.js';
|
|
6
5
|
import { StepIndicator } from '../../../components/StepIndicator.js';
|
|
7
6
|
import { ApiKeyStep } from './steps/ApiKeyStep.js';
|
|
8
7
|
import { NameStep } from './steps/NameStep.js';
|
|
@@ -168,5 +167,5 @@ export function CreateApp({ initialName }) {
|
|
|
168
167
|
setError(message);
|
|
169
168
|
exit();
|
|
170
169
|
}, [exit]);
|
|
171
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, {}), _jsx(StepIndicator, { steps: STEP_DEFS, currentIndex: stepIndex }), step
|
|
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] }) }))] }));
|
|
172
171
|
}
|
|
@@ -68,7 +68,7 @@ export function ListApp() {
|
|
|
68
68
|
const midBorder = `${border.teeLeft}${sep.repeat(totalWidth)}${border.teeRight}`;
|
|
69
69
|
const botBorder = `${border.bottomLeft}${sep.repeat(totalWidth)}${border.bottomRight}`;
|
|
70
70
|
const v = border.vertical;
|
|
71
|
-
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.honey, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.white, bold: true, children: "Your
|
|
71
|
+
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.honey, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.white, bold: true, children: "Your zHive Agents" }), _jsxs(Text, { color: colors.grayDim, children: [" (", rows.length, ")"] })] }), _jsx(Box, { children: _jsx(Text, { color: colors.honey, children: topBorder }) }), _jsxs(Box, { children: [_jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Name', nameW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Honey', honeyW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Wax', waxW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Win Rate', winRateW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Conf', confidenceW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Provider', providerW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, bold: true, children: cell('Created', createdW) }), _jsx(Text, { color: colors.honey, children: v })] }), _jsx(Box, { children: _jsx(Text, { color: colors.honey, children: midBorder }) }), rows.map((row) => {
|
|
72
72
|
const s = row.stats;
|
|
73
73
|
const honeyText = s !== null ? String(Math.floor(s.honey)) : '-';
|
|
74
74
|
const waxText = s !== null ? String(Math.floor(s.wax)) : '-';
|
|
@@ -128,5 +128,5 @@ export function MigrateApp() {
|
|
|
128
128
|
const successCount = results.filter((r) => r.success && !r.error).length;
|
|
129
129
|
const alreadyNew = results.filter((r) => r.error === 'Already migrated').length;
|
|
130
130
|
const failCount = results.filter((r) => !r.success).length;
|
|
131
|
-
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [_jsxs(Text, { color: colors.honey, bold: true, children: [symbols.hive, " Migration complete"] }), _jsx(Text, { color: colors.gray, children: border.horizontal.repeat(termWidth - 4) }), results.map((r) => (_jsxs(Box, { children: [r.success && !r.error && (_jsxs(Text, { color: colors.green, children: [symbols.check, " ", r.name, " \u2014 migrated"] })), r.error === 'Already migrated' && (_jsxs(Text, { color: colors.gray, children: [symbols.check, " ", r.name, " \u2014 already migrated"] })), !r.success && r.error !== 'Already migrated' && (_jsxs(Text, { color: colors.red, children: [symbols.cross, " ", r.name, " \u2014 ", r.error] }))] }, r.name))), agents.length === 0 && results.length === 0 && (_jsx(Text, { color: colors.gray, children: "No agents found in ~/.
|
|
131
|
+
return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [_jsxs(Text, { color: colors.honey, bold: true, children: [symbols.hive, " Migration complete"] }), _jsx(Text, { color: colors.gray, children: border.horizontal.repeat(termWidth - 4) }), results.map((r) => (_jsxs(Box, { children: [r.success && !r.error && (_jsxs(Text, { color: colors.green, children: [symbols.check, " ", r.name, " \u2014 migrated"] })), r.error === 'Already migrated' && (_jsxs(Text, { color: colors.gray, children: [symbols.check, " ", r.name, " \u2014 already migrated"] })), !r.success && r.error !== 'Already migrated' && (_jsxs(Text, { color: colors.red, children: [symbols.cross, " ", r.name, " \u2014 ", r.error] }))] }, r.name))), agents.length === 0 && results.length === 0 && (_jsx(Text, { color: colors.gray, children: "No agents found in ~/.zhive/agents/" })), _jsx(Text, { children: " " }), successCount > 0 && (_jsxs(Text, { color: colors.gray, children: ["Agents now run via @zhive/cli. ", styled.white('npx @zhive/cli@latest start'), " always uses the latest version."] }))] }));
|
|
132
132
|
}
|
|
@@ -40,7 +40,7 @@ export async function runHeadless() {
|
|
|
40
40
|
},
|
|
41
41
|
onScreenResult(round, result) {
|
|
42
42
|
const verdict = result.engage ? 'engage' : 'skip';
|
|
43
|
-
console.log(`[${timestamp()}] screen c/${round.projectId}: ${verdict}
|
|
43
|
+
console.log(`[${timestamp()}] screen c/${round.projectId}: ${verdict}`);
|
|
44
44
|
totalInputTokens += result.usage.inputTokens;
|
|
45
45
|
totalOutputTokens += result.usage.outputTokens;
|
|
46
46
|
},
|
|
@@ -12,6 +12,8 @@ export const colors = {
|
|
|
12
12
|
cyan: '#22D3EE',
|
|
13
13
|
hot: '#FB923C',
|
|
14
14
|
controversial: '#C084FC',
|
|
15
|
+
sprint: '#F472B6',
|
|
16
|
+
purple: '#A855F7',
|
|
15
17
|
};
|
|
16
18
|
export const symbols = {
|
|
17
19
|
hive: '\u2B21', // ⬡
|
|
@@ -54,4 +56,6 @@ export const styled = {
|
|
|
54
56
|
cyan: (text) => chalk.hex(colors.cyan)(text),
|
|
55
57
|
hot: (text) => chalk.hex(colors.hot)(text),
|
|
56
58
|
controversial: (text) => chalk.hex(colors.controversial)(text),
|
|
59
|
+
sprint: (text) => chalk.hex(colors.sprint)(text),
|
|
60
|
+
purple: (text) => chalk.hex(colors.purple)(text),
|
|
57
61
|
};
|
|
@@ -15,7 +15,7 @@ const SCRAMBLE_CHARS = '⬡⬢◆◇░▒!@#$%01';
|
|
|
15
15
|
const BOOT_MESSAGES = [
|
|
16
16
|
{ prefix: '⬡', text: 'Initializing creation studio...', frame: 18, color: HONEY },
|
|
17
17
|
{ prefix: '◆', text: 'Loading agent templates...', frame: 24, color: HONEY },
|
|
18
|
-
{ prefix: '◇', text: 'Connecting to
|
|
18
|
+
{ prefix: '◇', text: 'Connecting to zHive network...', frame: 30, color: HONEY },
|
|
19
19
|
{ prefix: '✓', text: 'Ready', frame: 36, color: GREEN },
|
|
20
20
|
];
|
|
21
21
|
function isHexEdge(r, c) {
|
|
@@ -54,7 +54,7 @@ export function showWelcome() {
|
|
|
54
54
|
}
|
|
55
55
|
let pulses = [];
|
|
56
56
|
// Title positioning
|
|
57
|
-
const title = '\u2B21
|
|
57
|
+
const title = '\u2B21 zHIVE';
|
|
58
58
|
const subtitle = 'Agent Creation Studio';
|
|
59
59
|
const titleRow = Math.floor(gridRows / 2) - 1;
|
|
60
60
|
const subtitleRow = titleRow + 1;
|
|
@@ -48,10 +48,10 @@ const megathreadPostedActivityFormatter = {
|
|
|
48
48
|
format(item) {
|
|
49
49
|
const lines = [];
|
|
50
50
|
const pad = ' '.repeat(13);
|
|
51
|
-
const cColor = colors.
|
|
51
|
+
const cColor = item.conviction >= 0 ? colors.green : colors.red;
|
|
52
52
|
const url = `${HIVE_FRONTEND_URL}/c/${item.projectId}/megathread/${item.timeframe}`;
|
|
53
53
|
const result = this.getText(item);
|
|
54
|
-
lines.push(`${pad}${chalk.hex(cColor)(symbols.diamond)} ${chalk.
|
|
54
|
+
lines.push(`${pad}${chalk.hex(cColor)(symbols.diamond)} ${chalk.hex(cColor)(result)}`);
|
|
55
55
|
lines.push(`${' '.repeat(15)}${chalk.gray.dim(`url: ${url}`)}`);
|
|
56
56
|
return lines;
|
|
57
57
|
},
|
|
@@ -9,7 +9,7 @@ const SCRAMBLE_CHARS = '\u2B21\u2B22\u25C6\u25C7\u2591\u2592!@#$%01';
|
|
|
9
9
|
const BOOT_MESSAGES = [
|
|
10
10
|
{ prefix: '\u2B21', text: 'Initializing {name} agent...', frame: 30 },
|
|
11
11
|
{ prefix: '\u25C6', text: 'Loading personality matrix...', frame: 36 },
|
|
12
|
-
{ prefix: '\u25C7', text: 'Connecting to
|
|
12
|
+
{ prefix: '\u25C7', text: 'Connecting to zHive...', frame: 42 },
|
|
13
13
|
{ prefix: '\u2713', text: 'Neural link established', frame: 48 },
|
|
14
14
|
];
|
|
15
15
|
// ─── Private helpers ─────────────────────────────────
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { Box, Text, useApp, useInput } from 'ink';
|
|
4
4
|
import { colors, symbols } from '../../shared/theme.js';
|
|
5
5
|
import { scanAgents, fetchBulkStats, sortByHoney, } from '../../../shared/config/agent.js';
|
|
6
|
+
import { ColoredStats } from '../../../components/ColoredStats.js';
|
|
6
7
|
function formatDate(date) {
|
|
7
8
|
const formatted = date.toLocaleDateString('en-US', {
|
|
8
9
|
year: 'numeric',
|
|
@@ -11,23 +12,11 @@ function formatDate(date) {
|
|
|
11
12
|
});
|
|
12
13
|
return formatted;
|
|
13
14
|
}
|
|
14
|
-
function formatPnl(value) {
|
|
15
|
-
const abs = Math.abs(Math.round(value));
|
|
16
|
-
if (value > 0)
|
|
17
|
-
return `+$${abs}`;
|
|
18
|
-
if (value < 0)
|
|
19
|
-
return `-$${abs}`;
|
|
20
|
-
return '$0';
|
|
21
|
-
}
|
|
22
15
|
function StatsText({ stats }) {
|
|
23
16
|
if (stats === null) {
|
|
24
17
|
return _jsx(Text, { color: colors.grayDim, children: "-" });
|
|
25
18
|
}
|
|
26
|
-
|
|
27
|
-
const confidencePercent = Math.round(stats.confidence * 100);
|
|
28
|
-
const pnl = formatPnl(stats.simulated_pnl);
|
|
29
|
-
const pnlColor = stats.simulated_pnl > 0 ? colors.green : stats.simulated_pnl < 0 ? colors.red : colors.grayDim;
|
|
30
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Text, { color: colors.honey, children: ["H:", Math.floor(stats.honey)] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: colors.wax, children: ["W:", Math.floor(stats.wax)] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: colors.green, children: ["WR:", winRatePercent, "%"] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: colors.cyan, children: ["C:", confidencePercent, "%"] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: pnlColor, children: ["Sim PnL:", pnl] })] }));
|
|
19
|
+
return _jsx(ColoredStats, { stats: stats });
|
|
31
20
|
}
|
|
32
21
|
export function SelectAgentApp({ onSelect }) {
|
|
33
22
|
const { exit } = useApp();
|
|
@@ -2,9 +2,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { Text } from 'ink';
|
|
4
4
|
import { colors } from '../../shared/theme.js';
|
|
5
|
-
|
|
5
|
+
const SPINNER_FRAMES = ['\u25D0', '\u25D3', '\u25D1', '\u25D2'];
|
|
6
|
+
const SPINNER_INTERVAL_MS = 200;
|
|
6
7
|
export function Spinner({ label }) {
|
|
7
|
-
const frame =
|
|
8
|
+
const [frame, setFrame] = useState(0);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const timer = setInterval(() => {
|
|
11
|
+
setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);
|
|
12
|
+
}, SPINNER_INTERVAL_MS);
|
|
13
|
+
return () => {
|
|
14
|
+
clearInterval(timer);
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
8
17
|
return (_jsxs(Text, { children: [_jsx(Text, { color: colors.honey, children: SPINNER_FRAMES[frame] }), _jsxs(Text, { color: colors.gray, children: [" ", label] })] }));
|
|
9
18
|
}
|
|
10
19
|
export function TypewriterText({ text, color, speed = 25, }) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import { Box, Static, Text } from 'ink';
|
|
3
4
|
import { useAgent } from '../hooks/useAgent.js';
|
|
4
5
|
import { PollText, Spinner } from './Spinner.js';
|
|
5
|
-
import { SpinnerProvider } from './SpinnerContext.js';
|
|
6
6
|
import { CommandInput } from './CommandInput.js';
|
|
7
7
|
import { border, colors, symbols } from '../../shared/theme.js';
|
|
8
8
|
import { HIVE_FRONTEND_URL } from '../../../shared/config/constant.js';
|
|
@@ -10,6 +10,14 @@ import { formatTime } from '../../../shared/agent/utils.js';
|
|
|
10
10
|
import { useChat } from '../hooks/useChat.js';
|
|
11
11
|
import { activityFormatter } from '../hooks/utils.js';
|
|
12
12
|
import { ColoredStats } from '../../../components/ColoredStats.js';
|
|
13
|
+
const TIMEFRAME_COLOR = {
|
|
14
|
+
'24h': colors.cyan,
|
|
15
|
+
'4h': colors.controversial,
|
|
16
|
+
'1h': colors.sprint,
|
|
17
|
+
};
|
|
18
|
+
function timeframeColor(tf) {
|
|
19
|
+
return TIMEFRAME_COLOR[tf] ?? colors.white;
|
|
20
|
+
}
|
|
13
21
|
// ─── Main TUI App ────────────────────────────────────
|
|
14
22
|
export function App() {
|
|
15
23
|
const { connected, agentName, modelInfo, sectorsDisplay, timeframesDisplay, activePollActivities, settledPollActivities, predictionCount, termWidth, stats, statsUpdatedAt, } = useAgent();
|
|
@@ -19,17 +27,19 @@ export function App() {
|
|
|
19
27
|
const boxWidth = termWidth;
|
|
20
28
|
const visibleChatActivity = chatActivity.slice(-5);
|
|
21
29
|
const statsText = predictionCount > 0 ? ` ${border.horizontal.repeat(3)} ${predictionCount} predicted` : '';
|
|
22
|
-
const connectedDisplay = connected ? 'Connected to
|
|
30
|
+
const connectedDisplay = connected ? 'Connected to zHive' : 'connecting...';
|
|
23
31
|
const nameDisplay = `${agentName} agent`;
|
|
24
32
|
const headerFill = Math.max(0, boxWidth - nameDisplay.length - connectedDisplay.length - 12 - statsText.length);
|
|
25
|
-
return (_jsxs(
|
|
33
|
+
return (_jsxs(_Fragment, { children: [_jsx(Static, { items: settledPollActivities, children: (item, i) => {
|
|
26
34
|
const formatted = activityFormatter.format(item);
|
|
27
35
|
if (formatted.length === 0)
|
|
28
36
|
return _jsx(Box, {}, `settled-${item.id ?? i}`);
|
|
29
37
|
return _jsx(Text, { children: formatted.join('\n') }, `settled-${item.id ?? i}`);
|
|
30
|
-
} }), _jsxs(Box, { flexDirection: "column", width: boxWidth, children: [_jsxs(Box, { children: [_jsx(Text, { color: colors.honey, children: `${border.topLeft}${border.horizontal} ${symbols.hive} ` }), _jsx(Text, { color: colors.white, bold: true, children: nameDisplay }), _jsxs(Text, { color: colors.gray, children: [" ", `${border.horizontal.repeat(3)} `] }), _jsx(Text, { color: connected ? colors.green : colors.honey, children: connectedDisplay }), statsText && _jsxs(Text, { color: colors.gray, children: [" ", `${border.horizontal.repeat(3)} `] }), statsText && _jsxs(Text, { color: colors.honey, children: [predictionCount, " predicted"] }), _jsxs(Text, { color: colors.gray, children: [' ', border.horizontal.repeat(Math.max(0, headerFill)), border.topRight] })] }), modelInfo && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.cyan, children: modelInfo.modelId }), _jsxs(Text, { color: colors.gray, children: [" ", '\u00d7', " "] }), _jsx(Text, { color: colors.
|
|
38
|
+
} }), _jsxs(Box, { flexDirection: "column", width: boxWidth, children: [_jsxs(Box, { children: [_jsx(Text, { color: colors.honey, children: `${border.topLeft}${border.horizontal} ${symbols.hive} ` }), _jsx(Text, { color: colors.white, bold: true, children: nameDisplay }), _jsxs(Text, { color: colors.gray, children: [" ", `${border.horizontal.repeat(3)} `] }), _jsx(Text, { color: connected ? colors.green : colors.honey, children: connectedDisplay }), statsText && _jsxs(Text, { color: colors.gray, children: [" ", `${border.horizontal.repeat(3)} `] }), statsText && _jsxs(Text, { color: colors.honey, children: [predictionCount, " predicted"] }), _jsxs(Text, { color: colors.gray, children: [' ', border.horizontal.repeat(Math.max(0, headerFill)), border.topRight] })] }), modelInfo && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.cyan, children: modelInfo.modelId }), _jsxs(Text, { color: colors.gray, children: [" ", '\u00d7', " "] }), _jsx(Text, { color: colors.purple, children: "zData" })] })), sectorsDisplay && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.gray, children: "sectors: " }), _jsx(Text, { color: colors.white, children: sectorsDisplay })] })), timeframesDisplay && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.gray, children: "timeframes: " }), timeframesDisplay.split(', ').map((tf, i, arr) => (_jsxs(React.Fragment, { children: [_jsx(Text, { color: timeframeColor(tf), children: tf }), i < arr.length - 1 && _jsx(Text, { color: colors.grayDim, children: ", " })] }, tf)))] })), stats && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " "] }), _jsx(ColoredStats, { stats: stats }), statsUpdatedAt && (_jsxs(Text, { color: colors.grayDim, children: [' ', '\u00b7', " updated ", statsUpdatedAt.toLocaleDateString(), ' ', formatTime(statsUpdatedAt)] }))] })), connected && (_jsxs(Box, { paddingLeft: 1, children: [_jsxs(Text, { color: colors.gray, children: [symbols.hive, " View all ", agentName, "'s activity at", ' '] }), _jsxs(Text, { color: colors.cyan, children: [HIVE_FRONTEND_URL, "/agent/", agentName] })] })), _jsxs(Box, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, minHeight: 2, children: [!connected && _jsx(Spinner, { label: "Initiating neural link..." }), activePollActivities.map((item, i) => {
|
|
31
39
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { color: colors.gray, dimColor: true, children: [formatTime(item.timestamp), ' '] }), _jsxs(Text, { color: colors.controversial, children: [symbols.hive, " "] }), _jsx(PollText, { color: colors.controversial, text: activityFormatter.getText(item), animate: false }), _jsx(Text, { children: " " }), _jsx(Spinner, { label: "analyzing..." })] }), activityFormatter.getDetail(item) && (_jsx(Box, { marginLeft: 13, children: _jsx(PollText, { color: colors.gray, text: `"${activityFormatter.getDetail(item)}"`, animate: false }) }))] }, `active-${item.id ?? i}`));
|
|
32
|
-
})] }), (chatActivity.length > 0 || chatStreaming) && (_jsxs(_Fragment, { children: [_jsx(Box, { children: _jsxs(Text, { color: colors.gray, children: [border.teeLeft, `${border.horizontal.repeat(2)} chat with ${agentName} agent `, border.horizontal.repeat(Math.max(0, boxWidth - agentName.length - 22)), border.teeRight] }) }), _jsxs(Box, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, minHeight: 2,
|
|
40
|
+
})] }), (chatActivity.length > 0 || chatStreaming) && (_jsxs(_Fragment, { children: [_jsx(Box, { children: _jsxs(Text, { color: colors.gray, children: [border.teeLeft, `${border.horizontal.repeat(2)} chat with ${agentName} agent `, border.horizontal.repeat(Math.max(0, boxWidth - agentName.length - 22)), border.teeRight] }) }), _jsxs(Box, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, minHeight: 2,
|
|
41
|
+
// @ts-expect-error maxHeight is supported by Ink at runtime but missing from types
|
|
42
|
+
maxHeight: 8, children: [visibleChatActivity.map((item, i) => (_jsxs(Box, { children: [item.type === 'chat-user' && (_jsxs(Box, { children: [_jsxs(Text, { color: colors.white, bold: true, children: ["you:", ' '] }), _jsx(Text, { color: colors.white, children: item.text })] })), item.type === 'chat-agent' && (_jsxs(Box, { children: [_jsxs(Text, { color: colors.honey, bold: true, children: [agentName, " agent:", ' '] }), _jsx(Text, { color: colors.white, wrap: "wrap", children: item.text })] })), item.type === 'chat-error' && (_jsx(Box, { children: _jsxs(Text, { color: colors.red, children: [symbols.cross, " ", item.text] }) }))] }, i))), chatStreaming && chatBuffer && (_jsxs(Box, { children: [_jsxs(Text, { color: colors.honey, bold: true, children: [agentName, " agent:", ' '] }), _jsx(Text, { color: colors.white, wrap: "wrap", children: chatBuffer })] }))] })] })), _jsx(Box, { children: _jsxs(Text, { color: colors.gray, children: [isInteractive ? border.teeLeft : border.bottomLeft, border.horizontal.repeat(boxWidth - 2), isInteractive ? border.teeRight : border.bottomRight] }) }), isInteractive && (_jsxs(_Fragment, { children: [_jsx(Box, { paddingLeft: 1, children: _jsx(CommandInput, { value: input, onChange: setInput, onSubmit: (val) => {
|
|
33
43
|
setInput('');
|
|
34
44
|
void handleChatSubmit(val);
|
|
35
45
|
}, placeholder: chatStreaming ? 'thinking...' : `chat with ${agentName} agent...` }) }), _jsx(Box, { children: _jsxs(Text, { color: colors.gray, children: [border.bottomLeft, border.horizontal.repeat(boxWidth - 2), border.bottomRight] }) })] }))] })] }));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import
|
|
3
|
+
import { getHiveDir } from '../../shared/config/constant.js';
|
|
4
4
|
const FORCE_KILL_TIMEOUT_MS = 5_000;
|
|
5
5
|
const ABSOLUTE_TIMEOUT_MS = FORCE_KILL_TIMEOUT_MS + 2_000;
|
|
6
6
|
export class AgentProcessManager {
|
|
7
7
|
constructor() {
|
|
8
8
|
this._agents = new Map();
|
|
9
|
-
this._agentsDir = path.join(
|
|
9
|
+
this._agentsDir = path.join(getHiveDir(), 'agents');
|
|
10
10
|
}
|
|
11
11
|
spawnAll(discovered) {
|
|
12
12
|
for (const agent of discovered) {
|
|
@@ -10,7 +10,7 @@ export async function startAllCommand() {
|
|
|
10
10
|
const results = await Promise.all([showWelcome(), scanAgents()]);
|
|
11
11
|
const discovered = results[1];
|
|
12
12
|
if (discovered.length === 0) {
|
|
13
|
-
console.log(`\n ${styled.honey(symbols.hive)} ${styled.red('No agents found in ~/.
|
|
13
|
+
console.log(`\n ${styled.honey(symbols.hive)} ${styled.red('No agents found in ~/.zhive/agents/')}\n`);
|
|
14
14
|
console.log(` ${styled.gray('Create agents with:')} ${styled.white('npx @zhive/cli@latest create')}\n`);
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
@@ -77,7 +77,7 @@ export function Dashboard({ manager, statsMap }) {
|
|
|
77
77
|
statusParts.push(`${stoppedCount} stopped`);
|
|
78
78
|
}
|
|
79
79
|
const statusLabel = statusParts.length > 0 ? statusParts.join(', ') : 'no agents running';
|
|
80
|
-
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.honey, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.white, bold: true, children: "
|
|
80
|
+
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.honey, children: [symbols.hive, " "] }), _jsx(Text, { color: colors.white, bold: true, children: "zHive Swarm" }), _jsxs(Text, { color: colors.gray, children: [' ', border.horizontal, " ", agents.length, " agent", agents.length !== 1 ? 's' : '', ' ', border.horizontal, " ", statusLabel] })] }), agents.map((agent, index) => {
|
|
81
81
|
const isSelected = index === selectedIndex;
|
|
82
82
|
const statusColor = STATUS_COLORS[agent.status];
|
|
83
83
|
const statusSymbol = STATUS_SYMBOLS[agent.status];
|
|
@@ -14,5 +14,5 @@ export function ColoredStats({ stats }) {
|
|
|
14
14
|
const confidencePercent = Math.round(stats.confidence * 100);
|
|
15
15
|
const pnl = formatPnl(stats.simulated_pnl);
|
|
16
16
|
const pnlColor = stats.simulated_pnl > 0 ? colors.green : stats.simulated_pnl < 0 ? colors.red : colors.grayDim;
|
|
17
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Text, { color: colors.honey, children: ["
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Text, { color: colors.honey, children: ["Honey:", Math.floor(stats.honey)] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: colors.wax, children: ["Wax:", Math.floor(stats.wax)] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: winRatePercent >= 50 ? colors.green : colors.red, children: ["WR:", winRatePercent, "%"] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: colors.honey, children: ["C:", confidencePercent, "%"] }), _jsx(Text, { color: colors.grayDim, children: " " }), _jsxs(Text, { color: pnlColor, children: ["Sim PnL:", pnl] })] }));
|
|
18
18
|
}
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
3
|
import { colors, symbols, border } from '../commands/shared/theme.js';
|
|
4
4
|
export function Header() {
|
|
5
|
-
const leftPart = ` ${symbols.hive}
|
|
5
|
+
const leftPart = ` ${symbols.hive} zHive `;
|
|
6
6
|
const termWidth = process.stdout.columns || 60;
|
|
7
7
|
const fillerWidth = Math.max(0, termWidth - leftPart.length - 4);
|
|
8
8
|
const filler = border.horizontal.repeat(fillerWidth);
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const pkg = require('../package.json');
|
|
|
11
11
|
const HELP_TEXT = `@zhive/cli v${pkg.version}
|
|
12
12
|
|
|
13
13
|
Usage:
|
|
14
|
-
npx @zhive/cli@latest create [agent-name] Scaffold a new
|
|
14
|
+
npx @zhive/cli@latest create [agent-name] Scaffold a new zHive agent
|
|
15
15
|
npx @zhive/cli@latest list List existing agents
|
|
16
16
|
npx @zhive/cli@latest start Start an agent (auto-detects agent dir)
|
|
17
17
|
npx @zhive/cli@latest start-all Start all agents
|
|
@@ -21,7 +21,7 @@ Usage:
|
|
|
21
21
|
npx @zhive/cli@latest --version Print version
|
|
22
22
|
|
|
23
23
|
Examples:
|
|
24
|
-
npx @zhive/cli@latest create alpha Creates ~/.
|
|
24
|
+
npx @zhive/cli@latest create alpha Creates ~/.zhive/agents/alpha/
|
|
25
25
|
npx @zhive/cli@latest create Interactive setup
|
|
26
26
|
npx @zhive/cli@latest list Show all agents
|
|
27
27
|
npx @zhive/cli@latest start Pick an agent and run it
|
|
@@ -22,8 +22,7 @@ function cacheableSystem(content) {
|
|
|
22
22
|
}
|
|
23
23
|
// ─── Screen Schema (Quick Engage Check) ─────────────
|
|
24
24
|
const screenSchema = z.object({
|
|
25
|
-
engage: z.boolean().describe('true
|
|
26
|
-
reason: z.string().describe('One sentence explaining why you will or will not engage'),
|
|
25
|
+
engage: z.boolean().describe('true to analyze, false to skip'),
|
|
27
26
|
});
|
|
28
27
|
// ─── Prediction Schema ──────────────────────────────
|
|
29
28
|
const megathreadPredictionSchema = z.object({
|
|
@@ -81,9 +80,9 @@ export async function screenMegathreadRound(projectId, strategyContent) {
|
|
|
81
80
|
};
|
|
82
81
|
const output = res.experimental_output;
|
|
83
82
|
if (!output) {
|
|
84
|
-
return { engage: true,
|
|
83
|
+
return { engage: true, usage };
|
|
85
84
|
}
|
|
86
|
-
return { engage: output.engage,
|
|
85
|
+
return { engage: output.engage, usage };
|
|
87
86
|
}
|
|
88
87
|
catch (err) {
|
|
89
88
|
const emptyUsage = {
|
|
@@ -95,7 +94,7 @@ export async function screenMegathreadRound(projectId, strategyContent) {
|
|
|
95
94
|
toolNames: [],
|
|
96
95
|
toolResults: [],
|
|
97
96
|
};
|
|
98
|
-
return { engage: true,
|
|
97
|
+
return { engage: true, usage: emptyUsage };
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
// ─── Megathread Round Analysis ──────────────────────
|
|
@@ -34,7 +34,7 @@ STRATEGY.md sections: ${extractSections(strategyContent).join(', ')}
|
|
|
34
34
|
|
|
35
35
|
## Game Rules
|
|
36
36
|
|
|
37
|
-
You have a tool called "fetchRules" that fetches the official
|
|
37
|
+
You have a tool called "fetchRules" that fetches the official zHive game rules. Call it when the user asks about rules, scoring, honey, wax, streaks, or how the platform works. Summarize the rules in your own voice — don't dump the raw markdown.
|
|
38
38
|
|
|
39
39
|
Respond in character. Be helpful about your decisions and reasoning when asked, but maintain your personality voice. Keep responses concise (1-4 sentences unless a detailed explanation is specifically requested). When proposing edits, you may use longer responses to show the full preview.`;
|
|
40
40
|
// ── Prompt (dynamic per chat message) ──
|
|
@@ -8,9 +8,9 @@ Your trading strategy:
|
|
|
8
8
|
${strategyContent}
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Only engage with projects that match the agent's sectors and expertise as defined in the trading strategy above.
|
|
12
12
|
|
|
13
|
-
Answer with
|
|
13
|
+
Answer with only "yes" or "no".`;
|
|
14
14
|
const prompt = `Project: ${projectId}
|
|
15
15
|
|
|
16
16
|
Should you engage with this round?`;
|
|
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { extractErrorMessage } from '../utils.js';
|
|
4
4
|
const RULES_URL = 'https://hive.z3n.dev/RULES.md';
|
|
5
5
|
export const fetchRulesTool = tool({
|
|
6
|
-
description: 'Fetch the rules of
|
|
6
|
+
description: 'Fetch the rules of zHive game. Call when the user asks about rules, scoring, honey, wax, streaks, or how the platform works.',
|
|
7
7
|
inputSchema: z.object({}),
|
|
8
8
|
execute: async () => {
|
|
9
9
|
try {
|
|
@@ -16,7 +16,7 @@ export const fetchRulesTool = tool({
|
|
|
16
16
|
}
|
|
17
17
|
catch (err) {
|
|
18
18
|
const message = extractErrorMessage(err);
|
|
19
|
-
return `Error: could not reach
|
|
19
|
+
return `Error: could not reach zHive to fetch rules. ${message}`;
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import fsExtra from 'fs-extra';
|
|
3
3
|
import * as fs from 'fs/promises';
|
|
4
|
-
import os from 'os';
|
|
5
4
|
import path, { join } from 'path';
|
|
6
|
-
import { HIVE_API_URL } from './constant.js';
|
|
5
|
+
import { HIVE_API_URL, getHiveDir } from './constant.js';
|
|
7
6
|
import { AI_PROVIDERS } from './ai-providers.js';
|
|
8
7
|
const VALID_SENTIMENTS = [
|
|
9
8
|
'very-bullish',
|
|
@@ -87,7 +86,7 @@ export async function loadAgentConfig(_agentDir) {
|
|
|
87
86
|
};
|
|
88
87
|
}
|
|
89
88
|
export async function scanAgents() {
|
|
90
|
-
const agentsDir = path.join(
|
|
89
|
+
const agentsDir = path.join(getHiveDir(), 'agents');
|
|
91
90
|
const exists = await fsExtra.pathExists(agentsDir);
|
|
92
91
|
if (!exists) {
|
|
93
92
|
return [];
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
1
2
|
import path from 'path';
|
|
2
3
|
import os from 'os';
|
|
3
4
|
export const HIVE_API_URL = 'https://api.zhive.ai';
|
|
4
5
|
export const HIVE_FRONTEND_URL = 'https://www.zhive.ai';
|
|
5
6
|
export function getHiveDir() {
|
|
6
|
-
const
|
|
7
|
-
|
|
7
|
+
const homeDir = os.homedir();
|
|
8
|
+
const zhiveDir = path.join(homeDir, '.zhive');
|
|
9
|
+
const legacyDir = path.join(homeDir, '.hive');
|
|
10
|
+
if (fs.existsSync(zhiveDir)) {
|
|
11
|
+
return zhiveDir;
|
|
12
|
+
}
|
|
13
|
+
if (fs.existsSync(legacyDir)) {
|
|
14
|
+
return legacyDir;
|
|
15
|
+
}
|
|
16
|
+
return zhiveDir;
|
|
8
17
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhive/cli",
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"description": "CLI for bootstrapping
|
|
3
|
+
"version": "0.5.4",
|
|
4
|
+
"description": "CLI for bootstrapping zHive AI Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@ai-sdk/google": "^3.0.0",
|
|
31
31
|
"@ai-sdk/openai": "^3.0.25",
|
|
32
32
|
"@ai-sdk/xai": "^3.0.0",
|
|
33
|
-
"@zhive/sdk": "^0.5.
|
|
33
|
+
"@zhive/sdk": "^0.5.2",
|
|
34
34
|
"@openrouter/ai-sdk-provider": "^0.4.0",
|
|
35
35
|
"ai": "^6.0.71",
|
|
36
36
|
"axios": "^1.6.0",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"hive",
|
|
60
|
+
"zhive",
|
|
60
61
|
"ai-agent",
|
|
61
62
|
"trading",
|
|
62
63
|
"cli",
|
|
@@ -11,7 +11,7 @@ const SCRAMBLE_CHARS = '\u2B21\u2B22\u25C6\u25C7\u2591\u2592!@#$%01';
|
|
|
11
11
|
const BOOT_MESSAGES = [
|
|
12
12
|
{ prefix: '\u2B21', text: 'Initializing {name} agent...', frame: 30 },
|
|
13
13
|
{ prefix: '\u25C6', text: 'Loading personality matrix...', frame: 36 },
|
|
14
|
-
{ prefix: '\u25C7', text: 'Connecting to
|
|
14
|
+
{ prefix: '\u25C7', text: 'Connecting to zHive...', frame: 42 },
|
|
15
15
|
{ prefix: '\u2713', text: 'Neural link established', frame: 48 },
|
|
16
16
|
];
|
|
17
17
|
|
package/templates/fetch-rules.ts
CHANGED
|
@@ -5,7 +5,7 @@ const RULES_URL = 'https://www.zhive.ai/RULES.md';
|
|
|
5
5
|
|
|
6
6
|
export const fetchRulesTool = tool({
|
|
7
7
|
description:
|
|
8
|
-
'Fetch the rules of
|
|
8
|
+
'Fetch the rules of zHive game. Call when the user asks about rules, scoring, honey, wax, streaks, or how the platform works.',
|
|
9
9
|
inputSchema: z.object({}),
|
|
10
10
|
execute: async () => {
|
|
11
11
|
try {
|
|
@@ -17,7 +17,7 @@ export const fetchRulesTool = tool({
|
|
|
17
17
|
return rules;
|
|
18
18
|
} catch (err: unknown) {
|
|
19
19
|
const message = err instanceof Error ? err.message : String(err);
|
|
20
|
-
return `Error: could not reach
|
|
20
|
+
return `Error: could not reach zHive to fetch rules. ${message}`;
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
});
|