@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
@@ -0,0 +1,83 @@
1
+ import { Command } from 'commander';
2
+ import { z } from 'zod';
3
+ import { HiveClient, loadConfig, } from '@zhive/sdk';
4
+ import { styled, symbols } from '../../shared/theme.js';
5
+ import { HIVE_API_URL } from '../../../shared/config/constant.js';
6
+ import { findAgentByName, scanAgents } from '../../../shared/config/agent.js';
7
+ import { printZodError } from '../../shared/ validation.js';
8
+ const convictionSchema = z
9
+ .object({
10
+ round: z.string().min(1),
11
+ conviction: z.coerce.number().min(-100).max(100),
12
+ text: z.string().min(1),
13
+ })
14
+ .array();
15
+ const CreateCommentsOptionsSchema = z.object({
16
+ agent: z.string().min(1),
17
+ json: z.string().transform((val, ctx) => {
18
+ try {
19
+ const parsed = convictionSchema.parse(JSON.parse(val));
20
+ return parsed;
21
+ }
22
+ catch (e) {
23
+ ctx.addIssue({
24
+ code: 'custom',
25
+ message: 'Invalid input',
26
+ });
27
+ return z.NEVER;
28
+ }
29
+ }),
30
+ });
31
+ export function createMegathreadCreateCommentsCommand() {
32
+ return new Command('create-comments')
33
+ .description('Batch create megathread comment')
34
+ .requiredOption('--agent <name>', 'Agent name')
35
+ .requiredOption('--json <object>', 'comment array')
36
+ .action(async (options) => {
37
+ const parseResult = CreateCommentsOptionsSchema.safeParse(options);
38
+ if (!parseResult.success) {
39
+ printZodError(parseResult);
40
+ process.exit(1);
41
+ }
42
+ const { agent: agentName, json } = parseResult.data;
43
+ const agentConfig = await findAgentByName(agentName);
44
+ if (!agentConfig) {
45
+ const agents = await scanAgents();
46
+ if (agents.length === 0) {
47
+ console.error(styled.red(`${symbols.cross} No agents found. Create one with: npx @zhive/cli@latest create`));
48
+ }
49
+ else {
50
+ const availableNames = agents.map((a) => a.name).join(', ');
51
+ console.error(styled.red(`${symbols.cross} Agent "${agentName}" not found. Available agents: ${availableNames}`));
52
+ }
53
+ process.exit(1);
54
+ }
55
+ const credentials = await loadConfig(agentConfig.dir);
56
+ if (!credentials?.apiKey) {
57
+ console.error(styled.red(`${symbols.cross} No credentials found for agent "${agentName}". The agent may need to be registered first.`));
58
+ process.exit(1);
59
+ }
60
+ const client = new HiveClient(HIVE_API_URL, credentials.apiKey);
61
+ const payload = {
62
+ comments: [],
63
+ };
64
+ for (const item of json) {
65
+ payload.comments.push({
66
+ roundId: item.round,
67
+ conviction: item.conviction,
68
+ text: item.text,
69
+ });
70
+ }
71
+ try {
72
+ await client.postBatchMegathreadComments(payload);
73
+ console.log('');
74
+ console.log(styled.green(`${symbols.check} ${payload.comments.length} Comments posted successfully!`));
75
+ console.log('');
76
+ }
77
+ catch (error) {
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ console.error(styled.red(`${symbols.cross} Failed to post comment: ${message}`));
80
+ process.exit(1);
81
+ }
82
+ });
83
+ }
@@ -1,9 +1,11 @@
1
1
  import { Command } from 'commander';
2
2
  import { createMegathreadListCommand } from './list.js';
3
3
  import { createMegathreadCreateCommentCommand } from './create-comment.js';
4
+ import { createMegathreadCreateCommentsCommand } from './create-comments.js';
4
5
  export function createMegathreadCommand() {
5
6
  const megathreadCommand = new Command('megathread').description('Megathread operations');
6
7
  megathreadCommand.addCommand(createMegathreadListCommand());
7
8
  megathreadCommand.addCommand(createMegathreadCreateCommentCommand());
9
+ megathreadCommand.addCommand(createMegathreadCreateCommentsCommand());
8
10
  return megathreadCommand;
9
11
  }
@@ -1,8 +1,8 @@
1
1
  import { Command } from 'commander';
2
- import { HiveClient, durationMsToTimeframe } from '@zhive/sdk';
2
+ import { HiveClient, durationMsToTimeframe, loadConfig } from '@zhive/sdk';
3
3
  import { styled, symbols, border } from '../../shared/theme.js';
4
4
  import { HIVE_API_URL } from '../../../shared/config/constant.js';
5
- import { findAgentByName, loadAgentCredentials, scanAgents } from '../../../shared/config/agent.js';
5
+ import { findAgentByName, scanAgents } from '../../../shared/config/agent.js';
6
6
  import z from 'zod';
7
7
  import { printZodError } from '../../shared/ validation.js';
8
8
  const VALID_TIMEFRAMES = ['1h', '4h', '24h'];
@@ -50,12 +50,12 @@ export function createMegathreadListCommand() {
50
50
  }
51
51
  process.exit(1);
52
52
  }
53
- const credentials = await loadAgentCredentials(agentConfig.dir, agentConfig.name);
54
- if (!credentials?.apiKey) {
53
+ const config = await loadConfig(agentConfig.dir);
54
+ if (!config?.apiKey) {
55
55
  console.error(styled.red(`${symbols.cross} No credentials found for agent "${agentName}". The agent may need to be registered first.`));
56
56
  process.exit(1);
57
57
  }
58
- const client = new HiveClient(HIVE_API_URL, credentials.apiKey);
58
+ const client = new HiveClient(HIVE_API_URL, config.apiKey);
59
59
  try {
60
60
  const rounds = await client.getUnpredictedRounds(timeframes);
61
61
  console.log('');
@@ -17,7 +17,7 @@ vi.mock('@zhive/sdk', async () => {
17
17
  HiveClient: vi.fn().mockImplementation(() => ({
18
18
  getUnpredictedRounds: vi.fn(),
19
19
  })),
20
- loadCredentials: vi.fn(),
20
+ loadConfig: vi.fn(),
21
21
  TIMEFRAME_DURATION_MS: {
22
22
  H1: 3600000,
23
23
  H4: 14400000,
@@ -30,10 +30,10 @@ vi.mock('@zhive/sdk', async () => {
30
30
  },
31
31
  };
32
32
  });
33
- import { HiveClient, loadCredentials } from '@zhive/sdk';
33
+ import { HiveClient, loadConfig } from '@zhive/sdk';
34
34
  import { createMegathreadListCommand } from './list.js';
35
35
  const MockHiveClient = HiveClient;
36
- const mockLoadCredentials = loadCredentials;
36
+ const mockLoadConfig = loadConfig;
37
37
  function createMockActiveRound(overrides = {}) {
38
38
  return {
39
39
  roundId: 'round-123',
@@ -88,21 +88,21 @@ describe('createMegathreadListCommand', () => {
88
88
  expect(consoleErrorOutput.length).toBeGreaterThan(0);
89
89
  });
90
90
  it('accepts valid timeframe values', async () => {
91
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
91
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
92
92
  mockGetUnpredictedRounds.mockResolvedValue([]);
93
93
  const command = createMegathreadListCommand();
94
94
  await command.parseAsync(['--agent', 'test-agent', '--timeframe', '1h,4h'], { from: 'user' });
95
95
  expect(mockGetUnpredictedRounds).toHaveBeenCalledWith(['1h', '4h']);
96
96
  });
97
97
  it('accepts single valid timeframe', async () => {
98
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
98
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
99
99
  mockGetUnpredictedRounds.mockResolvedValue([]);
100
100
  const command = createMegathreadListCommand();
101
101
  await command.parseAsync(['--agent', 'test-agent', '--timeframe', '24h'], { from: 'user' });
102
102
  expect(mockGetUnpredictedRounds).toHaveBeenCalledWith(['24h']);
103
103
  });
104
104
  it('passes undefined when no timeframe filter specified', async () => {
105
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
105
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
106
106
  mockGetUnpredictedRounds.mockResolvedValue([]);
107
107
  const command = createMegathreadListCommand();
108
108
  await command.parseAsync(['--agent', 'test-agent'], { from: 'user' });
@@ -122,13 +122,13 @@ describe('createMegathreadListCommand', () => {
122
122
  });
123
123
  describe('credentials validation', () => {
124
124
  it('shows error when credentials are missing', async () => {
125
- mockLoadCredentials.mockResolvedValue(null);
125
+ mockLoadConfig.mockResolvedValue(null);
126
126
  const command = createMegathreadListCommand();
127
127
  await expect(command.parseAsync(['--agent', 'test-agent'], { from: 'user' })).rejects.toThrow('process.exit(1)');
128
128
  expect(consoleErrorOutput.join('\n')).toContain('No credentials found for agent "test-agent"');
129
129
  });
130
130
  it('shows error when credentials have no API key', async () => {
131
- mockLoadCredentials.mockResolvedValue({ apiKey: null });
131
+ mockLoadConfig.mockResolvedValue({ apiKey: null });
132
132
  const command = createMegathreadListCommand();
133
133
  await expect(command.parseAsync(['--agent', 'test-agent'], { from: 'user' })).rejects.toThrow('process.exit(1)');
134
134
  expect(consoleErrorOutput.join('\n')).toContain('No credentials found');
@@ -136,7 +136,7 @@ describe('createMegathreadListCommand', () => {
136
136
  });
137
137
  describe('rounds display', () => {
138
138
  it('shows message when no unpredicted rounds available', async () => {
139
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
139
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
140
140
  mockGetUnpredictedRounds.mockResolvedValue([]);
141
141
  const command = createMegathreadListCommand();
142
142
  await command.parseAsync(['--agent', 'test-agent'], { from: 'user' });
@@ -149,7 +149,7 @@ describe('createMegathreadListCommand', () => {
149
149
  createMockActiveRound({ roundId: 'round-1', projectId: 'bitcoin', durationMs: 3600000 }),
150
150
  createMockActiveRound({ roundId: 'round-2', projectId: 'ethereum', durationMs: 14400000 }),
151
151
  ];
152
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
152
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
153
153
  mockGetUnpredictedRounds.mockResolvedValue(mockRounds);
154
154
  const command = createMegathreadListCommand();
155
155
  await command.parseAsync(['--agent', 'test-agent'], { from: 'user' });
@@ -168,7 +168,7 @@ describe('createMegathreadListCommand', () => {
168
168
  const mockRounds = [
169
169
  createMockActiveRound({ roundId: 'round-1', projectId: 'bitcoin', durationMs: 7200000 }),
170
170
  ];
171
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
171
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
172
172
  mockGetUnpredictedRounds.mockResolvedValue(mockRounds);
173
173
  const command = createMegathreadListCommand();
174
174
  await command.parseAsync(['--agent', 'test-agent'], { from: 'user' });
@@ -178,7 +178,7 @@ describe('createMegathreadListCommand', () => {
178
178
  });
179
179
  describe('API error handling', () => {
180
180
  it('shows error when API call fails', async () => {
181
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
181
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
182
182
  mockGetUnpredictedRounds.mockRejectedValue(new Error('Network error'));
183
183
  const command = createMegathreadListCommand();
184
184
  await expect(command.parseAsync(['--agent', 'test-agent'], { from: 'user' })).rejects.toThrow('process.exit(1)');
@@ -186,7 +186,7 @@ describe('createMegathreadListCommand', () => {
186
186
  expect(consoleErrorOutput.join('\n')).toContain('Network error');
187
187
  });
188
188
  it('handles non-Error exceptions', async () => {
189
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
189
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
190
190
  mockGetUnpredictedRounds.mockRejectedValue('String error');
191
191
  const command = createMegathreadListCommand();
192
192
  await expect(command.parseAsync(['--agent', 'test-agent'], { from: 'user' })).rejects.toThrow('process.exit(1)');
@@ -196,7 +196,7 @@ describe('createMegathreadListCommand', () => {
196
196
  });
197
197
  describe('works with different fixture agents', () => {
198
198
  it('works with empty-agent', async () => {
199
- mockLoadCredentials.mockResolvedValue({ apiKey: 'test-api-key' });
199
+ mockLoadConfig.mockResolvedValue({ apiKey: 'test-api-key' });
200
200
  mockGetUnpredictedRounds.mockResolvedValue([]);
201
201
  const command = createMegathreadListCommand();
202
202
  await command.parseAsync(['--agent', 'empty-agent'], { from: 'user' });
@@ -1,4 +1,4 @@
1
- import { credentialsPath, loadCredentials } from '@zhive/sdk';
1
+ import { loadConfig } from '@zhive/sdk';
2
2
  import { HIVE_API_URL } from '../../../shared/config/constant.js';
3
3
  import { extractErrorMessage } from '../../../shared/agent/utils.js';
4
4
  import { styled } from '../../shared/theme.js';
@@ -50,13 +50,12 @@ function getOutcomeStr(pred) {
50
50
  return `[WIN] +${pred.honey.toFixed(2)} Honey`;
51
51
  }
52
52
  if (pred.wax > 0) {
53
- return `[WIN] +${pred.wax.toFixed(2)} Wax`;
53
+ return `[LOSS] +${pred.wax.toFixed(2)} Wax`;
54
54
  }
55
55
  return '[LOSS]';
56
56
  }
57
57
  export async function predictionSlashCommand(agentName, callbacks) {
58
- const filePath = credentialsPath(agentName);
59
- const credentials = await loadCredentials(filePath);
58
+ const credentials = await loadConfig();
60
59
  if (!credentials?.apiKey) {
61
60
  callbacks.onError?.('Agent not registered yet. Wait for agent to start.');
62
61
  return;
@@ -7,7 +7,6 @@ import { fetchRulesTool } from '../../../shared/agent/tools/fetch-rules.js';
7
7
  import { extractErrorMessage } from '../../../shared/agent/utils.js';
8
8
  import { loadAgentConfig } from '../../../shared/config/agent.js';
9
9
  import { getModel } from '../../../shared/config/ai-providers.js';
10
- import { backtestSlashCommand } from '../commands/backtest.js';
11
10
  import { predictionSlashCommand } from '../commands/prediction.js';
12
11
  import { skillsSlashCommand } from '../commands/skills.js';
13
12
  import { SLASH_COMMANDS } from '../services/command-registry.js';
@@ -73,46 +72,46 @@ export function useChat(agentName) {
73
72
  const memoryOutput = memoryRef.current || 'No memory stored yet.';
74
73
  addChatActivity({ type: 'chat-agent', text: memoryOutput });
75
74
  },
76
- '/backtest': async () => {
77
- const config = {
78
- agentPath: process.cwd(),
79
- soulContent: soulContentRef.current,
80
- strategyContent: strategyContentRef.current,
81
- agentName: agentName,
82
- };
83
- await backtestSlashCommand(parts.slice(1), config, {
84
- onFetchStart: (numThreads) => {
85
- addChatActivity({
86
- type: 'chat-agent',
87
- text: `Fetching ${numThreads} resolved threads...`,
88
- });
89
- },
90
- onFetchError: (error) => {
91
- addChatActivity({
92
- type: 'chat-agent',
93
- text: `API fetch failed (${error}), falling back to default dataset...`,
94
- });
95
- addChatActivity({
96
- type: 'chat-agent',
97
- text: 'Starting backtest against default dataset...',
98
- });
99
- },
100
- onThreadStart: (index, total, thread) => {
101
- addChatActivity({
102
- type: 'chat-agent',
103
- text: `Processing ${index + 1}/${total}: ${thread.project_name}...`,
104
- });
105
- },
106
- onBacktestSuccess: (report) => {
107
- addChatActivity({ type: 'chat-agent', text: report });
108
- sessionMessagesRef.current.push({ role: 'assistant', content: report });
109
- },
110
- onBacktestError: (err) => {
111
- const errMessage = extractErrorMessage(err);
112
- addChatActivity({ type: 'chat-error', text: `Backtest failed: ${errMessage}` });
113
- },
114
- });
115
- },
75
+ // '/backtest': async () => {
76
+ // const config: RunnerConfig = {
77
+ // agentPath: process.cwd(),
78
+ // soulContent: soulContentRef.current,
79
+ // strategyContent: strategyContentRef.current,
80
+ // agentName: agentName,
81
+ // };
82
+ // await backtestSlashCommand(parts.slice(1), config, {
83
+ // onFetchStart: (numThreads) => {
84
+ // addChatActivity({
85
+ // type: 'chat-agent',
86
+ // text: `Fetching ${numThreads} resolved threads...`,
87
+ // });
88
+ // },
89
+ // onFetchError: (error: string) => {
90
+ // addChatActivity({
91
+ // type: 'chat-agent',
92
+ // text: `API fetch failed (${error}), falling back to default dataset...`,
93
+ // });
94
+ // addChatActivity({
95
+ // type: 'chat-agent',
96
+ // text: 'Starting backtest against default dataset...',
97
+ // });
98
+ // },
99
+ // onThreadStart: (index, total, thread) => {
100
+ // addChatActivity({
101
+ // type: 'chat-agent',
102
+ // text: `Processing ${index + 1}/${total}: ${thread.project_name}...`,
103
+ // });
104
+ // },
105
+ // onBacktestSuccess: (report: string) => {
106
+ // addChatActivity({ type: 'chat-agent', text: report });
107
+ // sessionMessagesRef.current.push({ role: 'assistant', content: report });
108
+ // },
109
+ // onBacktestError: (err: unknown) => {
110
+ // const errMessage = extractErrorMessage(err);
111
+ // addChatActivity({ type: 'chat-error', text: `Backtest failed: ${errMessage}` });
112
+ // },
113
+ // });
114
+ // },
116
115
  '/prediction': async () => {
117
116
  await predictionSlashCommand(agentName, {
118
117
  onFetchStart: () => {
@@ -3,7 +3,7 @@ export const SLASH_COMMANDS = [
3
3
  { name: '/help', description: 'Show available commands' },
4
4
  { name: '/clear', description: 'Clear chat history' },
5
5
  { name: '/memory', description: 'Show current memory state' },
6
- { name: '/backtest', description: 'Run agent against test set (/backtest <num> fetches from API)' },
6
+ // { name: '/backtest', description: 'Run agent against test set (/backtest <num> fetches from API)' },
7
7
  { name: '/prediction', description: 'Show your last 10 resolved predictions' },
8
8
  ];
9
9
  export function filterCommands(prefix) {
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { createStartCommand } from './commands/start/commands/index.js';
9
9
  import { createStartAllCommand } from './commands/start-all/commands/index.js';
10
10
  import { createRunCommand } from './commands/run/commands/index.js';
11
11
  import { createMigrateTemplatesCommand } from './commands/migrate-templates/commands/index.js';
12
+ import { createDoctorCommand } from './commands/doctor/commands/index.js';
12
13
  const require = createRequire(import.meta.url);
13
14
  const packageJson = require('../package.json');
14
15
  const program = new Command();
@@ -21,6 +22,7 @@ program.addCommand(createStartCommand());
21
22
  program.addCommand(createStartAllCommand());
22
23
  program.addCommand(createRunCommand());
23
24
  program.addCommand(createMigrateTemplatesCommand());
25
+ program.addCommand(createDoctorCommand());
24
26
  // Show help with exit code 0 when no arguments provided
25
27
  const args = process.argv.slice(2);
26
28
  if (args.length === 0) {
@@ -1,10 +1,10 @@
1
1
  import { generateText, Output, ToolLoopAgent } from 'ai';
2
2
  import { z } from 'zod';
3
- import { buildAnalystPrompt, buildMegathreadPrompt } from './prompt.js';
4
- import { loadMemory, saveMemory, getMemoryLineCount, MEMORY_SOFT_LIMIT } from '@hive-org/sdk';
5
- import { buildMemoryExtractionPrompt } from './memory-prompt.js';
3
+ import { buildAnalystPrompt, buildMegathreadPrompt } from './prompts/prompt.js';
4
+ import { loadMemory, saveMemory, getMemoryLineCount, MEMORY_SOFT_LIMIT, } from '@hive-org/sdk';
5
+ import { buildMemoryExtractionPrompt } from './prompts/memory-prompt.js';
6
6
  import { stripCodeFences } from './helpers.js';
7
- import { getModel } from './model.js';
7
+ import { getModel } from './helpers/model.js';
8
8
  // ─── Cache Helpers ─────────────────────────────────
9
9
  function cacheableSystem(content) {
10
10
  const message = {
@@ -146,7 +146,7 @@ export async function extractAndSaveMemory(sessionMessages) {
146
146
  const model = await getModel();
147
147
  const { text } = await generateText({
148
148
  model,
149
- messages: [cacheableSystem(prompt.system), { role: 'user', content: prompt.prompt }],
149
+ prompt,
150
150
  });
151
151
  const cleaned = stripCodeFences(text);
152
152
  await saveMemory(cleaned);
@@ -1,5 +1,5 @@
1
1
  import { readFileSync } from 'fs';
2
- import { AI_PROVIDER_ENV_VARS } from './ai-providers.js';
2
+ import { AI_PROVIDER_ENV_VARS } from '../ai-providers.js';
3
3
  let _agentProviderKeys = new Set();
4
4
  /**
5
5
  * Provider env-var names declared in the agent's .env file.
@@ -1,5 +1,5 @@
1
- import { AI_PROVIDERS } from '../ai-providers.js';
2
- import { getAgentProviderKeys } from '../load-agent-env.js';
1
+ import { AI_PROVIDERS } from '../../ai-providers.js';
2
+ import { getAgentProviderKeys } from '../env.js';
3
3
  const PROVIDERS = [
4
4
  {
5
5
  label: 'Anthropic',
@@ -1,9 +1,25 @@
1
1
  export function buildMemoryExtractionPrompt(context) {
2
2
  const { currentMemory, sessionMessages, lineCount } = context;
3
- // ── System (static — cached by providers) ──
4
- const system = `You are an AI trading agent's memory system. Your job is to maintain conversational continuity between sessions with the agent's operator.
3
+ let sessionSection = '';
4
+ if (sessionMessages.length > 0) {
5
+ const listed = sessionMessages
6
+ .map((m) => `${m.role === 'user' ? 'Operator' : 'Agent'}: ${m.content}`)
7
+ .join('\n');
8
+ sessionSection = `\n## Session Chat Log\n\n${listed}\n`;
9
+ }
10
+ const currentMemorySection = currentMemory.trim().length > 0
11
+ ? `\n## Current MEMORY.md\n\n\`\`\`markdown\n${currentMemory}\n\`\`\`\n`
12
+ : '\n## Current MEMORY.md\n\n(empty - this is a fresh agent)\n';
13
+ const consolidationNote = lineCount > 200
14
+ ? `\n**IMPORTANT: The current memory is ${lineCount} lines, exceeding the 200-line soft limit. Aggressively consolidate: merge related items, remove outdated or low-value entries, and keep only the most important context.**\n`
15
+ : '';
16
+ const prompt = `You are an AI trading agent's memory system. Your job is to maintain conversational continuity between sessions with the agent's operator.
17
+ ${currentMemorySection}${consolidationNote}
18
+ ## Session Activity
19
+ ${sessionSection}
20
+ ## Instructions
5
21
 
6
- Review the session data and update the agent's MEMORY.md file. This memory is about **conversational continuity** — making the agent feel like it remembers past sessions with its operator.
22
+ Review the session chat log above and update the agent's MEMORY.md file. This memory is about **conversational continuity** — making the agent feel like it remembers past sessions with its operator.
7
23
 
8
24
  Focus on extracting:
9
25
  1. **Topics discussed** — what subjects came up in conversation (e.g., "we talked about ETH gas fees", "operator asked about macro outlook")
@@ -25,23 +41,5 @@ Follow these rules:
25
41
  6. **Keep it under ~200 lines** — This file is injected into every prompt, so brevity matters.
26
42
 
27
43
  Output the complete updated MEMORY.md content. Start with \`# Memory\` as the top-level header. Output ONLY the markdown content, no code fences or explanation.`;
28
- // ── Prompt (dynamic — changes every call) ──
29
- let sessionSection = '';
30
- if (sessionMessages.length > 0) {
31
- const listed = sessionMessages
32
- .map((m) => `${m.role === 'user' ? 'Operator' : 'Agent'}: ${m.content}`)
33
- .join('\n');
34
- sessionSection = `\n## Session Chat Log\n\n${listed}\n`;
35
- }
36
- const currentMemorySection = currentMemory.trim().length > 0
37
- ? `\n## Current MEMORY.md\n\n\`\`\`markdown\n${currentMemory}\n\`\`\`\n`
38
- : '\n## Current MEMORY.md\n\n(empty - this is a fresh agent)\n';
39
- const consolidationNote = lineCount > 200
40
- ? `\n**IMPORTANT: The current memory is ${lineCount} lines, exceeding the 200-line soft limit. Aggressively consolidate: merge related items, remove outdated or low-value entries, and keep only the most important context.**\n`
41
- : '';
42
- const prompt = `${currentMemorySection}${consolidationNote}
43
- ## Session Activity
44
- ${sessionSection}
45
- Update the MEMORY.md based on the session activity above.`;
46
- return { system, prompt };
44
+ return prompt;
47
45
  }