@zhive/cli 0.6.7 → 0.6.8

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 (66) 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 -9
  5. package/dist/commands/create/presets.js +613 -0
  6. package/dist/commands/indicator/commands/bollinger.js +37 -0
  7. package/dist/commands/indicator/commands/ema.js +37 -0
  8. package/dist/commands/indicator/commands/index.js +14 -0
  9. package/dist/commands/indicator/commands/macd.js +51 -0
  10. package/dist/commands/indicator/commands/rsi.js +37 -0
  11. package/dist/commands/indicator/commands/sma.js +37 -0
  12. package/dist/commands/market/commands/index.js +5 -0
  13. package/dist/commands/market/commands/price.js +25 -0
  14. package/dist/commands/shared/utils.js +12 -0
  15. package/dist/commands/start/ui/AsciiTicker.js +81 -0
  16. package/dist/index.js +4 -0
  17. package/dist/services/agent/analysis.js +160 -0
  18. package/dist/services/agent/config.js +75 -0
  19. package/dist/services/agent/env.js +30 -0
  20. package/dist/services/agent/helpers/model.js +92 -0
  21. package/dist/services/agent/helpers.js +22 -0
  22. package/dist/services/agent/prompts/chat-prompt.js +65 -0
  23. package/dist/services/agent/prompts/memory-prompt.js +45 -0
  24. package/dist/services/agent/prompts/prompt.js +379 -0
  25. package/dist/services/agent/skills/index.js +2 -0
  26. package/dist/services/agent/skills/skill-parser.js +149 -0
  27. package/dist/services/agent/skills/types.js +1 -0
  28. package/dist/services/agent/tools/edit-section.js +59 -0
  29. package/dist/services/agent/tools/fetch-rules.js +21 -0
  30. package/dist/services/agent/tools/index.js +76 -0
  31. package/dist/services/agent/tools/market/client.js +41 -0
  32. package/dist/services/agent/tools/market/index.js +3 -0
  33. package/dist/services/agent/tools/market/tools.js +518 -0
  34. package/dist/services/agent/tools/mindshare/client.js +124 -0
  35. package/dist/services/agent/tools/mindshare/index.js +3 -0
  36. package/dist/services/agent/tools/mindshare/tools.js +563 -0
  37. package/dist/services/agent/tools/read-skill-tool.js +30 -0
  38. package/dist/services/agent/tools/ta/index.js +1 -0
  39. package/dist/services/agent/tools/ta/indicators.js +201 -0
  40. package/dist/services/agent/types.js +1 -0
  41. package/dist/services/ai-providers.js +66 -0
  42. package/dist/services/config/agent.js +110 -0
  43. package/dist/services/config/config.js +22 -0
  44. package/dist/services/config/constant.js +8 -0
  45. package/dist/shared/agent/agent-runtime.js +144 -0
  46. package/dist/shared/agent/analysis.js +2 -12
  47. package/dist/shared/agent/cache.js +10 -0
  48. package/dist/shared/agent/config.js +75 -0
  49. package/dist/shared/agent/env.js +30 -0
  50. package/dist/shared/agent/handler.js +3 -9
  51. package/dist/shared/agent/helpers/model.js +92 -0
  52. package/dist/shared/agent/prompts/megathread.js +0 -8
  53. package/dist/shared/agent/tools/execute-skill-tool.js +2 -1
  54. package/dist/shared/agent/tools/formatting.js +0 -19
  55. package/dist/shared/agent/tools/market/client.js +3 -3
  56. package/dist/shared/agent/tools/market/tools.js +88 -312
  57. package/dist/shared/agent/tools/market/utils.js +71 -0
  58. package/dist/shared/agent/tools/mindshare/tools.js +1 -1
  59. package/dist/shared/agent/tools/ta/index.js +3 -1
  60. package/dist/shared/agent/types.js +1 -0
  61. package/dist/shared/agent/utils.js +44 -0
  62. package/dist/shared/ai-providers.js +66 -0
  63. package/dist/shared/ta/error.js +12 -0
  64. package/dist/shared/ta/service.js +93 -0
  65. package/dist/shared/ta/utils.js +16 -0
  66. package/package.json +2 -1
@@ -0,0 +1,30 @@
1
+ import { readFileSync } from 'fs';
2
+ import { AI_PROVIDER_ENV_VARS } from '../ai-providers.js';
3
+ let _agentProviderKeys = new Set();
4
+ /**
5
+ * Provider env-var names declared in the agent's .env file.
6
+ * Used by getModel() to prioritize the agent's chosen provider
7
+ * over keys inherited from the shell.
8
+ */
9
+ export function getAgentProviderKeys() {
10
+ return _agentProviderKeys;
11
+ }
12
+ /**
13
+ * Load the agent's .env with provider-key priority.
14
+ *
15
+ * 1. Parse .env to discover which provider keys the agent declared.
16
+ * 2. Load .env with override so the agent's values win for the same key.
17
+ * 3. getModel() uses getAgentProviderKeys() to check those providers first,
18
+ * falling back to shell-inherited keys if the agent has none.
19
+ */
20
+ export async function loadAgentEnv() {
21
+ try {
22
+ const content = readFileSync('.env', 'utf-8');
23
+ _agentProviderKeys = new Set(AI_PROVIDER_ENV_VARS.filter((key) => new RegExp(`^${key}=`, 'm').test(content)));
24
+ }
25
+ catch {
26
+ _agentProviderKeys = new Set();
27
+ }
28
+ const { config } = await import('dotenv');
29
+ config({ override: true });
30
+ }
@@ -1,19 +1,13 @@
1
1
  import { processMegathreadRound, screenMegathreadRound, } from './analysis.js';
2
- import { getMarketClient } from './tools/market/index.js';
3
2
  import { extractErrorMessage } from './utils.js';
4
- export const fetchPrice = async (projectId, timestamp) => {
5
- const client = getMarketClient();
6
- const response = await client.getPrice(projectId, timestamp);
7
- return response.price ?? undefined;
8
- };
3
+ import { getPrice } from '../ta/service.js';
9
4
  export async function fetchRoundPrices(projectId, roundTimestamp, currentTime) {
10
5
  let priceAtStart;
11
6
  let currentPrice;
12
7
  try {
13
- const client = getMarketClient();
14
8
  [priceAtStart, currentPrice] = await Promise.all([
15
- fetchPrice(projectId, roundTimestamp),
16
- fetchPrice(projectId, currentTime ?? new Date().toISOString()),
9
+ getPrice({ project: projectId, at: roundTimestamp }),
10
+ getPrice({ project: projectId, at: currentTime ?? new Date().toISOString() }),
17
11
  ]);
18
12
  }
19
13
  catch {
@@ -0,0 +1,92 @@
1
+ import { AI_PROVIDERS } from '../../ai-providers.js';
2
+ import { getAgentProviderKeys } from '../../config/env-loader.js';
3
+ const PROVIDERS = [
4
+ {
5
+ label: 'Anthropic',
6
+ envVar: 'ANTHROPIC_API_KEY',
7
+ load: async (modelId) => {
8
+ const { anthropic } = await import('@ai-sdk/anthropic');
9
+ return anthropic(modelId);
10
+ },
11
+ },
12
+ {
13
+ label: 'OpenAI',
14
+ envVar: 'OPENAI_API_KEY',
15
+ load: async (modelId) => {
16
+ const { openai } = await import('@ai-sdk/openai');
17
+ return openai(modelId);
18
+ },
19
+ },
20
+ {
21
+ label: 'Google',
22
+ envVar: 'GOOGLE_GENERATIVE_AI_API_KEY',
23
+ load: async (modelId) => {
24
+ const { google } = await import('@ai-sdk/google');
25
+ return google(modelId);
26
+ },
27
+ },
28
+ {
29
+ label: 'xAI',
30
+ envVar: 'XAI_API_KEY',
31
+ load: async (modelId) => {
32
+ const { xai } = await import('@ai-sdk/xai');
33
+ return xai(modelId);
34
+ },
35
+ },
36
+ {
37
+ label: 'OpenRouter',
38
+ envVar: 'OPENROUTER_API_KEY',
39
+ load: async (modelId) => {
40
+ const { createOpenRouter } = await import('@openrouter/ai-sdk-provider');
41
+ const openrouter = createOpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
42
+ return openrouter.chat(modelId);
43
+ },
44
+ },
45
+ ];
46
+ export function resolveModelInfo() {
47
+ const overrideModel = process.env.HIVE_MODEL;
48
+ const agentKeys = getAgentProviderKeys();
49
+ const sortedProviders = [
50
+ ...PROVIDERS.filter((p) => agentKeys.has(p.envVar)),
51
+ ...PROVIDERS.filter((p) => !agentKeys.has(p.envVar)),
52
+ ];
53
+ for (const provider of sortedProviders) {
54
+ const keyValue = process.env[provider.envVar];
55
+ if (keyValue && keyValue.trim().length > 0) {
56
+ const centralProvider = AI_PROVIDERS.find((p) => p.envVar === provider.envVar);
57
+ const runtimeModel = centralProvider?.models.runtime ?? 'unknown';
58
+ const modelId = overrideModel ?? runtimeModel;
59
+ const source = agentKeys.has(provider.envVar) ? '.env' : 'shell';
60
+ return { provider: provider.label, modelId, source };
61
+ }
62
+ }
63
+ return { provider: 'unknown', modelId: 'unknown', source: 'unknown' };
64
+ }
65
+ let _modelPromise = null;
66
+ export function getModel() {
67
+ if (_modelPromise) {
68
+ return _modelPromise;
69
+ }
70
+ _modelPromise = (async () => {
71
+ const info = resolveModelInfo();
72
+ if (info.provider === 'unknown') {
73
+ throw new Error('No AI provider API key found in environment. ' +
74
+ 'Set one of: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, XAI_API_KEY, OPENROUTER_API_KEY');
75
+ }
76
+ const agentKeys = getAgentProviderKeys();
77
+ const sortedProviders = [
78
+ ...PROVIDERS.filter((p) => agentKeys.has(p.envVar)),
79
+ ...PROVIDERS.filter((p) => !agentKeys.has(p.envVar)),
80
+ ];
81
+ for (const provider of sortedProviders) {
82
+ const keyValue = process.env[provider.envVar];
83
+ if (keyValue && keyValue.trim().length > 0) {
84
+ const modelId = info.modelId;
85
+ const model = await provider.load(modelId);
86
+ return model;
87
+ }
88
+ }
89
+ throw new Error('Unreachable: resolveModelInfo succeeded but no provider found');
90
+ })();
91
+ return _modelPromise;
92
+ }
@@ -41,14 +41,6 @@ ${formatSkillList(runtime.skills)}
41
41
 
42
42
  Use the \`executeSkill\` tool to delegate a task to a specialized subagent:
43
43
 
44
- \`\`\`
45
- executeSkill({
46
- skillId: "ta", // Skill with the expertise you need
47
- task: "Analyze RSI and MACD for BTC. Is momentum bullish or bearish?",
48
- context: "Current price: $65,000" // Optional extra context
49
- })
50
- \`\`\`
51
-
52
44
  The subagent will use its expertise to complete YOUR task. You control what the subagent does — the skill provides the knowledge, you provide the instructions.`;
53
45
  }
54
46
  const system = `You are an agent who will be participated in price prediction game. You will be given a context called megathread round. Each round has a project, a duration, and a round-start baseline price. Your conviction = predicted total percent change from the round-start price by end of the round.
@@ -3,6 +3,7 @@ import * as ai from 'ai';
3
3
  import { z } from 'zod';
4
4
  import { wrapAISDK } from 'langsmith/experimental/vercel';
5
5
  import { getAllTools } from './index.js';
6
+ import { cacheableSystem } from '../cache.js';
6
7
  const { ToolLoopAgent } = wrapAISDK(ai);
7
8
  let _subagentUsageLog = [];
8
9
  export function clearSubagentUsage() {
@@ -110,7 +111,7 @@ export function createExecuteSkillTool(skillRegistry, config) {
110
111
  async function runSubagent({ model, systemPrompt, userPrompt, tools, maxOutputTokens, }) {
111
112
  const agent = new ToolLoopAgent({
112
113
  model,
113
- instructions: systemPrompt,
114
+ instructions: cacheableSystem(systemPrompt),
114
115
  tools,
115
116
  maxOutputTokens,
116
117
  });
@@ -17,25 +17,6 @@ export function signPrefix(value) {
17
17
  const prefix = value >= 0 ? '+' : '';
18
18
  return prefix;
19
19
  }
20
- /**
21
- * Truncate a timeseries array for display, keeping head and tail with a `null` gap in between.
22
- * Returns the original array unchanged if it fits within `maxDisplay`.
23
- */
24
- export function truncateTimeseries(data, maxDisplay = 20, headCount = 5, tailCount = 10) {
25
- if (data.length <= maxDisplay) {
26
- return data;
27
- }
28
- const truncated = [...data.slice(0, headCount), null, ...data.slice(-tailCount)];
29
- return truncated;
30
- }
31
- /**
32
- * Label for the truncation gap (e.g. `"... (42 more points) ..."`).
33
- */
34
- export function truncationLabel(totalLength, shownCount) {
35
- const hidden = totalLength - shownCount;
36
- const label = `... (${hidden} more) ...`;
37
- return label;
38
- }
39
20
  /**
40
21
  * Format a period-change percentage from first → last value.
41
22
  * Returns e.g. `"Period change: +12.34%"`.
@@ -7,7 +7,7 @@ export class MarketClient {
7
7
  this._baseUrl = baseUrl;
8
8
  }
9
9
  async getPrice(projectId, timestamp) {
10
- const url = `${this._baseUrl}/market/price/${encodeURIComponent(projectId)}?timestamp=${encodeURIComponent(timestamp)}`;
10
+ const url = `${this._baseUrl}/market/price/${encodeURIComponent(projectId)}?timestamp=${encodeURIComponent(new Date(timestamp).toISOString())}`;
11
11
  const response = await fetch(url);
12
12
  if (!response.ok) {
13
13
  const text = await response.text();
@@ -18,8 +18,8 @@ export class MarketClient {
18
18
  }
19
19
  async getOHLC(id, from, to, interval = 'daily') {
20
20
  const params = new URLSearchParams({
21
- from,
22
- to,
21
+ from: new Date(from).toISOString(),
22
+ to: new Date(to).toISOString(),
23
23
  interval,
24
24
  });
25
25
  const url = `${this._baseUrl}/market/ohlc/${encodeURIComponent(id)}?${params.toString()}`;