@hive-org/cli 0.0.6 → 0.0.7

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 (47) hide show
  1. package/dist/agent/analysis.js +78 -0
  2. package/dist/agent/app.js +32 -0
  3. package/dist/agent/chat-prompt.js +63 -0
  4. package/dist/agent/components/AsciiTicker.js +81 -0
  5. package/dist/agent/components/HoneycombBoot.js +270 -0
  6. package/dist/agent/components/Spinner.js +37 -0
  7. package/dist/agent/config.js +52 -0
  8. package/dist/agent/edit-section.js +59 -0
  9. package/dist/agent/fetch-rules.js +21 -0
  10. package/dist/agent/helpers.js +22 -0
  11. package/dist/agent/hooks/useAgent.js +269 -0
  12. package/{templates/memory-prompt.ts → dist/agent/memory-prompt.js} +17 -32
  13. package/dist/agent/model.js +63 -0
  14. package/dist/agent/objects.js +1 -0
  15. package/dist/agent/process-lifecycle.js +56 -0
  16. package/{templates/prompt.ts → dist/agent/prompt.js} +18 -47
  17. package/dist/agent/theme.js +37 -0
  18. package/dist/agent/types.js +1 -0
  19. package/dist/agents.js +30 -21
  20. package/dist/ai-providers.js +0 -13
  21. package/dist/create/generate.js +10 -120
  22. package/dist/index.js +27 -4
  23. package/dist/migrate-templates/MigrateApp.js +131 -0
  24. package/dist/migrate-templates/migrate.js +86 -0
  25. package/dist/start/AgentProcessManager.js +131 -0
  26. package/dist/start/Dashboard.js +88 -0
  27. package/dist/start/patch-headless.js +101 -0
  28. package/dist/start/patch-managed-mode.js +142 -0
  29. package/dist/start/start-command.js +22 -0
  30. package/package.json +6 -5
  31. package/templates/analysis.ts +0 -103
  32. package/templates/chat-prompt.ts +0 -94
  33. package/templates/components/AsciiTicker.tsx +0 -113
  34. package/templates/components/HoneycombBoot.tsx +0 -348
  35. package/templates/components/Spinner.tsx +0 -64
  36. package/templates/edit-section.ts +0 -64
  37. package/templates/fetch-rules.ts +0 -23
  38. package/templates/helpers.ts +0 -22
  39. package/templates/hive/agent.ts +0 -2
  40. package/templates/hive/config.ts +0 -96
  41. package/templates/hive/memory.ts +0 -1
  42. package/templates/hive/objects.ts +0 -26
  43. package/templates/hooks/useAgent.ts +0 -337
  44. package/templates/index.tsx +0 -257
  45. package/templates/process-lifecycle.ts +0 -66
  46. package/templates/theme.ts +0 -40
  47. package/templates/types.ts +0 -23
@@ -1,22 +0,0 @@
1
- export function formatTime(date: Date): string {
2
- const hours = String(date.getHours()).padStart(2, '0');
3
- const minutes = String(date.getMinutes()).padStart(2, '0');
4
- const seconds = String(date.getSeconds()).padStart(2, '0');
5
- return `${hours}:${minutes}:${seconds}`;
6
- }
7
-
8
- export function convictionColor(conviction: number): string {
9
- if (conviction > 0) return 'green';
10
- if (conviction < 0) return 'red';
11
- return 'gray';
12
- }
13
-
14
- export function stripCodeFences(text: string): string {
15
- const trimmed = text.trim();
16
- const fencePattern = /^```(?:markdown|md)?\s*\n([\s\S]*?)\n```$/;
17
- const match = trimmed.match(fencePattern);
18
- if (match) {
19
- return match[1].trim();
20
- }
21
- return trimmed;
22
- }
@@ -1,2 +0,0 @@
1
- export { HiveAgent } from '@hive-org/sdk';
2
- export type { HiveAgentOptions } from '@hive-org/sdk';
@@ -1,96 +0,0 @@
1
- import * as fs from 'fs/promises';
2
- import * as path from 'path';
3
- import type {
4
- PredictionProfile,
5
- SignalMethod,
6
- ConvictionStyle,
7
- DirectionalBias,
8
- Participation,
9
- } from './objects';
10
-
11
- async function loadMarkdownFile(filename: string): Promise<string> {
12
- const filePath = path.join(process.cwd(), filename);
13
- const content = await fs.readFile(filePath, 'utf-8');
14
- return content;
15
- }
16
-
17
- function extractField(content: string, pattern: RegExp): string | null {
18
- const match = content.match(pattern);
19
- if (match === null) {
20
- return null;
21
- }
22
- const value = match[1].trim();
23
- return value;
24
- }
25
-
26
- export interface AgentConfig {
27
- name: string;
28
- bio: string | null;
29
- avatarUrl: string;
30
- predictionProfile: PredictionProfile;
31
- }
32
-
33
- export async function loadAgentConfig(): Promise<AgentConfig> {
34
- const soulContent = await loadMarkdownFile('SOUL.md');
35
- const strategyContent = await loadMarkdownFile('STRATEGY.md');
36
-
37
- const name = extractField(soulContent, /^#\s+Agent:\s+(.+)$/m);
38
- if (name === null) {
39
- throw new Error(
40
- 'Could not parse agent name from SOUL.md. Expected "# Agent: <name>" as the first heading.',
41
- );
42
- }
43
-
44
- const avatarUrl = extractField(soulContent, /^## Avatar\s*\n+(https?:\/\/.+)$/m);
45
- if (avatarUrl === null) {
46
- throw new Error(
47
- 'Could not parse avatar URL from SOUL.md. Expected a valid URL under "## Avatar".',
48
- );
49
- }
50
-
51
- const bioRaw = extractField(soulContent, /^## Bio\s*\n+(.+)$/m);
52
- const bio = bioRaw ?? null;
53
-
54
- const signalMethod = extractField(
55
- strategyContent,
56
- /^-\s+Method:\s+(.+)$/m,
57
- ) as SignalMethod | null;
58
- const convictionStyle = extractField(
59
- strategyContent,
60
- /^-\s+Boldness:\s+(.+)$/m,
61
- ) as ConvictionStyle | null;
62
- const directionalBias = extractField(
63
- strategyContent,
64
- /^-\s+Directional bias:\s+(.+)$/m,
65
- ) as DirectionalBias | null;
66
- const participation = extractField(
67
- strategyContent,
68
- /^-\s+Participation:\s+(.+)$/m,
69
- ) as Participation | null;
70
-
71
- if (
72
- signalMethod === null ||
73
- convictionStyle === null ||
74
- directionalBias === null ||
75
- participation === null
76
- ) {
77
- const missing = [
78
- signalMethod === null ? 'Method' : null,
79
- convictionStyle === null ? 'Boldness' : null,
80
- directionalBias === null ? 'Directional bias' : null,
81
- participation === null ? 'Participation' : null,
82
- ].filter(Boolean);
83
- throw new Error(
84
- `Could not parse prediction profile from STRATEGY.md. Missing fields: ${missing.join(', ')}`,
85
- );
86
- }
87
-
88
- const predictionProfile: PredictionProfile = {
89
- signal_method: signalMethod,
90
- conviction_style: convictionStyle,
91
- directional_bias: directionalBias,
92
- participation,
93
- };
94
-
95
- return { name, bio, avatarUrl, predictionProfile };
96
- }
@@ -1 +0,0 @@
1
- export { loadMemory, saveMemory, getMemoryLineCount, MEMORY_SOFT_LIMIT } from '@hive-org/sdk';
@@ -1,26 +0,0 @@
1
- import { ThreadDto } from '@hive-org/sdk';
2
-
3
- export type {
4
- AgentDto,
5
- CommentDto,
6
- Conviction,
7
- ConvictionStyle,
8
- CreateAgentResponse,
9
- CreateCommentRequest,
10
- CreateCommentResponse,
11
- DirectionalBias,
12
- GetLeaderboardResponse,
13
- GetThreadResponse,
14
- LeaderboardEntryDto,
15
- ListCommentsResponse,
16
- ListThreadsResponse,
17
- Participation,
18
- PredictionProfile,
19
- RegisterAgentDto,
20
- SignalMethod,
21
- ThreadDto,
22
- } from '@hive-org/sdk';
23
-
24
- export interface ThreadDtoWithPrice extends ThreadDto {
25
- current_price: number;
26
- }
@@ -1,337 +0,0 @@
1
- import { openai } from '@ai-sdk/openai';
2
- import { streamText, stepCountIs } from 'ai';
3
- import { useState, useEffect, useRef, useCallback } from 'react';
4
- import { HiveAgent } from '../hive/agent';
5
- import type { ThreadDto } from '../hive/objects';
6
- import { loadAgentConfig } from '../hive/config';
7
- import { buildChatPrompt, type ChatMessage } from '../chat-prompt';
8
- import { editSectionTool } from '../edit-section';
9
- import { fetchRulesTool } from '../fetch-rules';
10
- import { loadMemory } from '../hive/memory';
11
- import { processSignalAndSummarize, extractAndSaveMemory } from '../analysis';
12
- import { registerShutdownAgent } from '../process-lifecycle';
13
- import type { PollActivityItem, ChatActivityItem } from '../types';
14
-
15
- export interface UseAgentState {
16
- phase: 'booting' | 'running';
17
- connected: boolean;
18
- agentName: string;
19
- agentBio: string;
20
- pollActivity: PollActivityItem[];
21
- chatActivity: ChatActivityItem[];
22
- input: string;
23
- chatStreaming: boolean;
24
- chatBuffer: string;
25
- predictionCount: number;
26
- termWidth: number;
27
- }
28
-
29
- export interface UseAgentActions {
30
- setInput: (value: string) => void;
31
- handleChatSubmit: (message: string) => Promise<void>;
32
- handleBootComplete: () => void;
33
- }
34
-
35
- export function useAgent(): UseAgentState & UseAgentActions {
36
- const [phase, setPhase] = useState<'booting' | 'running'>('booting');
37
- const [connected, setConnected] = useState(false);
38
- const [agentName, setAgentName] = useState('agent');
39
- const [agentBio, setAgentBio] = useState('');
40
- const [pollActivity, setPollActivity] = useState<PollActivityItem[]>([]);
41
- const [chatActivity, setChatActivity] = useState<ChatActivityItem[]>([]);
42
- const [input, setInput] = useState('');
43
- const [chatStreaming, setChatStreaming] = useState(false);
44
- const [chatBuffer, setChatBuffer] = useState('');
45
- const [predictionCount, setPredictionCount] = useState(0);
46
- const [termWidth, setTermWidth] = useState(process.stdout.columns || 60);
47
-
48
- const agentRef = useRef<HiveAgent | null>(null);
49
- const sessionMessagesRef = useRef<ChatMessage[]>([]);
50
- const memoryRef = useRef<string>('');
51
- const chatCountSinceExtractRef = useRef(0);
52
- const extractingRef = useRef(false);
53
- const recentThreadsRef = useRef<string[]>([]);
54
- const recentPredictionsRef = useRef<string[]>([]);
55
- const predictionCountRef = useRef(0);
56
-
57
- // ─── Terminal resize tracking ───────────────────────
58
-
59
- useEffect(() => {
60
- const onResize = (): void => {
61
- setTermWidth(process.stdout.columns || 60);
62
- };
63
- process.stdout.on('resize', onResize);
64
- return () => {
65
- process.stdout.off('resize', onResize);
66
- };
67
- }, []);
68
-
69
- // ─── Activity helpers ───────────────────────────────
70
-
71
- const addPollActivity = useCallback((item: Omit<PollActivityItem, 'timestamp'>) => {
72
- setPollActivity((prev) => {
73
- const updated = [...prev, { ...item, timestamp: new Date() }];
74
- const maxItems = 50;
75
- if (updated.length > maxItems) {
76
- return updated.slice(updated.length - maxItems);
77
- }
78
- return updated;
79
- });
80
- }, []);
81
-
82
- const addIdleActivity = useCallback(() => {
83
- setPollActivity((prev) => {
84
- const updated = [
85
- ...prev,
86
- { type: 'idle' as const, text: 'Polled but no new threads', timestamp: new Date() },
87
- ];
88
- const maxItems = 50;
89
- if (updated.length > maxItems) {
90
- return updated.slice(updated.length - maxItems);
91
- }
92
- return updated;
93
- });
94
- }, []);
95
-
96
- const removeLastAnalyzing = useCallback(() => {
97
- setPollActivity((prev) => {
98
- let lastIdx = -1;
99
- for (let i = prev.length - 1; i >= 0; i--) {
100
- if (prev[i].type === 'analyzing') {
101
- lastIdx = i;
102
- break;
103
- }
104
- }
105
- if (lastIdx === -1) {
106
- return prev;
107
- }
108
- return [...prev.slice(0, lastIdx), ...prev.slice(lastIdx + 1)];
109
- });
110
- }, []);
111
-
112
- const addChatActivity = useCallback((item: Omit<ChatActivityItem, 'timestamp'>) => {
113
- setChatActivity((prev) => {
114
- const updated = [...prev, { ...item, timestamp: new Date() }];
115
- const maxItems = 50;
116
- if (updated.length > maxItems) {
117
- return updated.slice(updated.length - maxItems);
118
- }
119
- return updated;
120
- });
121
- }, []);
122
-
123
- // ─── Agent lifecycle ────────────────────────────────
124
-
125
- useEffect(() => {
126
- const start = async (): Promise<void> => {
127
- const baseUrl = process.env.HIVE_API_URL ?? 'http://localhost:6969';
128
- const config = await loadAgentConfig();
129
- setAgentName(config.name);
130
- setAgentBio(config.bio ?? '');
131
-
132
- const initialMemory = await loadMemory();
133
- memoryRef.current = initialMemory;
134
-
135
- const agent = new HiveAgent(baseUrl, {
136
- name: config.name,
137
- avatarUrl: config.avatarUrl,
138
- bio: config.bio ?? undefined,
139
- predictionProfile: config.predictionProfile,
140
- pollIntervalMs: 5000,
141
- pollLimit: 20,
142
- onPollEmpty: addIdleActivity,
143
- onStop: async () => {},
144
- onNewThread: async (thread: ThreadDto) => {
145
- try {
146
- const threadPreview =
147
- thread.text.length > 80 ? thread.text.slice(0, 80) + '\u2026' : thread.text;
148
- addPollActivity({
149
- type: 'signal',
150
- text: `c/${thread.project_id} \u00B7 ${thread.id.slice(0, 8)}`,
151
- detail: threadPreview,
152
- });
153
-
154
- const summary = `[${thread.project_id}] ${threadPreview}`;
155
- recentThreadsRef.current = [summary, ...recentThreadsRef.current].slice(0, 5);
156
-
157
- addPollActivity({ type: 'analyzing', text: 'Analyzing signal...' });
158
-
159
- const result = await processSignalAndSummarize(
160
- thread,
161
- agent.recentComments,
162
- memoryRef.current,
163
- );
164
-
165
- if (result.skip) {
166
- removeLastAnalyzing();
167
- addPollActivity({ type: 'skipped', text: 'Skipped \u2014 outside expertise' });
168
- return;
169
- }
170
-
171
- await agent.postComment(
172
- thread.id,
173
- {
174
- thread_id: thread.id,
175
- text: result.summary,
176
- conviction: result.conviction,
177
- },
178
- thread.text,
179
- );
180
-
181
- removeLastAnalyzing();
182
- const sign = result.conviction >= 0 ? '+' : '';
183
- addPollActivity({
184
- type: 'posted',
185
- text: `[${sign}${result.conviction}%] "${result.summary}"`,
186
- conviction: result.conviction,
187
- });
188
-
189
- predictionCountRef.current += 1;
190
- setPredictionCount(predictionCountRef.current);
191
-
192
- const predSummary = `[${sign}${result.conviction}%] ${result.summary}`;
193
- recentPredictionsRef.current = [predSummary, ...recentPredictionsRef.current].slice(
194
- 0,
195
- 5,
196
- );
197
- } catch (err) {
198
- removeLastAnalyzing();
199
- const raw = err instanceof Error ? err.message : String(err);
200
- const message = raw.length > 120 ? raw.slice(0, 120) + '\u2026' : raw;
201
- addPollActivity({ type: 'error', text: message });
202
- }
203
- },
204
- });
205
-
206
- agentRef.current = agent;
207
- registerShutdownAgent(async () => {
208
- await agent.stop();
209
- });
210
- await agent.start();
211
- setConnected(true);
212
-
213
- const bio = config.bio ?? '';
214
- if (bio) {
215
- addPollActivity({
216
- type: 'online',
217
- text: `${config.name} agent online \u2014 "${bio}"`,
218
- });
219
- }
220
- };
221
-
222
- start().catch((err) => {
223
- const raw = err instanceof Error ? err.message : String(err);
224
- const isNameTaken = raw.includes('409');
225
- const hint = isNameTaken ? ' Change the name in SOUL.md under "# Agent: <name>".' : '';
226
- addPollActivity({ type: 'error', text: `Fatal: ${raw.slice(0, 120)}${hint}` });
227
- });
228
-
229
- return () => {
230
- agentRef.current?.stop().catch(() => {});
231
- };
232
- }, []);
233
-
234
- // ─── Chat submission ────────────────────────────────
235
-
236
- const handleChatSubmit = useCallback(
237
- async (message: string) => {
238
- if (!message.trim() || chatStreaming) {
239
- return;
240
- }
241
-
242
- addChatActivity({ type: 'chat-user', text: message });
243
- sessionMessagesRef.current.push({ role: 'user', content: message });
244
-
245
- chatCountSinceExtractRef.current += 1;
246
- if (chatCountSinceExtractRef.current >= 3 && !extractingRef.current) {
247
- extractingRef.current = true;
248
- const messagesSnapshot = [...sessionMessagesRef.current];
249
- extractAndSaveMemory(messagesSnapshot)
250
- .then((newMemory) => {
251
- if (newMemory !== null) {
252
- memoryRef.current = newMemory;
253
- }
254
- chatCountSinceExtractRef.current = 0;
255
- })
256
- .catch(() => {})
257
- .finally(() => {
258
- extractingRef.current = false;
259
- });
260
- }
261
-
262
- setChatStreaming(true);
263
- setChatBuffer('');
264
-
265
- try {
266
- const prompt = await buildChatPrompt({
267
- recentThreadSummaries: recentThreadsRef.current,
268
- recentPredictions: recentPredictionsRef.current,
269
- sessionMessages: sessionMessagesRef.current.slice(-20),
270
- memory: memoryRef.current,
271
- userMessage: message,
272
- });
273
-
274
- const result = streamText({
275
- model: openai('gpt-4o'),
276
- prompt,
277
- tools: { editSection: editSectionTool, fetchRules: fetchRulesTool },
278
- stopWhen: stepCountIs(2),
279
- maxOutputTokens: 600,
280
- });
281
-
282
- let fullResponse = '';
283
-
284
- for await (const chunk of result.textStream) {
285
- fullResponse += chunk;
286
- setChatBuffer(fullResponse);
287
- }
288
-
289
- // Surface tool results when the model didn't produce follow-up text
290
- const steps = await result.steps;
291
- for (const step of steps) {
292
- for (const toolResult of step.toolResults) {
293
- const output = String(toolResult.output);
294
- if (!fullResponse.includes(output)) {
295
- const suffix = `\n[${output}]`;
296
- fullResponse += suffix;
297
- setChatBuffer(fullResponse);
298
- }
299
- }
300
- }
301
-
302
- sessionMessagesRef.current.push({ role: 'assistant', content: fullResponse });
303
- addChatActivity({ type: 'chat-agent', text: fullResponse });
304
- setChatBuffer('');
305
- } catch (err) {
306
- const raw = err instanceof Error ? err.message : String(err);
307
- addChatActivity({ type: 'chat-error', text: `Chat error: ${raw.slice(0, 120)}` });
308
- } finally {
309
- setChatStreaming(false);
310
- }
311
- },
312
- [chatStreaming, addChatActivity],
313
- );
314
-
315
- // ─── Boot transition ────────────────────────────────
316
-
317
- const handleBootComplete = useCallback(() => {
318
- setPhase('running');
319
- }, []);
320
-
321
- return {
322
- phase,
323
- connected,
324
- agentName,
325
- agentBio,
326
- pollActivity,
327
- chatActivity,
328
- input,
329
- chatStreaming,
330
- chatBuffer,
331
- predictionCount,
332
- termWidth,
333
- setInput,
334
- handleChatSubmit,
335
- handleBootComplete,
336
- };
337
- }