@zhive/cli 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/CLAUDE.md +7 -0
  2. package/dist/backtest/CLAUDE.md +7 -0
  3. package/dist/cli.js +20 -0
  4. package/dist/commands/agent/commands/profile.js +3 -2
  5. package/dist/commands/agent/commands/profile.test.js +10 -12
  6. package/dist/commands/doctor/commands/index.js +93 -0
  7. package/dist/commands/megathread/commands/create-comment.js +4 -9
  8. package/dist/commands/megathread/commands/create-comment.test.js +15 -173
  9. package/dist/commands/megathread/commands/create-comments.js +83 -0
  10. package/dist/commands/megathread/commands/index.js +2 -0
  11. package/dist/commands/megathread/commands/list.js +5 -5
  12. package/dist/commands/megathread/commands/list.test.js +14 -14
  13. package/dist/commands/start/commands/prediction.js +3 -4
  14. package/dist/commands/start/hooks/useChat.js +40 -41
  15. package/dist/commands/start/services/command-registry.js +1 -1
  16. package/dist/index.js +2 -0
  17. package/dist/{agent → services/agent}/analysis.js +5 -5
  18. package/dist/{load-agent-env.js → services/agent/env.js} +1 -1
  19. package/dist/{agent → services/agent/helpers}/model.js +2 -2
  20. package/dist/{agent → services/agent/prompts}/memory-prompt.js +20 -22
  21. package/dist/{agent → services/agent/prompts}/prompt.js +80 -54
  22. package/dist/{agent → services/agent}/tools/market/client.js +1 -1
  23. package/dist/{agent → services/agent}/tools/mindshare/client.js +1 -1
  24. package/dist/{agents.js → services/config/agent.js} +2 -2
  25. package/dist/{config.js → services/config/config.js} +1 -7
  26. package/dist/services/config/constant.js +8 -0
  27. package/dist/shared/agent/config.js +75 -0
  28. package/dist/shared/agent/env.js +30 -0
  29. package/dist/shared/agent/helpers/model.js +92 -0
  30. package/dist/shared/ai-providers.js +66 -0
  31. package/dist/shared/config/agent.js +0 -11
  32. package/dist/shared/config/agent.test.js +4 -35
  33. package/package.json +2 -2
  34. package/dist/agent/app.js +0 -122
  35. package/dist/agent/commands/registry.js +0 -12
  36. package/dist/agent/components/AsciiTicker.js +0 -81
  37. package/dist/agent/components/CommandInput.js +0 -65
  38. package/dist/agent/components/HoneycombBoot.js +0 -291
  39. package/dist/agent/components/Spinner.js +0 -37
  40. package/dist/agent/hooks/useAgent.js +0 -480
  41. package/dist/agent/objects.js +0 -1
  42. package/dist/agent/process-lifecycle.js +0 -18
  43. package/dist/agent/run-headless.js +0 -189
  44. package/dist/agent/theme.js +0 -41
  45. package/dist/avatar.js +0 -34
  46. package/dist/backtest/default-backtest-data.js +0 -200
  47. package/dist/backtest/fetch.js +0 -41
  48. package/dist/backtest/import.js +0 -106
  49. package/dist/backtest/index.js +0 -10
  50. package/dist/backtest/results.js +0 -113
  51. package/dist/backtest/runner.js +0 -134
  52. package/dist/backtest/storage.js +0 -11
  53. package/dist/backtest/types.js +0 -1
  54. package/dist/commands/install.js +0 -50
  55. package/dist/commands/start/ui/PollText.js +0 -23
  56. package/dist/commands/start/ui/PredictionsPanel.js +0 -88
  57. package/dist/commands/start/ui/SpinnerContext.js +0 -20
  58. package/dist/components/InputGuard.js +0 -6
  59. package/dist/components/stdout-spinner.js +0 -48
  60. package/dist/create/CreateApp.js +0 -153
  61. package/dist/create/ai-generate.js +0 -147
  62. package/dist/create/generate.js +0 -73
  63. package/dist/create/steps/ApiKeyStep.js +0 -97
  64. package/dist/create/steps/AvatarStep.js +0 -16
  65. package/dist/create/steps/BioStep.js +0 -14
  66. package/dist/create/steps/DoneStep.js +0 -14
  67. package/dist/create/steps/IdentityStep.js +0 -163
  68. package/dist/create/steps/NameStep.js +0 -71
  69. package/dist/create/steps/ScaffoldStep.js +0 -58
  70. package/dist/create/steps/SoulStep.js +0 -58
  71. package/dist/create/steps/StrategyStep.js +0 -58
  72. package/dist/create/validate-api-key.js +0 -47
  73. package/dist/create/welcome.js +0 -304
  74. package/dist/list/ListApp.js +0 -79
  75. package/dist/migrate-templates/MigrateApp.js +0 -131
  76. package/dist/migrate-templates/migrate.js +0 -86
  77. package/dist/presets.js +0 -613
  78. package/dist/start/AgentProcessManager.js +0 -98
  79. package/dist/start/Dashboard.js +0 -92
  80. package/dist/start/SelectAgentApp.js +0 -81
  81. package/dist/start/StartApp.js +0 -189
  82. package/dist/start/patch-headless.js +0 -101
  83. package/dist/start/patch-managed-mode.js +0 -142
  84. package/dist/start/start-command.js +0 -24
  85. package/dist/theme.js +0 -54
  86. /package/dist/{agent → services/agent}/config.js +0 -0
  87. /package/dist/{agent → services/agent}/helpers.js +0 -0
  88. /package/dist/{agent → services/agent/prompts}/chat-prompt.js +0 -0
  89. /package/dist/{agent → services/agent}/skills/index.js +0 -0
  90. /package/dist/{agent → services/agent}/skills/skill-parser.js +0 -0
  91. /package/dist/{agent → services/agent}/skills/types.js +0 -0
  92. /package/dist/{agent → services/agent/tools}/edit-section.js +0 -0
  93. /package/dist/{agent → services/agent/tools}/fetch-rules.js +0 -0
  94. /package/dist/{agent → services/agent}/tools/index.js +0 -0
  95. /package/dist/{agent → services/agent}/tools/market/index.js +0 -0
  96. /package/dist/{agent → services/agent}/tools/market/tools.js +0 -0
  97. /package/dist/{agent → services/agent}/tools/mindshare/index.js +0 -0
  98. /package/dist/{agent → services/agent}/tools/mindshare/tools.js +0 -0
  99. /package/dist/{agent → services/agent}/tools/read-skill-tool.js +0 -0
  100. /package/dist/{agent → services/agent}/tools/ta/index.js +0 -0
  101. /package/dist/{agent → services/agent}/tools/ta/indicators.js +0 -0
  102. /package/dist/{agent → services/agent}/types.js +0 -0
  103. /package/dist/{ai-providers.js → services/ai-providers.js} +0 -0
@@ -1,58 +0,0 @@
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 '../../theme.js';
6
- import { scaffoldProject } from '../generate.js';
7
- export function ScaffoldStep({ projectName, provider, apiKey, soulContent, strategyContent, onComplete, onError, }) {
8
- const [steps, setSteps] = useState([]);
9
- const [currentLabel, setCurrentLabel] = useState('Starting...');
10
- useEffect(() => {
11
- let cancelled = false;
12
- const run = async () => {
13
- await scaffoldProject(projectName, provider, apiKey, soulContent, strategyContent, {
14
- onStep: (label) => {
15
- if (cancelled)
16
- return;
17
- setSteps((prev) => {
18
- if (prev.length > 0) {
19
- const updated = [...prev];
20
- updated[updated.length - 1] = { ...updated[updated.length - 1], done: true };
21
- return [...updated, { label, done: false }];
22
- }
23
- return [{ label, done: false }];
24
- });
25
- setCurrentLabel(label);
26
- },
27
- onDone: (projectDir) => {
28
- if (cancelled)
29
- return;
30
- setSteps((prev) => {
31
- if (prev.length > 0) {
32
- const updated = [...prev];
33
- updated[updated.length - 1] = { ...updated[updated.length - 1], done: true };
34
- return updated;
35
- }
36
- return prev;
37
- });
38
- onComplete(projectDir);
39
- },
40
- onError: (message) => {
41
- if (cancelled)
42
- return;
43
- onError(message);
44
- },
45
- });
46
- };
47
- run().catch((err) => {
48
- if (cancelled)
49
- return;
50
- const message = err instanceof Error ? err.message : String(err);
51
- onError(message);
52
- });
53
- return () => {
54
- cancelled = true;
55
- };
56
- }, [projectName, provider, apiKey, soulContent, strategyContent, onComplete, onError]);
57
- 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 }) }))] }));
58
- }
@@ -1,58 +0,0 @@
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 { StreamingText } from '../../components/StreamingText.js';
5
- import { TextPrompt } from '../../components/TextPrompt.js';
6
- import { CodeBlock } from '../../components/CodeBlock.js';
7
- import { Spinner } from '../../components/Spinner.js';
8
- import { colors, symbols } from '../../theme.js';
9
- import { streamSoul } from '../ai-generate.js';
10
- export function SoulStep({ providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, onComplete, }) {
11
- const [phase, setPhase] = useState('streaming');
12
- const [draft, setDraft] = useState('');
13
- const [errorMessage, setErrorMessage] = useState('');
14
- const [feedbackCount, setFeedbackCount] = useState(0);
15
- const stream = useMemo(() => streamSoul(providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes), []);
16
- const [currentStream, setCurrentStream] = useState(stream);
17
- const handleStreamComplete = useCallback((fullText) => {
18
- const trimmed = fullText.trim();
19
- if (trimmed.length === 0) {
20
- setErrorMessage('LLM returned empty content. Try regenerating.');
21
- setPhase('error');
22
- return;
23
- }
24
- setDraft(trimmed);
25
- setPhase('review');
26
- }, []);
27
- const handleStreamError = useCallback((error) => {
28
- setErrorMessage(error);
29
- setPhase('error');
30
- }, []);
31
- const handleAccept = useCallback(() => {
32
- onComplete(draft);
33
- }, [draft, onComplete]);
34
- const handleRetry = useCallback(() => {
35
- setFeedbackCount((prev) => prev + 1);
36
- setPhase('streaming');
37
- setDraft('');
38
- setErrorMessage('');
39
- const newStream = streamSoul(providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes);
40
- setCurrentStream(newStream);
41
- }, [providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes]);
42
- const handleFeedback = useCallback((feedback) => {
43
- setFeedbackCount((prev) => prev + 1);
44
- setPhase('streaming');
45
- setDraft('');
46
- setErrorMessage('');
47
- const newStream = streamSoul(providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, feedback);
48
- setCurrentStream(newStream);
49
- }, [providerId, apiKey, agentName, bio, avatarUrl, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes]);
50
- return (_jsxs(Box, { flexDirection: "column", children: [phase === 'streaming' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Spinner, { label: feedbackCount > 0 ? 'Regenerating SOUL.md...' : 'Generating SOUL.md...' }) }), _jsx(StreamingText, { stream: currentStream, title: "SOUL.md", onComplete: handleStreamComplete, onError: handleStreamError })] })), phase === 'error' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.red, children: [symbols.cross, " "] }), _jsx(Text, { color: colors.white, children: "Failed to generate SOUL.md" })] }), _jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsx(Text, { color: colors.red, children: errorMessage }) }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: colors.gray, children: ["Press ", _jsx(Text, { color: colors.honey, bold: true, children: "Enter" }), " to retry"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(TextPrompt, { label: "", placeholder: "Enter to retry...", onSubmit: () => handleRetry() }) })] })), phase === 'review' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.green, children: [symbols.check, " "] }), _jsx(Text, { color: colors.white, children: "SOUL.md draft ready" })] }), _jsx(CodeBlock, { title: "SOUL.md", children: draft }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.gray, children: ["Press ", _jsx(Text, { color: colors.honey, bold: true, children: "Enter" }), " to accept", ' ', symbols.dot, ' ', "Type feedback to regenerate"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(TextPrompt, { label: "", placeholder: "Enter to accept, or type feedback...", onSubmit: (val) => {
51
- if (!val) {
52
- handleAccept();
53
- }
54
- else {
55
- handleFeedback(val);
56
- }
57
- } }) })] }))] }));
58
- }
@@ -1,58 +0,0 @@
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 { StreamingText } from '../../components/StreamingText.js';
5
- import { TextPrompt } from '../../components/TextPrompt.js';
6
- import { CodeBlock } from '../../components/CodeBlock.js';
7
- import { Spinner } from '../../components/Spinner.js';
8
- import { colors, symbols } from '../../theme.js';
9
- import { streamStrategy } from '../ai-generate.js';
10
- export function StrategyStep({ providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, onComplete, }) {
11
- const [phase, setPhase] = useState('streaming');
12
- const [draft, setDraft] = useState('');
13
- const [errorMessage, setErrorMessage] = useState('');
14
- const [feedbackCount, setFeedbackCount] = useState(0);
15
- const stream = useMemo(() => streamStrategy(providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes), []);
16
- const [currentStream, setCurrentStream] = useState(stream);
17
- const handleStreamComplete = useCallback((fullText) => {
18
- const trimmed = fullText.trim();
19
- if (trimmed.length === 0) {
20
- setErrorMessage('LLM returned empty content. Try regenerating.');
21
- setPhase('error');
22
- return;
23
- }
24
- setDraft(trimmed);
25
- setPhase('review');
26
- }, []);
27
- const handleStreamError = useCallback((error) => {
28
- setErrorMessage(error);
29
- setPhase('error');
30
- }, []);
31
- const handleAccept = useCallback(() => {
32
- onComplete(draft);
33
- }, [draft, onComplete]);
34
- const handleRetry = useCallback(() => {
35
- setFeedbackCount((prev) => prev + 1);
36
- setPhase('streaming');
37
- setDraft('');
38
- setErrorMessage('');
39
- const newStream = streamStrategy(providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes);
40
- setCurrentStream(newStream);
41
- }, [providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes]);
42
- const handleFeedback = useCallback((feedback) => {
43
- setFeedbackCount((prev) => prev + 1);
44
- setPhase('streaming');
45
- setDraft('');
46
- setErrorMessage('');
47
- const newStream = streamStrategy(providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes, feedback);
48
- setCurrentStream(newStream);
49
- }, [providerId, apiKey, agentName, bio, personality, tone, voiceStyle, tradingStyle, sectors, sentiment, timeframes]);
50
- return (_jsxs(Box, { flexDirection: "column", children: [phase === 'streaming' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Spinner, { label: feedbackCount > 0 ? 'Regenerating STRATEGY.md...' : 'Generating STRATEGY.md...' }) }), _jsx(StreamingText, { stream: currentStream, title: "STRATEGY.md", onComplete: handleStreamComplete, onError: handleStreamError })] })), phase === 'error' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.red, children: [symbols.cross, " "] }), _jsx(Text, { color: colors.white, children: "Failed to generate STRATEGY.md" })] }), _jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsx(Text, { color: colors.red, children: errorMessage }) }), _jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: colors.gray, children: ["Press ", _jsx(Text, { color: colors.honey, bold: true, children: "Enter" }), " to retry"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(TextPrompt, { label: "", placeholder: "Enter to retry...", onSubmit: () => handleRetry() }) })] })), phase === 'review' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.green, children: [symbols.check, " "] }), _jsx(Text, { color: colors.white, children: "STRATEGY.md draft ready" })] }), _jsx(CodeBlock, { title: "STRATEGY.md", children: draft }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.gray, children: ["Press ", _jsx(Text, { color: colors.honey, bold: true, children: "Enter" }), " to accept", ' ', symbols.dot, ' ', "Type feedback to regenerate"] }) }), _jsx(Box, { marginTop: 1, children: _jsx(TextPrompt, { label: "", placeholder: "Enter to accept, or type feedback...", onSubmit: (val) => {
51
- if (!val) {
52
- handleAccept();
53
- }
54
- else {
55
- handleFeedback(val);
56
- }
57
- } }) })] }))] }));
58
- }
@@ -1,47 +0,0 @@
1
- import { generateText } from 'ai';
2
- import { createOpenAI } from '@ai-sdk/openai';
3
- import { createAnthropic } from '@ai-sdk/anthropic';
4
- import { createGoogleGenerativeAI } from '@ai-sdk/google';
5
- import { createXai } from '@ai-sdk/xai';
6
- import { createOpenRouter } from '@openrouter/ai-sdk-provider';
7
- import { getProvider } from '../ai-providers.js';
8
- /**
9
- * Make a lightweight test call to validate the user's API key.
10
- * Returns true if the key works, or an error message string on failure.
11
- */
12
- export async function validateApiKey(providerId, apiKey) {
13
- try {
14
- const model = buildTestModel(providerId, apiKey);
15
- await generateText({
16
- model,
17
- prompt: 'Say "ok"',
18
- maxOutputTokens: 16,
19
- });
20
- return true;
21
- }
22
- catch (err) {
23
- const message = err instanceof Error ? err.message : String(err);
24
- if (message.includes('401') ||
25
- message.includes('Unauthorized') ||
26
- message.includes('invalid')) {
27
- return 'Invalid API key. Please check and try again.';
28
- }
29
- return `API validation failed: ${message.slice(0, 120)}`;
30
- }
31
- }
32
- function buildTestModel(providerId, apiKey) {
33
- const provider = getProvider(providerId);
34
- const modelId = provider.models.validation;
35
- switch (providerId) {
36
- case 'openai':
37
- return createOpenAI({ apiKey })(modelId);
38
- case 'anthropic':
39
- return createAnthropic({ apiKey })(modelId);
40
- case 'google':
41
- return createGoogleGenerativeAI({ apiKey })(modelId);
42
- case 'xai':
43
- return createXai({ apiKey })(modelId);
44
- case 'openrouter':
45
- return createOpenRouter({ apiKey }).chat(modelId);
46
- }
47
- }
@@ -1,304 +0,0 @@
1
- import chalk from 'chalk';
2
- const HEX_W = 8;
3
- const HEX_H = 4;
4
- const DATA_CHARS = '01▪▫░▒';
5
- const TICK_MS = 80;
6
- const DURATION_MS = 3200;
7
- const NUM_BEES = 4;
8
- const NUM_STREAMS = 5;
9
- const HONEY = '#F5A623';
10
- const GREEN = '#27C587';
11
- const DIM = '#555555';
12
- const WHITE = '#FFFFFF';
13
- const RED = '#E14B4B';
14
- const SCRAMBLE_CHARS = '⬡⬢◆◇░▒!@#$%01';
15
- const BOOT_MESSAGES = [
16
- { prefix: '⬡', text: 'Initializing creation studio...', frame: 18, color: HONEY },
17
- { prefix: '◆', text: 'Loading agent templates...', frame: 24, color: HONEY },
18
- { prefix: '◇', text: 'Connecting to hive network...', frame: 30, color: HONEY },
19
- { prefix: '✓', text: 'Ready', frame: 36, color: GREEN },
20
- ];
21
- function isHexEdge(r, c) {
22
- const rowInHex = ((r % HEX_H) + HEX_H) % HEX_H;
23
- const isOddHex = Math.floor(r / HEX_H) % 2 === 1;
24
- const colOffset = isOddHex ? HEX_W / 2 : 0;
25
- const colInHex = (((c - colOffset) % HEX_W) + HEX_W) % HEX_W;
26
- if (rowInHex === 0 || rowInHex === HEX_H - 1) {
27
- return colInHex >= 2 && colInHex <= 5;
28
- }
29
- if (rowInHex === 1 || rowInHex === 2) {
30
- return colInHex === 1 || colInHex === 6;
31
- }
32
- return false;
33
- }
34
- export function showWelcome() {
35
- return new Promise((resolve) => {
36
- const cols = process.stdout.columns || 60;
37
- const gridRows = process.stdout.rows || 24;
38
- let frame = 0;
39
- // Init bees
40
- const bees = [];
41
- for (let i = 0; i < NUM_BEES; i++) {
42
- bees.push({
43
- r: Math.floor(Math.random() * gridRows),
44
- c: Math.floor(Math.random() * cols),
45
- vr: Math.random() > 0.5 ? 1 : -1,
46
- vc: Math.random() > 0.5 ? 1 : -1,
47
- });
48
- }
49
- // Init stream columns
50
- const streamCols = [];
51
- const spacing = Math.floor(cols / (NUM_STREAMS + 1));
52
- for (let i = 1; i <= NUM_STREAMS; i++) {
53
- streamCols.push(spacing * i);
54
- }
55
- let pulses = [];
56
- // Title positioning
57
- const title = '\u2B21 HIVE';
58
- const subtitle = 'Agent Creation Studio';
59
- const titleRow = Math.floor(gridRows / 2) - 1;
60
- const subtitleRow = titleRow + 1;
61
- const titleCol = Math.floor((cols - title.length) / 2);
62
- const subtitleCol = Math.floor((cols - subtitle.length) / 2);
63
- // Boot message row positions
64
- const msgStartRow = subtitleRow + 2;
65
- // Quiet zone around title + boot messages: no animation renders here
66
- const PADDING_H = 3;
67
- const PADDING_V = 1;
68
- const longestMsg = BOOT_MESSAGES.reduce((max, m) => Math.max(max, m.prefix.length + 1 + m.text.length), 0);
69
- const msgLeftEdge = Math.floor((cols - longestMsg) / 2);
70
- const msgRightEdge = msgLeftEdge + longestMsg;
71
- const quietLeft = Math.min(titleCol, subtitleCol, msgLeftEdge) - PADDING_H;
72
- const quietRight = Math.max(titleCol + title.length, subtitleCol + subtitle.length, msgRightEdge) + PADDING_H;
73
- const quietTop = titleRow - PADDING_V;
74
- const quietBottom = msgStartRow + BOOT_MESSAGES.length + PADDING_V;
75
- // Hide cursor
76
- process.stdout.write('\x1b[?25l');
77
- // Clear screen
78
- process.stdout.write('\x1b[2J');
79
- function renderFrame() {
80
- // Move cursor to top-left
81
- process.stdout.write('\x1b[H');
82
- // Advance bees every other frame
83
- if (frame > 0 && frame % 2 === 0) {
84
- for (const bee of bees) {
85
- bee.r += bee.vr;
86
- bee.c += bee.vc;
87
- if (bee.r <= 0 || bee.r >= gridRows - 1) {
88
- bee.vr *= -1;
89
- bee.r = Math.max(0, Math.min(gridRows - 1, bee.r));
90
- }
91
- if (bee.c <= 0 || bee.c >= cols - 1) {
92
- bee.vc *= -1;
93
- bee.c = Math.max(0, Math.min(cols - 1, bee.c));
94
- }
95
- if (Math.random() > 0.3) {
96
- bee.vc = Math.random() > 0.5 ? 1 : -1;
97
- }
98
- }
99
- }
100
- // Spawn pulses
101
- if (frame % 4 === 0) {
102
- for (let i = 0; i < 3; i++) {
103
- const pr = Math.floor(Math.random() * gridRows);
104
- const pc = Math.floor(Math.random() * cols);
105
- if (isHexEdge(pr, pc)) {
106
- const pulseColors = [GREEN, RED, HONEY];
107
- const color = pulseColors[Math.floor(Math.random() * pulseColors.length)];
108
- pulses.push({ r: pr, c: pc, ttl: 8, color });
109
- }
110
- }
111
- pulses = pulses.filter((p) => p.ttl > 0).map((p) => ({ ...p, ttl: p.ttl - 1 }));
112
- }
113
- // Build grid: char + color pairs
114
- const charGrid = [];
115
- const colorGrid = [];
116
- for (let r = 0; r < gridRows; r++) {
117
- const chars = [];
118
- const clrs = [];
119
- for (let c = 0; c < cols; c++) {
120
- // Skip animation in quiet zone around title
121
- if (r >= quietTop && r <= quietBottom && c >= quietLeft && c < quietRight) {
122
- chars.push(' ');
123
- clrs.push(DIM);
124
- continue;
125
- }
126
- const hexEdge = isHexEdge(r, c);
127
- // Scanning wave
128
- const scanRow = frame % (gridRows + 6);
129
- const dist = Math.abs(r - scanRow);
130
- if (hexEdge && dist === 0) {
131
- chars.push('⬢');
132
- clrs.push(HONEY);
133
- continue;
134
- }
135
- if (hexEdge && dist <= 1) {
136
- chars.push('⬡');
137
- clrs.push(HONEY);
138
- continue;
139
- }
140
- // Data streams
141
- let isStream = false;
142
- for (const sc of streamCols) {
143
- if (c === sc) {
144
- const streamOffset = (frame * 2 + sc) % (gridRows * 3);
145
- const streamDist = (((r - streamOffset) % gridRows) + gridRows) % gridRows;
146
- if (streamDist < 6) {
147
- const charIdx = (frame + r) % DATA_CHARS.length;
148
- const streamChar = DATA_CHARS[charIdx];
149
- chars.push(streamChar);
150
- if (streamDist === 0) {
151
- clrs.push(WHITE);
152
- }
153
- else if (streamDist < 3) {
154
- clrs.push(GREEN);
155
- }
156
- else {
157
- clrs.push(DIM);
158
- }
159
- isStream = true;
160
- break;
161
- }
162
- }
163
- }
164
- if (isStream)
165
- continue;
166
- // Default
167
- if (hexEdge) {
168
- chars.push('·');
169
- clrs.push(DIM);
170
- }
171
- else {
172
- chars.push(' ');
173
- clrs.push(DIM);
174
- }
175
- }
176
- charGrid.push(chars);
177
- colorGrid.push(clrs);
178
- }
179
- // Overlay pulses (skip quiet zone)
180
- for (const pulse of pulses) {
181
- if (pulse.r >= 0 && pulse.r < gridRows && pulse.c >= 0 && pulse.c < cols) {
182
- const inQuietZone = pulse.r >= quietTop &&
183
- pulse.r <= quietBottom &&
184
- pulse.c >= quietLeft &&
185
- pulse.c < quietRight;
186
- if (inQuietZone)
187
- continue;
188
- const brightness = pulse.ttl / 8;
189
- const cell = charGrid[pulse.r][pulse.c];
190
- if (cell === '·' || cell === ' ') {
191
- charGrid[pulse.r][pulse.c] = brightness > 0.5 ? '⬡' : '·';
192
- colorGrid[pulse.r][pulse.c] = pulse.color;
193
- }
194
- }
195
- }
196
- // Overlay bees (skip quiet zone)
197
- for (const bee of bees) {
198
- const br = Math.max(0, Math.min(gridRows - 1, Math.round(bee.r)));
199
- const bc = Math.max(0, Math.min(cols - 1, Math.round(bee.c)));
200
- const inQuietZone = br >= quietTop && br <= quietBottom && bc >= quietLeft && bc < quietRight;
201
- if (!inQuietZone) {
202
- charGrid[br][bc] = '◆';
203
- colorGrid[br][bc] = HONEY;
204
- }
205
- }
206
- // Overlay title with scramble→reveal effect
207
- const TITLE_START_FRAME = 6;
208
- const TITLE_REVEAL_FRAMES = 8;
209
- if (frame >= TITLE_START_FRAME && titleRow >= 0 && titleRow < gridRows) {
210
- const scrambleProgress = Math.min(1, (frame - TITLE_START_FRAME) / TITLE_REVEAL_FRAMES);
211
- for (let i = 0; i < title.length; i++) {
212
- const tc = titleCol + i;
213
- if (tc < 0 || tc >= cols)
214
- continue;
215
- const charThreshold = i / title.length;
216
- if (charThreshold <= scrambleProgress) {
217
- charGrid[titleRow][tc] = title[i];
218
- colorGrid[titleRow][tc] = HONEY;
219
- }
220
- else {
221
- const scrambleIdx = Math.floor(Math.random() * SCRAMBLE_CHARS.length);
222
- charGrid[titleRow][tc] = SCRAMBLE_CHARS[scrambleIdx];
223
- colorGrid[titleRow][tc] = DIM;
224
- }
225
- }
226
- }
227
- // Overlay subtitle with scramble→reveal (starts a few frames after title)
228
- const SUB_START_FRAME = 10;
229
- const SUB_REVEAL_FRAMES = 8;
230
- if (frame >= SUB_START_FRAME && subtitleRow >= 0 && subtitleRow < gridRows) {
231
- const scrambleProgress = Math.min(1, (frame - SUB_START_FRAME) / SUB_REVEAL_FRAMES);
232
- for (let i = 0; i < subtitle.length; i++) {
233
- const sc = subtitleCol + i;
234
- if (sc < 0 || sc >= cols)
235
- continue;
236
- const charThreshold = i / subtitle.length;
237
- if (charThreshold <= scrambleProgress) {
238
- charGrid[subtitleRow][sc] = subtitle[i];
239
- colorGrid[subtitleRow][sc] = DIM;
240
- }
241
- else {
242
- const scrambleIdx = Math.floor(Math.random() * SCRAMBLE_CHARS.length);
243
- charGrid[subtitleRow][sc] = SCRAMBLE_CHARS[scrambleIdx];
244
- colorGrid[subtitleRow][sc] = DIM;
245
- }
246
- }
247
- }
248
- // Overlay typewriter boot messages
249
- for (let idx = 0; idx < BOOT_MESSAGES.length; idx++) {
250
- const msg = BOOT_MESSAGES[idx];
251
- if (frame < msg.frame)
252
- continue;
253
- const r = msgStartRow + idx;
254
- if (r < 0 || r >= gridRows)
255
- continue;
256
- const fullText = `${msg.prefix} ${msg.text}`;
257
- const msgCol = Math.floor((cols - fullText.length) / 2);
258
- const visibleChars = Math.min(fullText.length, (frame - msg.frame) * 3);
259
- for (let i = 0; i < visibleChars; i++) {
260
- const c = msgCol + i;
261
- if (c < 0 || c >= cols)
262
- continue;
263
- charGrid[r][c] = fullText[i];
264
- colorGrid[r][c] = msg.color;
265
- }
266
- }
267
- // Render to stdout
268
- let output = '';
269
- for (let r = 0; r < gridRows; r++) {
270
- let line = '';
271
- let runColor = colorGrid[r][0];
272
- let runChars = '';
273
- for (let c = 0; c < cols; c++) {
274
- const curColor = colorGrid[r][c];
275
- const curChar = charGrid[r][c];
276
- if (curColor === runColor) {
277
- runChars += curChar;
278
- }
279
- else {
280
- line += chalk.hex(runColor)(runChars);
281
- runColor = curColor;
282
- runChars = curChar;
283
- }
284
- }
285
- if (runChars.length > 0) {
286
- line += chalk.hex(runColor)(runChars);
287
- }
288
- output += line;
289
- if (r < gridRows - 1) {
290
- output += '\n';
291
- }
292
- }
293
- process.stdout.write(output);
294
- frame++;
295
- }
296
- const timer = setInterval(renderFrame, TICK_MS);
297
- setTimeout(() => {
298
- clearInterval(timer);
299
- // Clear screen, show cursor, move to top
300
- process.stdout.write('\x1b[2J\x1b[H\x1b[?25h');
301
- resolve();
302
- }, DURATION_MS);
303
- });
304
- }
@@ -1,79 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from 'react';
3
- import { Box, Text, useApp } from 'ink';
4
- import { colors, symbols, border } from '../theme.js';
5
- import { scanAgents, fetchBulkStats, sortByHoney } from '../agents.js';
6
- const COL = {
7
- name: 0,
8
- honey: 8,
9
- wax: 8,
10
- winRate: 10,
11
- confidence: 8,
12
- provider: 0,
13
- created: 14,
14
- };
15
- function cell(text, width) {
16
- return ` ${text}`.padEnd(width);
17
- }
18
- function formatDate(date) {
19
- const formatted = date.toLocaleDateString('en-US', {
20
- year: 'numeric',
21
- month: 'short',
22
- day: 'numeric',
23
- });
24
- return formatted;
25
- }
26
- export function ListApp() {
27
- const { exit } = useApp();
28
- const [rows, setRows] = useState(null);
29
- useEffect(() => {
30
- const load = async () => {
31
- const agents = await scanAgents();
32
- if (agents.length === 0) {
33
- setRows([]);
34
- return;
35
- }
36
- const names = agents.map((a) => a.name);
37
- const statsMap = await fetchBulkStats(names);
38
- const agentRows = agents.map((info) => ({
39
- info,
40
- stats: statsMap.get(info.name) ?? null,
41
- }));
42
- const sortedRows = sortByHoney(agentRows);
43
- setRows(sortedRows);
44
- };
45
- void load();
46
- }, []);
47
- useEffect(() => {
48
- if (rows !== null) {
49
- exit();
50
- }
51
- }, [rows]);
52
- if (rows === null) {
53
- return (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: colors.gray, children: "Scanning agents..." }) }));
54
- }
55
- if (rows.length === 0) {
56
- 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: "No agents found" })] }), _jsxs(Text, { color: colors.gray, children: ["Create one with: ", _jsx(Text, { color: colors.white, children: "npx @hive-org/cli@latest create" })] })] }));
57
- }
58
- const nameW = Math.max(COL.name, ...rows.map((r) => r.info.name.length)) + 2;
59
- const providerW = Math.max(COL.provider, ...rows.map((r) => r.info.provider.length)) + 2;
60
- const honeyW = COL.honey;
61
- const waxW = COL.wax;
62
- const winRateW = COL.winRate;
63
- const confidenceW = COL.confidence;
64
- const createdW = COL.created;
65
- const sep = border.horizontal;
66
- const totalWidth = nameW + 1 + honeyW + 1 + waxW + 1 + winRateW + 1 + confidenceW + 1 + providerW + 1 + createdW;
67
- const topBorder = `${border.topLeft}${sep.repeat(totalWidth)}${border.topRight}`;
68
- const midBorder = `${border.teeLeft}${sep.repeat(totalWidth)}${border.teeRight}`;
69
- const botBorder = `${border.bottomLeft}${sep.repeat(totalWidth)}${border.bottomRight}`;
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 Hive 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
- const s = row.stats;
73
- const honeyText = s !== null ? String(Math.floor(s.honey)) : '-';
74
- const waxText = s !== null ? String(Math.floor(s.wax)) : '-';
75
- const winRateText = s !== null ? `${(s.win_rate * 100).toFixed(2)}%` : '-';
76
- const confidenceText = s !== null ? s.confidence.toFixed(2) : '-';
77
- return (_jsxs(Box, { children: [_jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.white, children: cell(row.info.name, nameW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.honey, children: cell(honeyText, honeyW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.wax, children: cell(waxText, waxW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.green, children: cell(winRateText, winRateW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.cyan, children: cell(confidenceText, confidenceW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.gray, children: cell(row.info.provider, providerW) }), _jsx(Text, { color: colors.honey, children: v }), _jsx(Text, { color: colors.grayDim, children: cell(formatDate(row.info.created), createdW) }), _jsx(Text, { color: colors.honey, children: v })] }, row.info.name));
78
- }), _jsx(Box, { children: _jsx(Text, { color: colors.honey, children: botBorder }) })] }));
79
- }