@zhive/cli 0.5.0

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 (189) hide show
  1. package/README.md +118 -0
  2. package/dist/agent/analysis.js +160 -0
  3. package/dist/agent/app.js +122 -0
  4. package/dist/agent/chat-prompt.js +65 -0
  5. package/dist/agent/commands/registry.js +12 -0
  6. package/dist/agent/components/AsciiTicker.js +81 -0
  7. package/dist/agent/components/CommandInput.js +65 -0
  8. package/dist/agent/components/HoneycombBoot.js +291 -0
  9. package/dist/agent/components/Spinner.js +37 -0
  10. package/dist/agent/config.js +75 -0
  11. package/dist/agent/edit-section.js +59 -0
  12. package/dist/agent/fetch-rules.js +21 -0
  13. package/dist/agent/helpers.js +22 -0
  14. package/dist/agent/hooks/useAgent.js +480 -0
  15. package/dist/agent/memory-prompt.js +47 -0
  16. package/dist/agent/model.js +92 -0
  17. package/dist/agent/objects.js +1 -0
  18. package/dist/agent/process-lifecycle.js +18 -0
  19. package/dist/agent/prompt.js +353 -0
  20. package/dist/agent/run-headless.js +189 -0
  21. package/dist/agent/skills/index.js +2 -0
  22. package/dist/agent/skills/skill-parser.js +149 -0
  23. package/dist/agent/skills/types.js +1 -0
  24. package/dist/agent/theme.js +41 -0
  25. package/dist/agent/tools/index.js +76 -0
  26. package/dist/agent/tools/market/client.js +41 -0
  27. package/dist/agent/tools/market/index.js +3 -0
  28. package/dist/agent/tools/market/tools.js +518 -0
  29. package/dist/agent/tools/mindshare/client.js +124 -0
  30. package/dist/agent/tools/mindshare/index.js +3 -0
  31. package/dist/agent/tools/mindshare/tools.js +563 -0
  32. package/dist/agent/tools/read-skill-tool.js +30 -0
  33. package/dist/agent/tools/ta/index.js +1 -0
  34. package/dist/agent/tools/ta/indicators.js +201 -0
  35. package/dist/agent/types.js +1 -0
  36. package/dist/agents.js +110 -0
  37. package/dist/ai-providers.js +66 -0
  38. package/dist/avatar.js +34 -0
  39. package/dist/backtest/default-backtest-data.js +200 -0
  40. package/dist/backtest/fetch.js +41 -0
  41. package/dist/backtest/import.js +106 -0
  42. package/dist/backtest/index.js +10 -0
  43. package/dist/backtest/results.js +113 -0
  44. package/dist/backtest/runner.js +134 -0
  45. package/dist/backtest/storage.js +11 -0
  46. package/dist/backtest/types.js +1 -0
  47. package/dist/commands/create/ai-generate.js +126 -0
  48. package/dist/commands/create/commands/index.js +10 -0
  49. package/dist/commands/create/generate.js +73 -0
  50. package/dist/commands/create/presets/data.js +225 -0
  51. package/dist/commands/create/presets/formatting.js +81 -0
  52. package/dist/commands/create/presets/index.js +3 -0
  53. package/dist/commands/create/presets/options.js +307 -0
  54. package/dist/commands/create/presets/types.js +1 -0
  55. package/dist/commands/create/presets.js +613 -0
  56. package/dist/commands/create/ui/CreateApp.js +172 -0
  57. package/dist/commands/create/ui/steps/ApiKeyStep.js +89 -0
  58. package/dist/commands/create/ui/steps/AvatarStep.js +16 -0
  59. package/dist/commands/create/ui/steps/DoneStep.js +14 -0
  60. package/dist/commands/create/ui/steps/IdentityStep.js +125 -0
  61. package/dist/commands/create/ui/steps/NameStep.js +148 -0
  62. package/dist/commands/create/ui/steps/ScaffoldStep.js +59 -0
  63. package/dist/commands/create/ui/steps/SoulStep.js +21 -0
  64. package/dist/commands/create/ui/steps/StrategyStep.js +20 -0
  65. package/dist/commands/create/ui/steps/StreamingGenerationStep.js +56 -0
  66. package/dist/commands/create/ui/validation.js +34 -0
  67. package/dist/commands/create/validate-api-key.js +27 -0
  68. package/dist/commands/install.js +50 -0
  69. package/dist/commands/list/commands/index.js +7 -0
  70. package/dist/commands/list/ui/ListApp.js +79 -0
  71. package/dist/commands/migrate-templates/commands/index.js +9 -0
  72. package/dist/commands/migrate-templates/migrate.js +87 -0
  73. package/dist/commands/migrate-templates/ui/MigrateApp.js +132 -0
  74. package/dist/commands/run/commands/index.js +17 -0
  75. package/dist/commands/run/run-headless.js +111 -0
  76. package/dist/commands/shared/theme.js +57 -0
  77. package/dist/commands/shared/welcome.js +304 -0
  78. package/dist/commands/start/commands/backtest.js +35 -0
  79. package/dist/commands/start/commands/index.js +62 -0
  80. package/dist/commands/start/commands/prediction.js +73 -0
  81. package/dist/commands/start/commands/skills.js +44 -0
  82. package/dist/commands/start/commands/skills.test.js +140 -0
  83. package/dist/commands/start/hooks/types.js +1 -0
  84. package/dist/commands/start/hooks/useAgent.js +177 -0
  85. package/dist/commands/start/hooks/useChat.js +266 -0
  86. package/dist/commands/start/hooks/usePollActivity.js +45 -0
  87. package/dist/commands/start/hooks/utils.js +152 -0
  88. package/dist/commands/start/services/backtest/default-backtest-data.js +200 -0
  89. package/dist/commands/start/services/backtest/fetch.js +42 -0
  90. package/dist/commands/start/services/backtest/import.js +109 -0
  91. package/dist/commands/start/services/backtest/index.js +10 -0
  92. package/dist/commands/start/services/backtest/results.js +113 -0
  93. package/dist/commands/start/services/backtest/runner.js +103 -0
  94. package/dist/commands/start/services/backtest/storage.js +11 -0
  95. package/dist/commands/start/services/backtest/types.js +1 -0
  96. package/dist/commands/start/services/command-registry.js +13 -0
  97. package/dist/commands/start/ui/AsciiTicker.js +81 -0
  98. package/dist/commands/start/ui/CommandInput.js +65 -0
  99. package/dist/commands/start/ui/HoneycombBoot.js +291 -0
  100. package/dist/commands/start/ui/PollText.js +23 -0
  101. package/dist/commands/start/ui/PredictionsPanel.js +88 -0
  102. package/dist/commands/start/ui/SelectAgentApp.js +93 -0
  103. package/dist/commands/start/ui/Spinner.js +29 -0
  104. package/dist/commands/start/ui/SpinnerContext.js +20 -0
  105. package/dist/commands/start/ui/app.js +36 -0
  106. package/dist/commands/start-all/AgentProcessManager.js +98 -0
  107. package/dist/commands/start-all/commands/index.js +24 -0
  108. package/dist/commands/start-all/ui/Dashboard.js +91 -0
  109. package/dist/components/AsciiTicker.js +81 -0
  110. package/dist/components/CharacterSummaryCard.js +33 -0
  111. package/dist/components/CodeBlock.js +11 -0
  112. package/dist/components/ColoredStats.js +18 -0
  113. package/dist/components/Header.js +10 -0
  114. package/dist/components/HoneycombLoader.js +190 -0
  115. package/dist/components/InputGuard.js +6 -0
  116. package/dist/components/MultiSelectPrompt.js +45 -0
  117. package/dist/components/SelectPrompt.js +20 -0
  118. package/dist/components/Spinner.js +16 -0
  119. package/dist/components/StepIndicator.js +31 -0
  120. package/dist/components/StreamingText.js +50 -0
  121. package/dist/components/TextPrompt.js +28 -0
  122. package/dist/components/stdout-spinner.js +48 -0
  123. package/dist/config.js +28 -0
  124. package/dist/create/CreateApp.js +153 -0
  125. package/dist/create/ai-generate.js +147 -0
  126. package/dist/create/generate.js +73 -0
  127. package/dist/create/steps/ApiKeyStep.js +97 -0
  128. package/dist/create/steps/AvatarStep.js +16 -0
  129. package/dist/create/steps/BioStep.js +14 -0
  130. package/dist/create/steps/DoneStep.js +14 -0
  131. package/dist/create/steps/IdentityStep.js +163 -0
  132. package/dist/create/steps/NameStep.js +71 -0
  133. package/dist/create/steps/ScaffoldStep.js +58 -0
  134. package/dist/create/steps/SoulStep.js +58 -0
  135. package/dist/create/steps/StrategyStep.js +58 -0
  136. package/dist/create/validate-api-key.js +47 -0
  137. package/dist/create/welcome.js +304 -0
  138. package/dist/index.js +60 -0
  139. package/dist/list/ListApp.js +79 -0
  140. package/dist/load-agent-env.js +30 -0
  141. package/dist/migrate-templates/MigrateApp.js +131 -0
  142. package/dist/migrate-templates/migrate.js +86 -0
  143. package/dist/presets.js +613 -0
  144. package/dist/shared/agent/agent-runtime.js +144 -0
  145. package/dist/shared/agent/analysis.js +171 -0
  146. package/dist/shared/agent/helpers.js +1 -0
  147. package/dist/shared/agent/prompts/chat-prompt.js +60 -0
  148. package/dist/shared/agent/prompts/megathread.js +202 -0
  149. package/dist/shared/agent/prompts/memory-prompt.js +47 -0
  150. package/dist/shared/agent/prompts/prompt.js +18 -0
  151. package/dist/shared/agent/skills/index.js +2 -0
  152. package/dist/shared/agent/skills/skill-parser.js +167 -0
  153. package/dist/shared/agent/skills/skill-parser.test.js +190 -0
  154. package/dist/shared/agent/skills/types.js +1 -0
  155. package/dist/shared/agent/tools/edit-section.js +60 -0
  156. package/dist/shared/agent/tools/execute-skill-tool.js +134 -0
  157. package/dist/shared/agent/tools/fetch-rules.js +22 -0
  158. package/dist/shared/agent/tools/formatting.js +48 -0
  159. package/dist/shared/agent/tools/index.js +87 -0
  160. package/dist/shared/agent/tools/market/client.js +41 -0
  161. package/dist/shared/agent/tools/market/index.js +3 -0
  162. package/dist/shared/agent/tools/market/tools.js +497 -0
  163. package/dist/shared/agent/tools/mindshare/client.js +124 -0
  164. package/dist/shared/agent/tools/mindshare/index.js +3 -0
  165. package/dist/shared/agent/tools/mindshare/tools.js +167 -0
  166. package/dist/shared/agent/tools/read-skill-tool.js +30 -0
  167. package/dist/shared/agent/tools/ta/index.js +1 -0
  168. package/dist/shared/agent/tools/ta/indicators.js +201 -0
  169. package/dist/shared/agent/types.js +1 -0
  170. package/dist/shared/agent/utils.js +43 -0
  171. package/dist/shared/config/agent.js +177 -0
  172. package/dist/shared/config/ai-providers.js +156 -0
  173. package/dist/shared/config/config.js +22 -0
  174. package/dist/shared/config/constant.js +8 -0
  175. package/dist/shared/config/env-loader.js +30 -0
  176. package/dist/shared/types.js +1 -0
  177. package/dist/start/AgentProcessManager.js +98 -0
  178. package/dist/start/Dashboard.js +92 -0
  179. package/dist/start/SelectAgentApp.js +81 -0
  180. package/dist/start/StartApp.js +189 -0
  181. package/dist/start/patch-headless.js +101 -0
  182. package/dist/start/patch-managed-mode.js +142 -0
  183. package/dist/start/start-command.js +24 -0
  184. package/dist/theme.js +54 -0
  185. package/package.json +68 -0
  186. package/templates/components/HoneycombBoot.tsx +343 -0
  187. package/templates/fetch-rules.ts +23 -0
  188. package/templates/skills/mindshare/SKILL.md +197 -0
  189. package/templates/skills/ta/SKILL.md +179 -0
@@ -0,0 +1,124 @@
1
+ import { HIVE_API_URL } from '../../../config/constant.js';
2
+ export class MindshareClient {
3
+ constructor(baseUrl = HIVE_API_URL) {
4
+ this._baseUrl = baseUrl;
5
+ }
6
+ async _fetch(path, params) {
7
+ const url = new URL(path, this._baseUrl);
8
+ if (params) {
9
+ for (const [key, value] of Object.entries(params)) {
10
+ if (value !== undefined) {
11
+ url.searchParams.set(key, String(value));
12
+ }
13
+ }
14
+ }
15
+ const response = await fetch(url.toString());
16
+ if (!response.ok) {
17
+ const text = await response.text();
18
+ throw new Error(`Mindshare API request failed: ${response.status} - ${text}`);
19
+ }
20
+ const data = (await response.json());
21
+ return data;
22
+ }
23
+ async getProjectLeaderboard(timeframe, rankBy, limit) {
24
+ const result = await this._fetch('/mindshare/project/leaderboard', {
25
+ timeframe,
26
+ rankBy,
27
+ limit,
28
+ });
29
+ return result;
30
+ }
31
+ async getProjectMindshare(projectId, timeframe) {
32
+ const result = await this._fetch(`/mindshare/project/${encodeURIComponent(projectId)}`, {
33
+ timeframe,
34
+ });
35
+ return result;
36
+ }
37
+ async getProjectMindshareTimeseries(projectId, timeframe) {
38
+ const result = await this._fetch(`/mindshare/project/${encodeURIComponent(projectId)}/timeseries`, { timeframe });
39
+ return result;
40
+ }
41
+ async getProjectLeaderboardBySector(sectorId, timeframe, rankBy, limit, filterBy) {
42
+ const result = await this._fetch(`/mindshare/project/sector/${encodeURIComponent(sectorId)}/leaderboard`, { timeframe, rankBy, limit, filterBy });
43
+ return result;
44
+ }
45
+ async getSectorLeaderboard(timeframe, rankBy, limit) {
46
+ const result = await this._fetch('/mindshare/sector/leaderboard', {
47
+ timeframe,
48
+ rankBy,
49
+ limit,
50
+ });
51
+ return result;
52
+ }
53
+ async getSectorMindshare(sectorId, timeframe) {
54
+ const result = await this._fetch(`/mindshare/sector/${encodeURIComponent(sectorId)}`, {
55
+ timeframe,
56
+ });
57
+ return result;
58
+ }
59
+ async getSectorMindshareTimeseries(sectorId, timeframe) {
60
+ const result = await this._fetch(`/mindshare/sector/${encodeURIComponent(sectorId)}/timeseries`, { timeframe });
61
+ return result;
62
+ }
63
+ async getUserLeaderboard(timeframe, rankBy, limit, page) {
64
+ const result = await this._fetch('/mindshare/user/leaderboard', {
65
+ timeframe,
66
+ rankBy,
67
+ limit,
68
+ page,
69
+ });
70
+ return result;
71
+ }
72
+ async getUserLeaderboardByProject(projectId, timeframe, rankBy, limit, page) {
73
+ const result = await this._fetch(`/mindshare/user/project/${encodeURIComponent(projectId)}/leaderboard`, { timeframe, rankBy, limit, page });
74
+ return result;
75
+ }
76
+ async getUserMindshare(userId, timeframe, withTimeseries) {
77
+ const result = await this._fetch(`/mindshare/user/${encodeURIComponent(userId)}`, {
78
+ timeframe,
79
+ withTimeseries,
80
+ });
81
+ return result;
82
+ }
83
+ async getUserMindshareTimeseries(userId, timeframe) {
84
+ const result = await this._fetch(`/mindshare/user/${encodeURIComponent(userId)}/timeseries`, { timeframe });
85
+ return result;
86
+ }
87
+ async getMindshareDeltaSignals(projectId, minThreshold, limit, page, includeTrendingTopics) {
88
+ const result = await this._fetch('/signal/mindshare/delta', {
89
+ projectId,
90
+ minThreshold,
91
+ limit,
92
+ page,
93
+ includeTrendingTopics,
94
+ });
95
+ return result;
96
+ }
97
+ async getMindshareMASignals(projectId, minThreshold, limit, page, includeTrendingTopics) {
98
+ const result = await this._fetch('/signal/mindshare/ma', {
99
+ projectId,
100
+ minThreshold,
101
+ limit,
102
+ page,
103
+ includeTrendingTopics,
104
+ });
105
+ return result;
106
+ }
107
+ async getMindshareSMAZScoreSignals(projectId, limit, cursor, mode, includeSignalSummary) {
108
+ const result = await this._fetch('/signal/mindshare/sma-zscore', {
109
+ projectId,
110
+ limit,
111
+ cursor,
112
+ mode,
113
+ includeSignalSummary,
114
+ });
115
+ return result;
116
+ }
117
+ }
118
+ let clientInstance = null;
119
+ export function getMindshareClient() {
120
+ if (clientInstance === null) {
121
+ clientInstance = new MindshareClient();
122
+ }
123
+ return clientInstance;
124
+ }
@@ -0,0 +1,3 @@
1
+ export { mindshareTools } from './tools.js';
2
+ export { getProjectLeaderboardTool, getProjectMindshareTool, getProjectMindshareTimeseriesTool, getProjectLeaderboardBySectorTool, } from './tools.js';
3
+ export { MindshareClient, getMindshareClient } from './client.js';
@@ -0,0 +1,167 @@
1
+ import { tool } from 'ai';
2
+ import { z } from 'zod';
3
+ import { getMindshareClient, } from './client.js';
4
+ import { formatToolError, signPrefix, truncateTimeseries, truncationLabel, formatPeriodChange, } from '../formatting.js';
5
+ const timeframeSchema = z
6
+ .enum(['30m', '24h', '3D', '7D', '1M', '3M', 'YTD'])
7
+ .optional()
8
+ .describe('Timeframe for mindshare data. Defaults to 24h.');
9
+ const rankBySchema = z
10
+ .enum(['delta', 'value'])
11
+ .optional()
12
+ .describe('Rank by "delta" (change) or "value" (absolute). Defaults to value.');
13
+ const limitSchema = z
14
+ .number()
15
+ .int()
16
+ .min(1)
17
+ .max(100)
18
+ .optional()
19
+ .describe('Number of results to return (max 100). Defaults to 20.');
20
+ function formatMindshare(ms) {
21
+ const value = ms?.value != null ? `${(ms.value * 100).toFixed(4)}%` : 'N/A';
22
+ const rawDelta = ms?.delta ?? 0;
23
+ const delta = `${signPrefix(rawDelta)}${(rawDelta * 100).toFixed(2)}%`;
24
+ const rank = ms?.rank != null ? `#${ms.rank}` : 'N/A';
25
+ return { value, delta, rank };
26
+ }
27
+ export const getProjectLeaderboardTool = tool({
28
+ description: 'Get the top trending projects by mindshare. Returns a ranked list of projects sorted by mindshare value or delta change. Use this to identify what projects are gaining attention.',
29
+ inputSchema: z.object({
30
+ timeframe: timeframeSchema,
31
+ rankBy: rankBySchema,
32
+ limit: limitSchema,
33
+ }),
34
+ execute: async ({ timeframe, rankBy, limit }) => {
35
+ try {
36
+ const client = getMindshareClient();
37
+ const data = await client.getProjectLeaderboard(timeframe, rankBy, limit);
38
+ if (data.length === 0) {
39
+ return 'No projects found in the mindshare leaderboard.';
40
+ }
41
+ const lines = [
42
+ `Top ${data.length} Projects by Mindshare (${timeframe ?? '24h'}, ranked by ${rankBy ?? 'value'}):`,
43
+ '',
44
+ 'Rank | Project | Mindshare | Delta',
45
+ '--- | --- | --- | ---',
46
+ ];
47
+ for (const item of data) {
48
+ const ms = formatMindshare(item.mindshare);
49
+ lines.push(`${ms.rank} | ${item.name} | ${ms.value} | ${ms.delta}`);
50
+ }
51
+ const output = lines.join('\n');
52
+ return output;
53
+ }
54
+ catch (err) {
55
+ return formatToolError(err, 'fetching project leaderboard');
56
+ }
57
+ },
58
+ });
59
+ export const getProjectMindshareTool = tool({
60
+ description: 'Get the mindshare data for a specific project by ID. Returns current mindshare value, delta change, and ranking position.',
61
+ inputSchema: z.object({
62
+ projectId: z.string().describe('The project ID to look up.'),
63
+ timeframe: timeframeSchema,
64
+ }),
65
+ execute: async ({ projectId, timeframe }) => {
66
+ try {
67
+ const client = getMindshareClient();
68
+ const data = await client.getProjectMindshare(projectId, timeframe);
69
+ const ms = formatMindshare(data.mindshare);
70
+ const lines = [
71
+ `Mindshare for ${data.name ?? projectId} (${timeframe ?? '24h'}):`,
72
+ '',
73
+ `- Rank: ${ms.rank}`,
74
+ `- Mindshare Value: ${ms.value}`,
75
+ `- Delta Change: ${ms.delta}`,
76
+ ];
77
+ if (data.symbol) {
78
+ lines.push(`- Symbol: ${data.symbol}`);
79
+ }
80
+ const output = lines.join('\n');
81
+ return output;
82
+ }
83
+ catch (err) {
84
+ return formatToolError(err, 'fetching project mindshare');
85
+ }
86
+ },
87
+ });
88
+ export const getProjectMindshareTimeseriesTool = tool({
89
+ description: 'Get historical mindshare data for a specific project. Returns timeseries data points showing mindshare value over time.',
90
+ inputSchema: z.object({
91
+ projectId: z.string().describe('The project ID to look up.'),
92
+ timeframe: timeframeSchema,
93
+ }),
94
+ execute: async ({ projectId, timeframe }) => {
95
+ try {
96
+ const client = getMindshareClient();
97
+ const data = await client.getProjectMindshareTimeseries(projectId, timeframe);
98
+ if (!data.data_points || data.data_points.length === 0) {
99
+ return `No historical mindshare data available for project ${projectId}.`;
100
+ }
101
+ const points = data.data_points;
102
+ const lines = [
103
+ `Mindshare Timeseries for ${projectId} (${timeframe ?? '24h'}, ${points.length} data points):`,
104
+ '',
105
+ ];
106
+ const displayPoints = truncateTimeseries(points);
107
+ for (const point of displayPoints) {
108
+ if (point === null) {
109
+ lines.push(truncationLabel(points.length, 15));
110
+ continue;
111
+ }
112
+ const date = new Date(point.timestamp).toISOString();
113
+ lines.push(`${date}: ${(point.value * 100).toFixed(4)}%`);
114
+ }
115
+ lines.push('');
116
+ lines.push(formatPeriodChange(points[0].value, points[points.length - 1].value));
117
+ const output = lines.join('\n');
118
+ return output;
119
+ }
120
+ catch (err) {
121
+ return formatToolError(err, 'fetching project mindshare timeseries');
122
+ }
123
+ },
124
+ });
125
+ export const getProjectLeaderboardBySectorTool = tool({
126
+ description: 'Get the top projects within a specific sector by mindshare. Use this to analyze which projects are gaining attention in a particular market segment.',
127
+ inputSchema: z.object({
128
+ sectorId: z.string().describe('The sector ID to filter by.'),
129
+ timeframe: timeframeSchema,
130
+ rankBy: rankBySchema,
131
+ limit: limitSchema,
132
+ filterBy: z
133
+ .enum(['all', 'preTGE', 'nonePreTGE'])
134
+ .optional()
135
+ .describe('Filter by project stage: all, preTGE (pre-token launch), or nonePreTGE.'),
136
+ }),
137
+ execute: async ({ sectorId, timeframe, rankBy, limit, filterBy }) => {
138
+ try {
139
+ const client = getMindshareClient();
140
+ const data = await client.getProjectLeaderboardBySector(sectorId, timeframe, rankBy, limit, filterBy);
141
+ if (data.length === 0) {
142
+ return `No projects found in sector ${sectorId}.`;
143
+ }
144
+ const lines = [
145
+ `Top ${data.length} Projects in Sector "${sectorId}" (${timeframe ?? '24h'}, ranked by ${rankBy ?? 'value'}):`,
146
+ '',
147
+ 'Rank | Project | Mindshare | Delta',
148
+ '--- | --- | --- | ---',
149
+ ];
150
+ for (const item of data) {
151
+ const ms = formatMindshare(item.mindshare);
152
+ lines.push(`${ms.rank} | ${item.name} | ${ms.value} | ${ms.delta}`);
153
+ }
154
+ const output = lines.join('\n');
155
+ return output;
156
+ }
157
+ catch (err) {
158
+ return formatToolError(err, 'fetching sector project leaderboard');
159
+ }
160
+ },
161
+ });
162
+ export const mindshareTools = {
163
+ getProjectLeaderboard: getProjectLeaderboardTool,
164
+ getProjectMindshare: getProjectMindshareTool,
165
+ getProjectMindshareTimeseries: getProjectMindshareTimeseriesTool,
166
+ getProjectLeaderboardBySector: getProjectLeaderboardBySectorTool,
167
+ };
@@ -0,0 +1,30 @@
1
+ import { tool } from 'ai';
2
+ import { z } from 'zod';
3
+ /**
4
+ * Create a tool that allows the agent to read skill knowledge.
5
+ * Returns the full SKILL.md body content when called.
6
+ */
7
+ export function createReadSkillTool(skillRegistry) {
8
+ const readSkillTool = tool({
9
+ description: 'Read a skill to get detailed knowledge and instructions. Call this when you need specialized expertise for analysis. Use the skill ID from the available skills list.',
10
+ inputSchema: z.object({
11
+ skillId: z
12
+ .string()
13
+ .describe('The skill ID to read (from the available skills list in your prompt)'),
14
+ }),
15
+ execute: async ({ skillId }) => {
16
+ const skill = skillRegistry.get(skillId);
17
+ if (skill === undefined) {
18
+ const availableIds = Array.from(skillRegistry.keys());
19
+ if (availableIds.length === 0) {
20
+ return `Skill "${skillId}" not found. No skills are currently available.`;
21
+ }
22
+ const idList = availableIds.join(', ');
23
+ return `Skill "${skillId}" not found. Available skills: ${idList}`;
24
+ }
25
+ const output = `# ${skill.metadata.name}\n\n${skill.body}`;
26
+ return output;
27
+ },
28
+ });
29
+ return readSkillTool;
30
+ }
@@ -0,0 +1 @@
1
+ export { computeSMA, computeEMA, computeRSI, computeMACD, computeBollingerBands } from './indicators.js';
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Extract close prices from OHLC data.
3
+ */
4
+ function extractClosePrices(data) {
5
+ const result = [];
6
+ for (const point of data) {
7
+ const timestamp = point[0];
8
+ const close = point[4];
9
+ result.push({ timestamp, close });
10
+ }
11
+ return result;
12
+ }
13
+ /**
14
+ * Compute Simple Moving Average (SMA).
15
+ * SMA = sum of close prices over period / period
16
+ */
17
+ export function computeSMA(data, period) {
18
+ const prices = extractClosePrices(data);
19
+ const result = [];
20
+ if (prices.length < period) {
21
+ return result;
22
+ }
23
+ for (let i = period - 1; i < prices.length; i++) {
24
+ let sum = 0;
25
+ for (let j = i - period + 1; j <= i; j++) {
26
+ sum += prices[j].close;
27
+ }
28
+ const sma = sum / period;
29
+ result.push({
30
+ timestamp: prices[i].timestamp,
31
+ value: sma,
32
+ });
33
+ }
34
+ return result;
35
+ }
36
+ /**
37
+ * Compute Exponential Moving Average (EMA).
38
+ * EMA = (Close - Previous EMA) * multiplier + Previous EMA
39
+ * multiplier = 2 / (period + 1)
40
+ */
41
+ export function computeEMA(data, period) {
42
+ const prices = extractClosePrices(data);
43
+ const result = [];
44
+ if (prices.length < period) {
45
+ return result;
46
+ }
47
+ const multiplier = 2 / (period + 1);
48
+ let initialSum = 0;
49
+ for (let i = 0; i < period; i++) {
50
+ initialSum += prices[i].close;
51
+ }
52
+ let ema = initialSum / period;
53
+ result.push({
54
+ timestamp: prices[period - 1].timestamp,
55
+ value: ema,
56
+ });
57
+ for (let i = period; i < prices.length; i++) {
58
+ ema = (prices[i].close - ema) * multiplier + ema;
59
+ result.push({
60
+ timestamp: prices[i].timestamp,
61
+ value: ema,
62
+ });
63
+ }
64
+ return result;
65
+ }
66
+ /**
67
+ * Compute Relative Strength Index (RSI).
68
+ * RSI = 100 - (100 / (1 + RS))
69
+ * RS = Average Gain / Average Loss over period
70
+ */
71
+ export function computeRSI(data, period) {
72
+ const prices = extractClosePrices(data);
73
+ const result = [];
74
+ if (prices.length < period + 1) {
75
+ return result;
76
+ }
77
+ const gains = [];
78
+ const losses = [];
79
+ for (let i = 1; i < prices.length; i++) {
80
+ const change = prices[i].close - prices[i - 1].close;
81
+ if (change > 0) {
82
+ gains.push(change);
83
+ losses.push(0);
84
+ }
85
+ else {
86
+ gains.push(0);
87
+ losses.push(Math.abs(change));
88
+ }
89
+ }
90
+ let avgGain = 0;
91
+ let avgLoss = 0;
92
+ for (let i = 0; i < period; i++) {
93
+ avgGain += gains[i];
94
+ avgLoss += losses[i];
95
+ }
96
+ avgGain /= period;
97
+ avgLoss /= period;
98
+ const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;
99
+ const rsi = 100 - 100 / (1 + rs);
100
+ result.push({
101
+ timestamp: prices[period].timestamp,
102
+ value: rsi,
103
+ });
104
+ for (let i = period; i < gains.length; i++) {
105
+ avgGain = (avgGain * (period - 1) + gains[i]) / period;
106
+ avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
107
+ const currentRs = avgLoss === 0 ? 100 : avgGain / avgLoss;
108
+ const currentRsi = 100 - 100 / (1 + currentRs);
109
+ result.push({
110
+ timestamp: prices[i + 1].timestamp,
111
+ value: currentRsi,
112
+ });
113
+ }
114
+ return result;
115
+ }
116
+ /**
117
+ * Compute MACD (Moving Average Convergence Divergence).
118
+ * MACD Line = Fast EMA - Slow EMA
119
+ * Signal Line = EMA of MACD Line
120
+ * Histogram = MACD Line - Signal Line
121
+ */
122
+ export function computeMACD(data, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
123
+ const fastEma = computeEMA(data, fastPeriod);
124
+ const slowEma = computeEMA(data, slowPeriod);
125
+ const result = [];
126
+ if (fastEma.length === 0 || slowEma.length === 0) {
127
+ return result;
128
+ }
129
+ const fastMap = new Map();
130
+ for (const point of fastEma) {
131
+ fastMap.set(point.timestamp, point.value);
132
+ }
133
+ const macdLine = [];
134
+ for (const slow of slowEma) {
135
+ const fast = fastMap.get(slow.timestamp);
136
+ if (fast !== undefined) {
137
+ macdLine.push({
138
+ timestamp: slow.timestamp,
139
+ value: fast - slow.value,
140
+ });
141
+ }
142
+ }
143
+ if (macdLine.length < signalPeriod) {
144
+ return result;
145
+ }
146
+ const signalMultiplier = 2 / (signalPeriod + 1);
147
+ let signalSum = 0;
148
+ for (let i = 0; i < signalPeriod; i++) {
149
+ signalSum += macdLine[i].value;
150
+ }
151
+ let signal = signalSum / signalPeriod;
152
+ result.push({
153
+ timestamp: macdLine[signalPeriod - 1].timestamp,
154
+ macd: macdLine[signalPeriod - 1].value,
155
+ signal,
156
+ histogram: macdLine[signalPeriod - 1].value - signal,
157
+ });
158
+ for (let i = signalPeriod; i < macdLine.length; i++) {
159
+ signal = (macdLine[i].value - signal) * signalMultiplier + signal;
160
+ result.push({
161
+ timestamp: macdLine[i].timestamp,
162
+ macd: macdLine[i].value,
163
+ signal,
164
+ histogram: macdLine[i].value - signal,
165
+ });
166
+ }
167
+ return result;
168
+ }
169
+ /**
170
+ * Compute Bollinger Bands.
171
+ * Middle Band = SMA
172
+ * Upper Band = SMA + (stdDev * standard deviation)
173
+ * Lower Band = SMA - (stdDev * standard deviation)
174
+ */
175
+ export function computeBollingerBands(data, period = 20, stdDevMultiplier = 2) {
176
+ const prices = extractClosePrices(data);
177
+ const result = [];
178
+ if (prices.length < period) {
179
+ return result;
180
+ }
181
+ for (let i = period - 1; i < prices.length; i++) {
182
+ let sum = 0;
183
+ for (let j = i - period + 1; j <= i; j++) {
184
+ sum += prices[j].close;
185
+ }
186
+ const sma = sum / period;
187
+ let squaredDiffSum = 0;
188
+ for (let j = i - period + 1; j <= i; j++) {
189
+ const diff = prices[j].close - sma;
190
+ squaredDiffSum += diff * diff;
191
+ }
192
+ const stdDev = Math.sqrt(squaredDiffSum / period);
193
+ result.push({
194
+ timestamp: prices[i].timestamp,
195
+ upper: sma + stdDevMultiplier * stdDev,
196
+ middle: sma,
197
+ lower: sma - stdDevMultiplier * stdDev,
198
+ });
199
+ }
200
+ return result;
201
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ export function formatTime(date) {
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
+ export function convictionColor(conviction) {
8
+ if (conviction > 0)
9
+ return 'green';
10
+ if (conviction < 0)
11
+ return 'red';
12
+ return 'gray';
13
+ }
14
+ export function extractErrorMessage(err) {
15
+ const message = err instanceof Error ? err.message : String(err);
16
+ return message;
17
+ }
18
+ export function formatTokenCount(n) {
19
+ const formatted = n.toLocaleString('en-US');
20
+ return formatted;
21
+ }
22
+ export function formatTokenUsage(usage) {
23
+ let input = `input: ${formatTokenCount(usage.inputTokens)}`;
24
+ if (usage.cacheReadTokens > 0) {
25
+ const newTokens = usage.inputTokens - usage.cacheReadTokens;
26
+ input += ` (${formatTokenCount(newTokens)} new, ${formatTokenCount(usage.cacheReadTokens)} cached)`;
27
+ }
28
+ else if (usage.cacheWriteTokens > 0) {
29
+ input += ` (${formatTokenCount(usage.cacheWriteTokens)} cache write)`;
30
+ }
31
+ const output = `output: ${formatTokenCount(usage.outputTokens)}`;
32
+ const tools = usage.toolCalls > 0 ? `tools: ${usage.toolNames.join(', ')}` : null;
33
+ return { input, output, tools };
34
+ }
35
+ export function stripCodeFences(text) {
36
+ const trimmed = text.trim();
37
+ const fencePattern = /^```(?:markdown|md)?\s*\n([\s\S]*?)\n```$/;
38
+ const match = trimmed.match(fencePattern);
39
+ if (match) {
40
+ return match[1].trim();
41
+ }
42
+ return trimmed;
43
+ }