hypervibes 0.0.0-stage → 0.4.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 (362) hide show
  1. package/.build/client/assets/_authenticated-C87LKvH0.js +1 -0
  2. package/.build/client/assets/_authenticated.account-D-nTh_fC.js +1 -0
  3. package/.build/client/assets/_authenticated.agents-HwcveLyB.js +1 -0
  4. package/.build/client/assets/_authenticated.agents._agentId-DuE8Lv62.js +1 -0
  5. package/.build/client/assets/_authenticated.agents._agentId.chart-Bb_XkvQx.js +4 -0
  6. package/.build/client/assets/_authenticated.agents._agentId.chat-ClMMKw_N.js +1 -0
  7. package/.build/client/assets/_authenticated.agents._agentId.index-DNJwBwn9.js +1 -0
  8. package/.build/client/assets/_authenticated.agents._agentId.indicators-BmVjLtRI.js +1 -0
  9. package/.build/client/assets/_authenticated.agents._agentId.indicators_._indicatorId-CMqaaFQf.js +2 -0
  10. package/.build/client/assets/_authenticated.agents._agentId.indicators_._indicatorId-DtgkoNV5.js +6 -0
  11. package/.build/client/assets/_authenticated.agents._agentId.memories-O-4f6a4G.js +1 -0
  12. package/.build/client/assets/_authenticated.agents._agentId.memories_._memoryRef-BUPtUcj3.js +1 -0
  13. package/.build/client/assets/_authenticated.agents._agentId.notifications-2lyhXCSk.js +1 -0
  14. package/.build/client/assets/_authenticated.agents._agentId.notifications_._notificationId-Da3ZVT4v.js +1 -0
  15. package/.build/client/assets/_authenticated.agents._agentId.settings-C5cWHoYw.js +1 -0
  16. package/.build/client/assets/_authenticated.agents._agentId.sub-agents-HwcveLyB.js +1 -0
  17. package/.build/client/assets/_authenticated.agents._agentId.sub-agents._subagentId-CZ4MeRy4.js +1 -0
  18. package/.build/client/assets/_authenticated.agents._agentId.sub-agents._subagentId_.runs._runId-dVbo5kMU.js +3 -0
  19. package/.build/client/assets/_authenticated.agents._agentId.sub-agents.index-DeWTOYJD.js +1 -0
  20. package/.build/client/assets/_authenticated.agents._agentId.sub-agents.new-D02TflCE.js +37 -0
  21. package/.build/client/assets/_authenticated.agents._agentId.transactions-D3a8Glgj.js +1 -0
  22. package/.build/client/assets/_authenticated.agents.index-CEqeDEgP.js +1 -0
  23. package/.build/client/assets/_authenticated.agents.new-DLRWK5Uk.js +1 -0
  24. package/.build/client/assets/_authenticated.providers-D0iPLXra.js +1 -0
  25. package/.build/client/assets/agent-chat-page-C5eYFgxw.js +1 -0
  26. package/.build/client/assets/agent-enablement-control-CUzOp9ce.js +1 -0
  27. package/.build/client/assets/agent-events-DC8eDZf3.js +1 -0
  28. package/.build/client/assets/agent-input-aolvZ47U.js +1 -0
  29. package/.build/client/assets/agent-notifications-page-B0mr-Zz8.js +1 -0
  30. package/.build/client/assets/agent-queries-CNMBImun.js +1 -0
  31. package/.build/client/assets/app-DjmsvbUC.css +2 -0
  32. package/.build/client/assets/artifact-content-COO4VTSZ.js +1 -0
  33. package/.build/client/assets/auth-client-K13li9H1.js +3 -0
  34. package/.build/client/assets/call-DxlGie4_.js +31 -0
  35. package/.build/client/assets/ccip-BgPlVPYP.js +1 -0
  36. package/.build/client/assets/chart-contracts-Cr5SFCbE.js +1 -0
  37. package/.build/client/assets/chart-queries-Bpvrgd0-.js +1 -0
  38. package/.build/client/assets/chat-bubble-CAJkT-vL.js +1 -0
  39. package/.build/client/assets/config-dialog-C9x9gKW9.js +1 -0
  40. package/.build/client/assets/contracts-HhAL7Tt7.js +1 -0
  41. package/.build/client/assets/createServerFn-DfZIp2Fu.js +3 -0
  42. package/.build/client/assets/custom-BeqXuIIS.js +5 -0
  43. package/.build/client/assets/decimal-B0DEG-1V.js +1 -0
  44. package/.build/client/assets/esm-BTb2nBdW.js +1 -0
  45. package/.build/client/assets/identicon-Lb9pS4O1.js +1 -0
  46. package/.build/client/assets/index-B4hvjMmI.js +10 -0
  47. package/.build/client/assets/indicator-input-fields-CtmrfVfS.js +1 -0
  48. package/.build/client/assets/indicator-queries-CzZ6u1Mh.js +1 -0
  49. package/.build/client/assets/indicator-renderer-CfccsIt2.js +1 -0
  50. package/.build/client/assets/instrument-label-BZYlWXR5.js +1 -0
  51. package/.build/client/assets/instrument-picker-DLPpryOm.js +1 -0
  52. package/.build/client/assets/journal-decimal-DBvd_Ibi.js +1 -0
  53. package/.build/client/assets/jsx-runtime-CIazjfqY.js +1 -0
  54. package/.build/client/assets/lazyRouteComponent-CJgUa7_r.js +1 -0
  55. package/.build/client/assets/lightweight-charts.production-BiBiFZSH.js +1 -0
  56. package/.build/client/assets/login-MNgYxCOY.js +3 -0
  57. package/.build/client/assets/memory-badge-BbN-DJQi.js +1 -0
  58. package/.build/client/assets/memory-contracts-Doi_Q1XJ.js +1 -0
  59. package/.build/client/assets/memory-queries-BttL580R.js +1 -0
  60. package/.build/client/assets/model-picker-YCQNNmyw.js +1 -0
  61. package/.build/client/assets/notification-queries-B12DG3aS.js +1 -0
  62. package/.build/client/assets/preload-helper-Czpn1I53.js +1 -0
  63. package/.build/client/assets/provider-logo-Ddb77aBD.js +1 -0
  64. package/.build/client/assets/provider-queries-DxPwhDOU.js +1 -0
  65. package/.build/client/assets/query-nvK_95Jo.js +1 -0
  66. package/.build/client/assets/random-uuid-DJR3ygJS.js +1 -0
  67. package/.build/client/assets/react-dom-C6bOPxes.js +1 -0
  68. package/.build/client/assets/risk-queries-D_6PHwus.js +1 -0
  69. package/.build/client/assets/run-subagent-dialog-B4yQe9T9.js +1 -0
  70. package/.build/client/assets/secp256k1-BbZnIgDP.js +1 -0
  71. package/.build/client/assets/setup-checklist-CUW-K484.js +1 -0
  72. package/.build/client/assets/sha2-hT-Q4pur.js +1 -0
  73. package/.build/client/assets/subagent-enabled-toggle-Bk5wfScg.js +1 -0
  74. package/.build/client/assets/subagent-input-TQke90I1.js +1 -0
  75. package/.build/client/assets/subagent-mutations-DfsDbmFu.js +1 -0
  76. package/.build/client/assets/subagent-queries-DVv5JCfs.js +1 -0
  77. package/.build/client/assets/subagent-run-history-D55Uh5VK.js +1 -0
  78. package/.build/client/assets/toggle-timestamp-B50FTPmA.js +1 -0
  79. package/.build/client/assets/useBaseQuery-Bxruo_mV.js +1 -0
  80. package/.build/client/assets/useMutation-DrF53EQG.js +1 -0
  81. package/.build/client/assets/useQuery-BMSU16jY.js +1 -0
  82. package/.build/client/assets/useRouter-c0I1aURm.js +1 -0
  83. package/.build/client/assets/useSelector-ERD9RroG.js +2 -0
  84. package/.build/client/assets/useSuspenseQuery-vODFwDb8.js +1 -0
  85. package/.build/client/assets/utils-Bpv4vmSW.js +1 -0
  86. package/.build/client/assets/worker-triggers-DtXyn40O.js +1 -0
  87. package/.build/server/assets/_authenticated-Bch0_2QH.js +264 -0
  88. package/.build/server/assets/_authenticated-DGV5cZYE.js +22 -0
  89. package/.build/server/assets/_authenticated.account-6qu6oQ1y.js +685 -0
  90. package/.build/server/assets/_authenticated.agents-DYDnQxli.js +5 -0
  91. package/.build/server/assets/_authenticated.agents._agentId-4HvB3mhd.js +17 -0
  92. package/.build/server/assets/_authenticated.agents._agentId-Cl608F1T.js +260 -0
  93. package/.build/server/assets/_authenticated.agents._agentId-G2jAHjma.js +15 -0
  94. package/.build/server/assets/_authenticated.agents._agentId.chart-BIA8wy73.js +2644 -0
  95. package/.build/server/assets/_authenticated.agents._agentId.chart-D4aj8Qy9.js +22 -0
  96. package/.build/server/assets/_authenticated.agents._agentId.chat-ClsVle4g.js +13 -0
  97. package/.build/server/assets/_authenticated.agents._agentId.chat-JV3FDsTp.js +18 -0
  98. package/.build/server/assets/_authenticated.agents._agentId.index-Ct4kbu2f.js +1044 -0
  99. package/.build/server/assets/_authenticated.agents._agentId.index-DJgrupvW.js +18 -0
  100. package/.build/server/assets/_authenticated.agents._agentId.indicators-DrKd0aP5.js +184 -0
  101. package/.build/server/assets/_authenticated.agents._agentId.indicators-wiVaY8fW.js +18 -0
  102. package/.build/server/assets/_authenticated.agents._agentId.indicators_._indicatorId-C4Ox2R-a.js +25 -0
  103. package/.build/server/assets/_authenticated.agents._agentId.indicators_._indicatorId-D8Q0hCW0.js +489 -0
  104. package/.build/server/assets/_authenticated.agents._agentId.memories-BUTyVLYy.js +42 -0
  105. package/.build/server/assets/_authenticated.agents._agentId.memories-E8-nSEMT.js +362 -0
  106. package/.build/server/assets/_authenticated.agents._agentId.memories_._memoryRef-C-SC6wzq.js +14 -0
  107. package/.build/server/assets/_authenticated.agents._agentId.memories_._memoryRef-ZCrdrc8C.js +490 -0
  108. package/.build/server/assets/_authenticated.agents._agentId.notifications-DQeQqTzh.js +14 -0
  109. package/.build/server/assets/_authenticated.agents._agentId.notifications-DlFyYyHh.js +16 -0
  110. package/.build/server/assets/_authenticated.agents._agentId.notifications_._notificationId-B0RosY_R.js +15 -0
  111. package/.build/server/assets/_authenticated.agents._agentId.notifications_._notificationId-C1NikQ9e.js +13 -0
  112. package/.build/server/assets/_authenticated.agents._agentId.settings-DDwjT3Ui.js +42 -0
  113. package/.build/server/assets/_authenticated.agents._agentId.settings-PEzEvOfo.js +751 -0
  114. package/.build/server/assets/_authenticated.agents._agentId.sub-agents-z34-J3Tu.js +5 -0
  115. package/.build/server/assets/_authenticated.agents._agentId.sub-agents._subagentId-D-6TOi1U.js +1371 -0
  116. package/.build/server/assets/_authenticated.agents._agentId.sub-agents._subagentId-DipzVdnr.js +13 -0
  117. package/.build/server/assets/_authenticated.agents._agentId.sub-agents._subagentId_.runs._runId-BZR3VLV7.js +610 -0
  118. package/.build/server/assets/_authenticated.agents._agentId.sub-agents._subagentId_.runs._runId-DsYJKfGm.js +12 -0
  119. package/.build/server/assets/_authenticated.agents._agentId.sub-agents.index-BF8Cuzcr.js +231 -0
  120. package/.build/server/assets/_authenticated.agents._agentId.sub-agents.index-D2x0qCnt.js +12 -0
  121. package/.build/server/assets/_authenticated.agents._agentId.sub-agents.new-CYm_vuDD.js +13 -0
  122. package/.build/server/assets/_authenticated.agents._agentId.sub-agents.new-CiVShIka.js +497 -0
  123. package/.build/server/assets/_authenticated.agents._agentId.transactions-BC_XfGqw.js +95 -0
  124. package/.build/server/assets/_authenticated.agents._agentId.transactions-WtBW3xmh.js +495 -0
  125. package/.build/server/assets/_authenticated.agents.index-C8zmu8T8.js +78 -0
  126. package/.build/server/assets/_authenticated.agents.new-Bt-tBR47.js +302 -0
  127. package/.build/server/assets/_authenticated.providers-C0pb-ujV.js +672 -0
  128. package/.build/server/assets/_tanstack-start-manifest_v-Baw5u9sk.js +354 -0
  129. package/.build/server/assets/account-XvMwzRXh.js +66 -0
  130. package/.build/server/assets/account-queries-AJJVkLAV.js +32 -0
  131. package/.build/server/assets/agent-chat-page-DChiz8KQ.js +686 -0
  132. package/.build/server/assets/agent-enablement-control-C90f0uIb.js +143 -0
  133. package/.build/server/assets/agent-events-DK9Yz5__.js +217 -0
  134. package/.build/server/assets/agent-notifications-page-BdyKAyds.js +276 -0
  135. package/.build/server/assets/agent-queries-Cmx8RiUx.js +51 -0
  136. package/.build/server/assets/agents-CZq-0mna.js +106 -0
  137. package/.build/server/assets/agents-CfjmtW7A.js +278 -0
  138. package/.build/server/assets/artifact-content-B6uHmPz7.js +35 -0
  139. package/.build/server/assets/artifacts-HtLwHs8q.js +42 -0
  140. package/.build/server/assets/auth-DTikZAVz.js +12 -0
  141. package/.build/server/assets/auth-client-Vb3O0v7P.js +1897 -0
  142. package/.build/server/assets/auth-user-DkLo8ojH.js +108 -0
  143. package/.build/server/assets/chart-queries-Bc3AfsEb.js +109 -0
  144. package/.build/server/assets/charts-C4dKuwTJ.js +130 -0
  145. package/.build/server/assets/chat-bubble-ik3itVbx.js +109 -0
  146. package/.build/server/assets/config-dialog-9gSAjwwT.js +55 -0
  147. package/.build/server/assets/contracts-CG-nZuYJ.js +155 -0
  148. package/.build/server/assets/createServerRpc-DNqhdU4z.js +12 -0
  149. package/.build/server/assets/decimal-BthtZ77w.js +97 -0
  150. package/.build/server/assets/empty-plugin-adapters-MOWBbCMw.js +5 -0
  151. package/.build/server/assets/errors-DaZqUftX.js +151 -0
  152. package/.build/server/assets/gateway-CHkruO_a.js +193 -0
  153. package/.build/server/assets/identicon-CyawcVnx.js +41 -0
  154. package/.build/server/assets/indicator-input-fields-bzuhIh6t.js +75 -0
  155. package/.build/server/assets/indicator-queries-4dY1-LXx.js +171 -0
  156. package/.build/server/assets/indicator-renderer-B2muPS-8.js +395 -0
  157. package/.build/server/assets/indicators-ENxAHN42.js +192 -0
  158. package/.build/server/assets/insight-contracts-B5rmUDfO.js +14 -0
  159. package/.build/server/assets/instrument-label-C-tTGGsD.js +40 -0
  160. package/.build/server/assets/instrument-picker-CRroLwVq.js +381 -0
  161. package/.build/server/assets/journal-9aE-um9f.js +107 -0
  162. package/.build/server/assets/journal-decimal-Bh9EL029.js +66 -0
  163. package/.build/server/assets/login-BsEFUvTX.js +125 -0
  164. package/.build/server/assets/memories-2WF2fW1G.js +100 -0
  165. package/.build/server/assets/memory-badge-DVYLTtRR.js +53 -0
  166. package/.build/server/assets/memory-contracts-DQGN2IKV.js +22 -0
  167. package/.build/server/assets/memory-queries--4RbPRrk.js +92 -0
  168. package/.build/server/assets/model-picker-CA1uYb--.js +225 -0
  169. package/.build/server/assets/notification-queries-0CJUkBt9.js +52 -0
  170. package/.build/server/assets/notifications-Cn7BiCyw.js +72 -0
  171. package/.build/server/assets/provider-logo-BRdbOr9I.js +32 -0
  172. package/.build/server/assets/provider-queries-BaZWLw8J.js +78 -0
  173. package/.build/server/assets/providers-CyoN_jgW.js +89 -0
  174. package/.build/server/assets/risk-Bqrb6hKQ.js +34 -0
  175. package/.build/server/assets/risk-queries-JQpByHT2.js +18 -0
  176. package/.build/server/assets/router-Hkr5TH_I.js +419 -0
  177. package/.build/server/assets/run-subagent-dialog-C7iUOZa-.js +59 -0
  178. package/.build/server/assets/setup-DqMlwgNr.js +30 -0
  179. package/.build/server/assets/setup-checklist-BICTmBo2.js +60 -0
  180. package/.build/server/assets/start-C-GPoWRt.js +4 -0
  181. package/.build/server/assets/subagent-enabled-toggle-Djte00oo.js +22 -0
  182. package/.build/server/assets/subagent-input-BHQKs2cW.js +57 -0
  183. package/.build/server/assets/subagent-mutations-dUo3B_SG.js +32 -0
  184. package/.build/server/assets/subagent-queries-sAwBjFxC.js +146 -0
  185. package/.build/server/assets/subagent-run-history-C_xmucO-.js +186 -0
  186. package/.build/server/assets/subagents-CIoilC66.js +180 -0
  187. package/.build/server/assets/toggle-timestamp-CToUVn67.js +28 -0
  188. package/.build/server/assets/trading-contracts-zWq1Hxnb.js +26 -0
  189. package/.build/server/assets/validation-BX-krL0i.js +33 -0
  190. package/.build/server/assets/worker-triggers-CJF5HWzR.js +51 -0
  191. package/.build/server/server.js +7501 -0
  192. package/LICENSE +661 -0
  193. package/README.md +145 -2
  194. package/bin/hypervibes.js +24 -0
  195. package/dist/agents/agent-enablement.js +10 -0
  196. package/dist/agents/agent-input.js +38 -0
  197. package/dist/agents/agent-service.js +1004 -0
  198. package/dist/agents/cancel-task-scope.js +52 -0
  199. package/dist/agents/candle-intervals.js +1 -0
  200. package/dist/agents/default-subagents.js +36 -0
  201. package/dist/agents/execution-context-contracts.js +1 -0
  202. package/dist/agents/execution-context.js +206 -0
  203. package/dist/agents/execution-warnings.js +33 -0
  204. package/dist/agents/orchestrator-insights.js +14 -0
  205. package/dist/agents/run-inspection.js +99 -0
  206. package/dist/agents/subagent-dashboard.js +1 -0
  207. package/dist/agents/subagent-extension.js +156 -0
  208. package/dist/agents/subagent-history.js +5 -0
  209. package/dist/agents/subagent-input.js +73 -0
  210. package/dist/agents/subagent-service.js +1177 -0
  211. package/dist/agents/subagent-templates.js +20 -0
  212. package/dist/agents/template-manifest.js +34 -0
  213. package/dist/agents/templates/basic-analysis.json +40 -0
  214. package/dist/agents/templates/basic-review.json +48 -0
  215. package/dist/agents/templates/basic-trading.json +45 -0
  216. package/dist/agents/templates/indicator-developer.json +16 -0
  217. package/dist/agents/time-guidance.js +29 -0
  218. package/dist/agents/worker-events.js +18 -0
  219. package/dist/agents/worker-inbox.js +28 -0
  220. package/dist/agents/worker-triggers.js +23 -0
  221. package/dist/auth-options.js +98 -0
  222. package/dist/auth-user.js +15 -0
  223. package/dist/auth.js +28 -0
  224. package/dist/cache/svg-logo-cache.js +155 -0
  225. package/dist/canonical.js +13 -0
  226. package/dist/charts/chart-service.js +236 -0
  227. package/dist/charts/contracts.js +118 -0
  228. package/dist/charts/durable-extension.js +27 -0
  229. package/dist/charts/trading-contracts.js +14 -0
  230. package/dist/config.js +85 -0
  231. package/dist/db/agent-schema.js +26 -0
  232. package/dist/db/auth-schema.js +122 -0
  233. package/dist/db/database.js +31 -0
  234. package/dist/db/exchange-schema.js +23 -0
  235. package/dist/db/gateway-schema.js +24 -0
  236. package/dist/db/indicator-schema.js +19 -0
  237. package/dist/db/migrations/20261015221717_auth/migration.sql +62 -0
  238. package/dist/db/migrations/20261015231224_agents/migration.sql +35 -0
  239. package/dist/db/migrations/20261016040641_provider_connections/migration.sql +19 -0
  240. package/dist/db/migrations/20261016061831_trade_journal/migration.sql +48 -0
  241. package/dist/db/migrations/20261016080320_order_execution/migration.sql +62 -0
  242. package/dist/db/migrations/20261016181110_subagents/migration.sql +51 -0
  243. package/dist/db/migrations/20261017222959_research_artifacts/migration.sql +37 -0
  244. package/dist/db/migrations/20261018061531_memories_and_insights/migration.sql +162 -0
  245. package/dist/db/migrations/20261020091156_worker_event_inbox/migration.sql +54 -0
  246. package/dist/db/migrations/20261021051229_chart_workspace/migration.sql +33 -0
  247. package/dist/db/migrations/20261021222116_gateways/migration.sql +15 -0
  248. package/dist/db/migrations/20261022015813_pine_indicators/migration.sql +43 -0
  249. package/dist/db/migrations/20261022101559_notifications/migration.sql +51 -0
  250. package/dist/db/migrations.js +12 -0
  251. package/dist/db/order-provenance-schema.js +17 -0
  252. package/dist/db/order-schema.js +32 -0
  253. package/dist/db/profile-lock.js +12 -0
  254. package/dist/db/provider-schema.js +16 -0
  255. package/dist/db/shared-database.js +128 -0
  256. package/dist/db/subagent-schema.js +79 -0
  257. package/dist/gateway/bridge-service.js +223 -0
  258. package/dist/gateway/gateway-store.js +77 -0
  259. package/dist/gateway/handlers.js +122 -0
  260. package/dist/gateway/telegram/connector.js +115 -0
  261. package/dist/gateway/telegram/transport.js +96 -0
  262. package/dist/hyperliquid/account-info.js +117 -0
  263. package/dist/hyperliquid/account-status.js +64 -0
  264. package/dist/hyperliquid/agent-dashboard.js +56 -0
  265. package/dist/hyperliquid/chart-contracts.js +9 -0
  266. package/dist/hyperliquid/constants.js +25 -0
  267. package/dist/hyperliquid/crypto.js +29 -0
  268. package/dist/hyperliquid/currency-logo.js +7 -0
  269. package/dist/hyperliquid/decimal.js +98 -0
  270. package/dist/hyperliquid/durable-extension.js +39 -0
  271. package/dist/hyperliquid/errors.js +8 -0
  272. package/dist/hyperliquid/exchange.js +118 -0
  273. package/dist/hyperliquid/journal-decimal.js +48 -0
  274. package/dist/hyperliquid/journal-model.js +167 -0
  275. package/dist/hyperliquid/journal-service.js +648 -0
  276. package/dist/hyperliquid/live-dashboard.js +245 -0
  277. package/dist/hyperliquid/logo-cache.js +27 -0
  278. package/dist/hyperliquid/market-charts.js +242 -0
  279. package/dist/hyperliquid/market-snapshot.js +45 -0
  280. package/dist/hyperliquid/orders/order-contracts.js +42 -0
  281. package/dist/hyperliquid/orders/order-math.js +89 -0
  282. package/dist/hyperliquid/orders/order-outcomes.js +74 -0
  283. package/dist/hyperliquid/orders/order-prepare.js +109 -0
  284. package/dist/hyperliquid/orders/order-service.js +432 -0
  285. package/dist/hyperliquid/orders/order-store.js +134 -0
  286. package/dist/hyperliquid/orders/order-tools.js +40 -0
  287. package/dist/hyperliquid/orders/protection.js +35 -0
  288. package/dist/hyperliquid/orders/risk-settings.js +44 -0
  289. package/dist/hyperliquid/orders/trade-admission.js +117 -0
  290. package/dist/hyperliquid/orders/trade-planning.js +60 -0
  291. package/dist/hyperliquid/service.js +529 -0
  292. package/dist/hyperliquid/shared-feeds.js +40 -0
  293. package/dist/hyperliquid/signing.js +89 -0
  294. package/dist/indicators/builtin-catalog.js +59 -0
  295. package/dist/indicators/builtins/adx.pine +22 -0
  296. package/dist/indicators/builtins/atr.pine +11 -0
  297. package/dist/indicators/builtins/bollinger.pine +10 -0
  298. package/dist/indicators/builtins/ema.pine +5 -0
  299. package/dist/indicators/builtins/macd.pine +18 -0
  300. package/dist/indicators/builtins/rsi.pine +18 -0
  301. package/dist/indicators/builtins/sma.pine +5 -0
  302. package/dist/indicators/candle-window.js +36 -0
  303. package/dist/indicators/chart-contracts.js +64 -0
  304. package/dist/indicators/contracts.js +14 -0
  305. package/dist/indicators/durable-extension.js +32 -0
  306. package/dist/indicators/indicator-service.js +300 -0
  307. package/dist/indicators/indicator-store.js +137 -0
  308. package/dist/indicators/normalize.js +149 -0
  309. package/dist/indicators/result-schema.js +79 -0
  310. package/dist/indicators/runtime-wrapper.js +52 -0
  311. package/dist/indicators/runtime.js +201 -0
  312. package/dist/indicators/validation.js +124 -0
  313. package/dist/indicators/worker-queue.js +48 -0
  314. package/dist/initialize-config.js +160 -0
  315. package/dist/main.js +59 -0
  316. package/dist/memory/decision-audit.js +47 -0
  317. package/dist/memory/durable-extension.js +40 -0
  318. package/dist/memory/execution-audit.js +83 -0
  319. package/dist/memory/insight-contracts.js +33 -0
  320. package/dist/memory/insight-service.js +117 -0
  321. package/dist/memory/memory-contracts.js +113 -0
  322. package/dist/memory/memory-service.js +179 -0
  323. package/dist/memory/operations.js +46 -0
  324. package/dist/memory/tool-schemas.js +44 -0
  325. package/dist/memory/validation.js +42 -0
  326. package/dist/notifications/contracts.js +1 -0
  327. package/dist/notifications/delivery.js +11 -0
  328. package/dist/notifications/durable-extension.js +20 -0
  329. package/dist/notifications/notification-service.js +324 -0
  330. package/dist/providers/credential-store.js +86 -0
  331. package/dist/providers/ollama-cloud.js +148 -0
  332. package/dist/providers/provider-logo-url.js +18 -0
  333. package/dist/providers/provider-logo.js +31 -0
  334. package/dist/providers/provider-service.js +295 -0
  335. package/dist/research/artifacts.js +151 -0
  336. package/dist/research/call-queue.js +43 -0
  337. package/dist/research/contracts.js +37 -0
  338. package/dist/research/evidence.js +43 -0
  339. package/dist/research/journal.js +30 -0
  340. package/dist/research/research-service.js +191 -0
  341. package/dist/research/tool-activity.js +49 -0
  342. package/dist/research/tool-response.js +25 -0
  343. package/dist/runtime.js +145 -0
  344. package/dist/web/agent-events.js +418 -0
  345. package/dist/web/app.js +206 -0
  346. package/dist/web/artifact-downloads.js +23 -0
  347. package/dist/web/middleware.js +25 -0
  348. package/dist/web/random-uuid.js +14 -0
  349. package/dist/web/start.js +56 -0
  350. package/package.json +93 -3
  351. package/scripts/check-node.mjs +24 -0
  352. package/static/android-chrome-192x192.png +0 -0
  353. package/static/android-chrome-512x512.png +0 -0
  354. package/static/apple-touch-icon.png +0 -0
  355. package/static/favicon-16x16.png +0 -0
  356. package/static/favicon-32x32.png +0 -0
  357. package/static/favicon.ico +0 -0
  358. package/static/github.svg +3 -0
  359. package/static/hypervibes.png +0 -0
  360. package/static/logo.png +0 -0
  361. package/static/site.webmanifest +1 -0
  362. package/static/telegram.svg +1 -0
@@ -0,0 +1,245 @@
1
+ import { HttpTransport, SubscriptionClient, WebSocketTransport } from "@nktkas/hyperliquid";
2
+ import { dashboardOrders, dashboardPerps, dashboardSpot, loadAgentDashboard } from "./agent-dashboard.js";
3
+ /** One read-only connection per linked account, never per browser tab. */
4
+ export const openAccountFeed = (address, events, sharedTransport) => {
5
+ const transport = sharedTransport ?? new WebSocketTransport();
6
+ const client = new SubscriptionClient({ transport });
7
+ const abort = new AbortController();
8
+ let modeSeen = false;
9
+ let lastMode = null;
10
+ const connected = () => { modeSeen = false; events.connected(); };
11
+ const disconnected = () => events.disconnected();
12
+ transport.socket.addEventListener("open", connected);
13
+ transport.socket.addEventListener("close", disconnected);
14
+ const user = address;
15
+ const options = { signal: abort.signal, onError: () => events.failed() };
16
+ if (transport.socket.readyState === 1)
17
+ queueMicrotask(() => { if (!abort.signal.aborted)
18
+ connected(); });
19
+ const tasks = [
20
+ client.clearinghouseState({ user, dex: "" }, (event) => {
21
+ if (event.user.toLowerCase() === address && event.dex === "")
22
+ events.update("perps", dashboardPerps(event.clearinghouseState));
23
+ }, options),
24
+ client.spotState({ user }, (event) => {
25
+ if (event.user.toLowerCase() === address)
26
+ events.update("spot", dashboardSpot(event.spotState));
27
+ }, options),
28
+ client.openOrders({ user, dex: "" }, (event) => {
29
+ if (event.user.toLowerCase() === address && event.dex === "")
30
+ events.update("orders", dashboardOrders(event.orders));
31
+ }, options),
32
+ client.webData3({ user }, (event) => {
33
+ if (event.userState.user.toLowerCase() !== address)
34
+ return;
35
+ const mode = event.userState.abstraction ?? null;
36
+ // Omitted abstraction is unknown. Repair it once, not on every user event.
37
+ if (modeSeen && mode === lastMode)
38
+ return;
39
+ modeSeen = true;
40
+ lastMode = mode;
41
+ events.update("mode", { accountAbstraction: mode });
42
+ }, options),
43
+ ];
44
+ for (const task of tasks)
45
+ void task.catch(() => { if (!abort.signal.aborted)
46
+ events.failed(); });
47
+ return { async close() {
48
+ transport.socket.removeEventListener("open", connected);
49
+ transport.socket.removeEventListener("close", disconnected);
50
+ abort.abort();
51
+ if (!sharedTransport)
52
+ transport.close();
53
+ const subscriptions = await Promise.allSettled(tasks);
54
+ await Promise.allSettled(subscriptions.flatMap((result) => result.status === "fulfilled" ? [result.value.unsubscribe()] : []));
55
+ } };
56
+ };
57
+ const sections = ["perps", "spot", "orders", "mode"];
58
+ /** Ephemeral latest-state projection, not a journal or reliable event queue. */
59
+ export class LiveDashboards {
60
+ transport;
61
+ factory;
62
+ accounts = new Map();
63
+ stopped = false;
64
+ tasks = new Set();
65
+ constructor(transport = new HttpTransport(), factory = openAccountFeed) {
66
+ this.transport = transport;
67
+ this.factory = factory;
68
+ }
69
+ snapshot(address) {
70
+ return structuredClone(this.ensure(address.toLowerCase()).snapshot);
71
+ }
72
+ watch(address, signal, publish) {
73
+ if (signal.aborted)
74
+ return Promise.resolve();
75
+ const account = this.ensure(address.toLowerCase());
76
+ return new Promise((resolve) => {
77
+ const listener = () => publish(structuredClone(account.snapshot));
78
+ const finish = () => {
79
+ account.listeners.delete(listener);
80
+ signal.removeEventListener("abort", finish);
81
+ account.abort.signal.removeEventListener("abort", finish);
82
+ resolve();
83
+ };
84
+ account.listeners.add(listener);
85
+ signal.addEventListener("abort", finish, { once: true });
86
+ account.abort.signal.addEventListener("abort", finish, { once: true });
87
+ listener();
88
+ });
89
+ }
90
+ async reconcile(addresses) {
91
+ if (this.stopped)
92
+ return;
93
+ const wanted = new Set(addresses.map((address) => address.toLowerCase()));
94
+ for (const address of wanted)
95
+ this.ensure(address);
96
+ for (const [address, account] of this.accounts) {
97
+ if (wanted.has(address))
98
+ continue;
99
+ await this.stop(account);
100
+ this.accounts.delete(address);
101
+ }
102
+ }
103
+ ensure(address) {
104
+ if (this.stopped)
105
+ throw new Error("Live account service is closed");
106
+ const existing = this.accounts.get(address);
107
+ if (existing)
108
+ return existing;
109
+ const account = {
110
+ snapshot: {
111
+ address, accountAbstraction: null, fetchedAt: Date.now(), perpEquity: null, spotUsdc: null, positions: null, orders: null, errors: [],
112
+ live: { status: "connecting", sections: {
113
+ perps: { updatedAt: null, fresh: false }, spot: { updatedAt: null, fresh: false }, orders: { updatedAt: null, fresh: false }, mode: { updatedAt: null, fresh: false },
114
+ } },
115
+ },
116
+ listeners: new Set(), revision: { perps: 0, spot: 0, orders: 0, mode: 0 }, generation: 0, abort: new AbortController(),
117
+ };
118
+ this.accounts.set(address, account);
119
+ this.connect(account);
120
+ return account;
121
+ }
122
+ publish(account) {
123
+ for (const listener of account.listeners)
124
+ listener(account.snapshot);
125
+ }
126
+ connect(account) {
127
+ if (account.abort.signal.aborted)
128
+ return;
129
+ const generation = ++account.generation;
130
+ let epoch = 0;
131
+ let repairRunning = false;
132
+ let repairRequested = false;
133
+ const update = (section, patch) => {
134
+ const modeChanged = section === "mode" && patch.accountAbstraction !== account.snapshot.accountAbstraction;
135
+ if (modeChanged) {
136
+ // Balances observed before this boundary cannot establish current equity.
137
+ for (const balance of ["perps", "spot"]) {
138
+ account.snapshot.live.sections[balance].fresh = false;
139
+ account.revision[balance]++;
140
+ }
141
+ }
142
+ Object.assign(account.snapshot, patch);
143
+ account.revision[section]++;
144
+ const now = Date.now();
145
+ account.snapshot.fetchedAt = now;
146
+ account.snapshot.live.sections[section] = { updatedAt: now, fresh: section !== "mode" || account.snapshot.accountAbstraction !== null };
147
+ this.publish(account);
148
+ if (modeChanged || (section === "mode" && account.snapshot.accountAbstraction === null))
149
+ requestRepair();
150
+ };
151
+ const active = () => !account.abort.signal.aborted && generation === account.generation;
152
+ const requestRepair = () => {
153
+ repairRequested = true;
154
+ if (repairRunning || !active() || account.snapshot.live.status !== "connected")
155
+ return;
156
+ repairRequested = false;
157
+ repairRunning = true;
158
+ const connectionEpoch = epoch;
159
+ const revision = { ...account.revision };
160
+ const refresh = loadAgentDashboard(this.transport, account.snapshot.address, account.abort.signal).then((snapshot) => {
161
+ if (!active() || connectionEpoch !== epoch || account.snapshot.live.status !== "connected")
162
+ return;
163
+ // Apply mode first. A changed mode invalidates this request's balances
164
+ // and schedules a post-boundary repair, even for an idle account.
165
+ if (account.revision.mode === revision.mode && snapshot.accountAbstraction !== null)
166
+ update("mode", { accountAbstraction: snapshot.accountAbstraction });
167
+ for (const section of ["perps", "spot", "orders"]) {
168
+ if (account.revision[section] !== revision[section])
169
+ continue;
170
+ if (section === "perps" && snapshot.perpEquity !== null && snapshot.positions !== null)
171
+ update(section, { perpEquity: snapshot.perpEquity, positions: snapshot.positions });
172
+ if (section === "spot" && snapshot.spotUsdc !== null)
173
+ update(section, { spotUsdc: snapshot.spotUsdc, spotUsdcHold: snapshot.spotUsdcHold ?? null });
174
+ if (section === "orders" && snapshot.orders !== null)
175
+ update(section, { orders: snapshot.orders });
176
+ }
177
+ this.publish(account);
178
+ }).catch(() => { }).finally(() => {
179
+ repairRunning = false;
180
+ if (repairRequested && active() && account.snapshot.live.status === "connected")
181
+ requestRepair();
182
+ });
183
+ this.track(refresh);
184
+ };
185
+ const invalidate = () => {
186
+ ++epoch;
187
+ account.snapshot.live.status = "reconnecting";
188
+ for (const section of sections)
189
+ account.snapshot.live.sections[section].fresh = false;
190
+ this.publish(account);
191
+ };
192
+ const failed = () => {
193
+ if (!active())
194
+ return;
195
+ ++account.generation;
196
+ invalidate();
197
+ const feed = account.feed;
198
+ account.feed = undefined;
199
+ if (feed)
200
+ this.track(feed.close());
201
+ account.retry = setTimeout(() => this.connect(account), 5_000);
202
+ account.retry.unref();
203
+ };
204
+ try {
205
+ account.feed = this.factory(account.snapshot.address, {
206
+ connected: () => {
207
+ if (!active())
208
+ return;
209
+ account.snapshot.live.status = "connected";
210
+ this.publish(account);
211
+ // Only connection and mode events trigger HTTP repair; never polling.
212
+ ++epoch;
213
+ requestRepair();
214
+ },
215
+ disconnected: () => { if (active())
216
+ invalidate(); },
217
+ update: (section, patch) => { if (active())
218
+ update(section, patch); },
219
+ failed,
220
+ });
221
+ }
222
+ catch {
223
+ failed();
224
+ }
225
+ }
226
+ track(task) {
227
+ const tracked = task.finally(() => this.tasks.delete(tracked));
228
+ this.tasks.add(tracked);
229
+ }
230
+ async stop(account) {
231
+ clearTimeout(account.retry);
232
+ account.snapshot.live.status = "stopped";
233
+ for (const section of sections)
234
+ account.snapshot.live.sections[section].fresh = false;
235
+ this.publish(account);
236
+ account.abort.abort();
237
+ await account.feed?.close();
238
+ }
239
+ async close() {
240
+ this.stopped = true;
241
+ await Promise.all([...this.accounts.values()].map((account) => this.stop(account)));
242
+ this.accounts.clear();
243
+ await Promise.all(this.tasks);
244
+ }
245
+ }
@@ -0,0 +1,27 @@
1
+ import { SvgLogoCache } from "../cache/svg-logo-cache.js";
2
+ import { isPerpetualLogoSymbol } from "./currency-logo.js";
3
+ export function fallbackCurrencyLogo(symbol) {
4
+ // Only validated symbols may reach the SVG template.
5
+ if (!isPerpetualLogoSymbol(symbol))
6
+ throw new Error("Invalid currency symbol");
7
+ return Buffer.from(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="8" fill="#18181b"/><text x="16" y="21" text-anchor="middle" font-family="sans-serif" font-size="${symbol.length <= 3 ? 11 : 8}" textLength="26" lengthAdjust="spacingAndGlyphs" fill="#fafafa">${symbol}</text></svg>`);
8
+ }
9
+ const source = {
10
+ directory: "hyperliquid/logos",
11
+ validate: isPerpetualLogoSymbol,
12
+ url: (symbol) => `https://app.hyperliquid.xyz/coins/${encodeURIComponent(symbol)}.svg`,
13
+ fallback: fallbackCurrencyLogo,
14
+ };
15
+ /** Caches Hyperliquid perpetual coin logos; see {@link SvgLogoCache} for mechanics. */
16
+ export class CurrencyLogoCache {
17
+ cache;
18
+ constructor(root, fetcher = fetch) {
19
+ this.cache = new SvgLogoCache(root, source, fetcher);
20
+ }
21
+ get(symbol) {
22
+ return this.cache.get(symbol);
23
+ }
24
+ close() {
25
+ return this.cache.close();
26
+ }
27
+ }
@@ -0,0 +1,242 @@
1
+ import { HttpTransport, InfoClient } from "@nktkas/hyperliquid";
2
+ import { HyperliquidError } from "./errors.js";
3
+ import { intervalMillis, isChartInterval, mergeChartCandles } from "./chart-contracts.js";
4
+ const pageSize = 500;
5
+ function normalize(raw, selection) {
6
+ const candles = [];
7
+ for (const row of raw) {
8
+ if (row.s !== selection.coin || row.i !== selection.interval)
9
+ continue;
10
+ const candle = { time: row.t / 1000, open: Number(row.o), high: Number(row.h), low: Number(row.l), close: Number(row.c), volume: Number(row.v) };
11
+ if (!Number.isSafeInteger(row.t) || row.t < 0 || row.t % intervalMillis[selection.interval] !== 0
12
+ || !Object.values(candle).every(Number.isFinite) || candle.volume < 0 || candle.low <= 0
13
+ || candle.low > Math.min(candle.open, candle.close) || candle.high < Math.max(candle.open, candle.close))
14
+ continue;
15
+ candles.push(candle);
16
+ }
17
+ return mergeChartCandles([], candles);
18
+ }
19
+ /** Cancelling a consumer must not cancel a shared public-market-data request. */
20
+ function waitForSignal(task, signal) {
21
+ if (!signal)
22
+ return task;
23
+ if (signal.aborted) {
24
+ void task.catch(() => { }); // The abandoned caller must still observe rejection.
25
+ return Promise.reject(signal.reason);
26
+ }
27
+ return new Promise((resolve, reject) => {
28
+ const abort = () => { signal.removeEventListener("abort", abort); reject(signal.reason); };
29
+ signal.addEventListener("abort", abort, { once: true });
30
+ void task.then((value) => { signal.removeEventListener("abort", abort); resolve(value); }, (error) => { signal.removeEventListener("abort", abort); reject(error); });
31
+ });
32
+ }
33
+ /** Bounded ephemeral market data; history is shared across viewers, never persisted. */
34
+ export class MarketCharts {
35
+ factory;
36
+ info;
37
+ abort = new AbortController();
38
+ feeds = new Map();
39
+ tasks = new Set();
40
+ cache = new Map();
41
+ researchCache = new Map();
42
+ universe;
43
+ constructor(transport, factory) {
44
+ this.factory = factory;
45
+ this.info = new InfoClient({ transport });
46
+ }
47
+ admit() { if (this.abort.signal.aborted)
48
+ throw new HyperliquidError("Market data service is closed", 503); }
49
+ track(task) {
50
+ this.tasks.add(task);
51
+ void task.finally(() => this.tasks.delete(task)).catch(() => { });
52
+ return task;
53
+ }
54
+ instruments() {
55
+ return this.instrumentDetails().then((items) => items.map((item) => item.symbol));
56
+ }
57
+ instrumentDetails() {
58
+ this.admit();
59
+ if (this.universe && this.universe.expires > Date.now())
60
+ return this.universe.task;
61
+ const task = this.track(this.info.meta({ dex: "" }, this.abort.signal).then((meta) => meta.universe.filter((asset) => !asset.isDelisted)
62
+ .map((asset) => ({ symbol: asset.name, sizeDecimals: asset.szDecimals })).sort((a, b) => a.symbol.localeCompare(b.symbol))));
63
+ this.universe = { expires: Date.now() + 60_000, task };
64
+ void task.catch(() => { if (this.universe?.task === task)
65
+ this.universe = undefined; });
66
+ return task;
67
+ }
68
+ async selection(coin, interval) {
69
+ this.admit();
70
+ if (!isChartInterval(interval) || !coin || coin.length > 64)
71
+ throw new HyperliquidError("Invalid chart selection");
72
+ if (!(await this.instruments()).includes(coin))
73
+ throw new HyperliquidError("Select an available perpetual instrument");
74
+ return { coin, interval };
75
+ }
76
+ async history(selection, before) {
77
+ this.admit();
78
+ if (before !== undefined && (!Number.isSafeInteger(before) || before <= 0 || before > Date.now() + intervalMillis[selection.interval]))
79
+ throw new HyperliquidError("Invalid history cursor");
80
+ const width = intervalMillis[selection.interval];
81
+ // The cursor is an exclusive candle-open timestamp, in milliseconds.
82
+ const endTime = before === undefined ? Math.floor(Date.now() / width) * width : Math.floor((before - 1) / width) * width;
83
+ const startTime = Math.max(0, endTime - (pageSize - 1) * width);
84
+ const key = `${selection.coin}/${selection.interval}/${endTime}`;
85
+ const cached = this.cache.get(key);
86
+ if (cached && cached.expires > Date.now())
87
+ return cached.task;
88
+ if (this.tasks.size >= 12)
89
+ throw new HyperliquidError("Market data is busy. Please retry.", 429);
90
+ const task = this.track(this.info.candleSnapshot({ ...selection, startTime, endTime }, this.abort.signal).then((raw) => {
91
+ const candles = normalize(raw, selection).filter((candle) => candle.time * 1000 >= startTime && candle.time * 1000 <= endTime).slice(-pageSize);
92
+ return { candles, hasMore: candles.length > 0 && startTime > 0 };
93
+ }));
94
+ if (this.cache.size >= 64)
95
+ this.cache.delete(this.cache.keys().next().value);
96
+ this.cache.set(key, { expires: Date.now() + (before === undefined ? 2_000 : 60_000), task });
97
+ void task.catch(() => { if (this.cache.get(key)?.task === task)
98
+ this.cache.delete(key); });
99
+ return task;
100
+ }
101
+ /** Research pages have a fixed exclusive end and never include forming candles.
102
+ * Hyperliquid retains only the most recent ~5,000 candles per instrument/interval.
103
+ */
104
+ async researchHistory(coin, interval, start, end, limit, cancellation) {
105
+ cancellation?.throwIfAborted();
106
+ const selection = await waitForSignal(this.selection(coin, interval), cancellation);
107
+ const width = intervalMillis[selection.interval];
108
+ if (![start, end, limit].every(Number.isSafeInteger) || start < 0 || end <= start || end > Date.now() || limit < 1 || limit > 5000)
109
+ throw new HyperliquidError("Invalid research candle range");
110
+ const boundary = Math.min(Math.floor(end / width) * width, Math.floor(Date.now() / width) * width);
111
+ const pageStart = Math.ceil(start / width) * width;
112
+ const pageEnd = Math.min(boundary, pageStart + limit * width);
113
+ const key = JSON.stringify([selection.coin, selection.interval, pageStart, pageEnd]);
114
+ let cached = this.researchCache.get(key);
115
+ if (!cached || cached.expires <= Date.now()) {
116
+ if (this.tasks.size >= 12)
117
+ throw new HyperliquidError("Market data is busy", 429);
118
+ const task = pageEnd <= pageStart ? Promise.resolve([]) : this.track(this.info.candleSnapshot({ ...selection, startTime: pageStart, endTime: pageEnd - 1 }, AbortSignal.any([this.abort.signal, AbortSignal.timeout(15_000)]))
119
+ .then((raw) => normalize(raw, selection).filter((row) => row.time * 1000 >= pageStart && row.time * 1000 + width <= pageEnd)));
120
+ if (this.researchCache.size >= 16)
121
+ this.researchCache.delete(this.researchCache.keys().next().value);
122
+ cached = { expires: Date.now() + 60_000, task };
123
+ this.researchCache.set(key, cached);
124
+ void task.catch(() => { if (this.researchCache.get(key)?.task === task)
125
+ this.researchCache.delete(key); });
126
+ }
127
+ const items = (await waitForSignal(cached.task, cancellation)).slice(0, limit).map((candle) => ({ ...candle }));
128
+ const expected = Math.max(0, (pageEnd - pageStart) / width);
129
+ return { coin, interval, start, end: boundary, pageEnd, candles: items, nextStart: pageEnd < boundary ? pageEnd : null,
130
+ coverage: { complete: items.length === expected, returned: items.length, expected, sourceLimit: "Hyperliquid retains approximately the latest 5,000 candles; empty/gapped data is not proof of no trading.", closedOnly: true } };
131
+ }
132
+ watch(selection, signal, publish) {
133
+ this.admit();
134
+ if (signal.aborted)
135
+ return Promise.resolve();
136
+ const key = `${selection.coin}/${selection.interval}`;
137
+ let feed = this.feeds.get(key);
138
+ if (!feed) {
139
+ if (this.feeds.size >= 40)
140
+ throw new HyperliquidError("Too many active charts. Please retry.", 429);
141
+ feed = { snapshot: { candles: [], status: "connecting" }, listeners: new Set(), abort: new AbortController(), updates: new Map(), generation: 0 };
142
+ this.feeds.set(key, feed);
143
+ }
144
+ const current = feed;
145
+ const task = new Promise((resolve) => {
146
+ const listener = (snapshot) => publish(structuredClone(snapshot));
147
+ const finish = () => {
148
+ current.listeners.delete(listener);
149
+ signal.removeEventListener("abort", finish);
150
+ current.abort.signal.removeEventListener("abort", finish);
151
+ if (!current.listeners.size && this.feeds.get(key) === current) {
152
+ this.feeds.delete(key);
153
+ void this.stop(current);
154
+ }
155
+ resolve();
156
+ };
157
+ current.listeners.add(listener);
158
+ signal.addEventListener("abort", finish, { once: true });
159
+ current.abort.signal.addEventListener("abort", finish, { once: true });
160
+ listener(current.snapshot);
161
+ if (!current.handle)
162
+ this.open(current, selection);
163
+ });
164
+ return task;
165
+ }
166
+ publish(feed) { for (const listener of feed.listeners)
167
+ listener(feed.snapshot); }
168
+ open(feed, selection) {
169
+ const generation = ++feed.generation;
170
+ feed.updates.clear();
171
+ const active = () => !feed.abort.signal.aborted && feed.generation === generation;
172
+ const repair = async () => {
173
+ const history = await this.history(selection);
174
+ if (!active())
175
+ return;
176
+ // HTTP must never overwrite newer websocket values for the forming candle.
177
+ feed.snapshot.candles = mergeChartCandles(history.candles, [...feed.updates.values()]).slice(-pageSize);
178
+ feed.snapshot.status = "live";
179
+ this.publish(feed);
180
+ };
181
+ const disconnected = () => { if (active()) {
182
+ ++feed.generation;
183
+ feed.snapshot.status = "reconnecting";
184
+ this.publish(feed);
185
+ this.retry(feed, selection);
186
+ } };
187
+ try {
188
+ feed.handle = this.factory(selection, {
189
+ connected: () => { if (active())
190
+ void this.track(repair()).catch(disconnected); },
191
+ disconnected,
192
+ failed: disconnected,
193
+ update: (raw) => {
194
+ if (!active())
195
+ return;
196
+ const candles = normalize([raw], selection);
197
+ if (!candles.length)
198
+ return;
199
+ for (const candle of candles)
200
+ feed.updates.set(candle.time, candle);
201
+ if (feed.updates.size > pageSize)
202
+ feed.updates.delete(feed.updates.keys().next().value);
203
+ feed.snapshot.candles = mergeChartCandles(feed.snapshot.candles, candles).slice(-pageSize);
204
+ this.publish(feed);
205
+ },
206
+ });
207
+ }
208
+ catch {
209
+ disconnected();
210
+ }
211
+ }
212
+ retry(feed, selection) {
213
+ if (feed.retry || feed.abort.signal.aborted)
214
+ return;
215
+ feed.retry = setTimeout(() => {
216
+ feed.retry = undefined;
217
+ const old = feed.handle;
218
+ feed.handle = undefined;
219
+ void this.track((async () => {
220
+ await old?.close();
221
+ if (!feed.abort.signal.aborted)
222
+ this.open(feed, selection);
223
+ })()).catch(() => this.retry(feed, selection));
224
+ }, 3_000);
225
+ feed.retry.unref();
226
+ }
227
+ stop(feed) {
228
+ feed.abort.abort();
229
+ clearTimeout(feed.retry);
230
+ return this.track(feed.handle?.close() ?? Promise.resolve());
231
+ }
232
+ async close() {
233
+ this.abort.abort();
234
+ const feeds = [...this.feeds.values()];
235
+ this.feeds.clear();
236
+ for (const feed of feeds)
237
+ void this.stop(feed);
238
+ await Promise.allSettled(this.tasks);
239
+ this.cache.clear();
240
+ this.researchCache.clear();
241
+ }
242
+ }
@@ -0,0 +1,45 @@
1
+ import { Type } from "@earendil-works/pi-ai";
2
+ import { InfoClient } from "@nktkas/hyperliquid";
3
+ import { HyperliquidError } from "./errors.js";
4
+ import { amount } from "./journal-decimal.js";
5
+ const decimal = Type.String({ pattern: "^-?[0-9]+(\\.[0-9]+)?$" });
6
+ const nullableDecimal = Type.Union([decimal, Type.Null()]);
7
+ export const MarketSnapshotSchema = Type.Object({
8
+ instrument: Type.String(), scope: Type.Literal("main-dex-perpetuals"),
9
+ source: Type.Literal("Hyperliquid metaAndAssetCtxs HTTP"), observedAt: Type.Integer(),
10
+ midPrice: nullableDecimal, markPrice: decimal, oraclePrice: decimal,
11
+ previousDayPrice: decimal, markChange24hPercent: nullableDecimal,
12
+ volume24hUsd: decimal, volume24hBase: decimal, fundingRateHourly: decimal,
13
+ openInterestBase: decimal, warning: Type.String(),
14
+ });
15
+ /** A single venue response keeps metadata and its index-aligned contexts together. */
16
+ export async function loadMarketSnapshot(transport, instrument, signal) {
17
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,31}$/.test(instrument))
18
+ throw new HyperliquidError("Select a main-DEX perpetual instrument such as BTC.");
19
+ const requestSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(10_000)]) : AbortSignal.timeout(10_000);
20
+ requestSignal.throwIfAborted();
21
+ const [meta, contexts] = await new InfoClient({ transport }).metaAndAssetCtxs({ dex: "" }, requestSignal);
22
+ const observedAt = Date.now();
23
+ const index = meta.universe.findIndex((asset) => asset.name === instrument && !asset.isDelisted);
24
+ if (index < 0)
25
+ throw new HyperliquidError("Unknown or delisted main-DEX perpetual instrument.", 404);
26
+ const ctx = contexts[index];
27
+ if (!ctx || contexts.length !== meta.universe.length)
28
+ throw new HyperliquidError("Market snapshot context is unavailable.", 502);
29
+ // Reject malformed data, rather than silently turning missing values into zero.
30
+ const nonnegative = [ctx.markPx, ctx.oraclePx, ctx.prevDayPx, ctx.dayNtlVlm, ctx.dayBaseVlm, ctx.openInterest, ...(ctx.midPx === null ? [] : [ctx.midPx])];
31
+ if (nonnegative.some((value) => amount(value).sign < 0))
32
+ throw new HyperliquidError("Invalid market snapshot amounts.", 502);
33
+ amount(ctx.funding);
34
+ const previous = amount(ctx.prevDayPx);
35
+ return {
36
+ instrument, scope: "main-dex-perpetuals",
37
+ source: "Hyperliquid metaAndAssetCtxs HTTP", observedAt,
38
+ midPrice: ctx.midPx, markPrice: ctx.markPx, oraclePrice: ctx.oraclePx,
39
+ previousDayPrice: ctx.prevDayPx,
40
+ markChange24hPercent: previous.zero ? null : amount(ctx.markPx).sub(previous).mul(amount("100")).div(previous).toString(),
41
+ volume24hUsd: ctx.dayNtlVlm, volume24hBase: ctx.dayBaseVlm,
42
+ fundingRateHourly: ctx.funding, openInterestBase: ctx.openInterest,
43
+ warning: "Host observation time in UTC milliseconds, not a venue timestamp. Mid/mark/oracle prices are not executable quotes or last-trade prices. 24h change uses mark versus previous-day price; null means unavailable. Funding is an hourly decimal rate, not percent or APR. Volume is rolling 24h; open interest is base-asset quantity. Snapshot only, not candle/indicator research or trade authority.",
44
+ };
45
+ }
@@ -0,0 +1,42 @@
1
+ import { Type } from "@earendil-works/pi-ai";
2
+ const object = { additionalProperties: false };
3
+ export const Decimal = Type.String({ pattern: "^(0|[1-9][0-9]*)(\\.[0-9]+)?$", maxLength: 80, description: "Exact plain decimal string, never a JSON number or exponent." });
4
+ export const OrderSize = { ...Decimal, description: "Exact positive base-asset quantity, NOT USD notional. Read list_instruments sizeDecimals/sizeStep first; do not guess precision or silently increase the user's size/budget. For a USD budget, choose an expressible base quantity consistent with that budget." };
5
+ export const OrderPrice = { ...Decimal, description: "Exact positive price string. Read list_instruments: fractional prices must satisfy BOTH priceMaxDecimals and priceMaxSignificantFigures; positive integer prices are exempt from these precision limits." };
6
+ export const RequestId = Type.String({ minLength: 1, maxLength: 120, pattern: "^[a-zA-Z0-9_-]+$", description: "Unique logical request ID. Reuse with identical arguments on retry; never issue a new ID to retry an unknown outcome." });
7
+ const SymbolName = Type.String({ minLength: 1, maxLength: 30, pattern: "^[A-Za-z0-9_-]+$", description: "Exact main-DEX perpetual symbol from exchange metadata (e.g. BTC). No spot or HIP-3 symbols." });
8
+ const Trigger = Type.Object({ trigger_price: OrderPrice, limit_price: Type.Optional(OrderPrice), size: Type.Optional(OrderSize) }, object);
9
+ export const OrderInputSchema = Type.Object({
10
+ symbol: SymbolName, side: Type.Union([Type.Literal("buy"), Type.Literal("sell")]),
11
+ order_type: Type.Union([Type.Literal("limit"), Type.Literal("market"), Type.Literal("take_profit"), Type.Literal("stop_loss")], { description: 'Use "limit" with price, "market" for a 0.5%-guarded IOC (omit price/time_in_force), or "take_profit"/"stop_loss" for standalone reduce-only triggers with trigger_price. This is not the planner entry_style field.' }),
12
+ size: OrderSize, price: Type.Optional(OrderPrice), trigger_price: Type.Optional(OrderPrice),
13
+ time_in_force: Type.Optional(Type.Union([Type.Literal("gtc"), Type.Literal("ioc"), Type.Literal("alo")], { description: 'Limit orders only: "gtc" (default), "ioc", or "alo". Omit for market orders and standalone triggers.' })),
14
+ reduce_only: Type.Optional(Type.Boolean()),
15
+ take_profits: Type.Optional(Type.Array(Trigger, { maxItems: 1, description: "At most one attached native OCO take-profit. Use a standalone reduce-only trigger for position-level protection." })),
16
+ stop_losses: Type.Optional(Type.Array(Trigger, { maxItems: 1 })),
17
+ }, object);
18
+ export const SubmitSchema = Type.Object({ request_id: RequestId, decision_ref: Type.Optional(Type.String({ pattern: "^m[1-9][0-9]*$", maxLength: 17, description: "Optional reference to a decision that actually motivates this submission, for audit only, never trading authority. For a direct/manual user request with no memory-based rationale, omit this field; no research or decision memory is required. Do not attach an unrelated or previously blocked/skipped decision just to populate it." })), orders: Type.Array(OrderInputSchema, { minItems: 1, maxItems: 20 }) }, object);
19
+ export const CancelInputSchema = Type.Object({ symbol: SymbolName, oid: Type.String({ pattern: "^[1-9][0-9]*$", maxLength: 16, description: "Exchange order ID as a decimal string." }) }, object);
20
+ export const CancelSchema = Type.Object({ request_id: RequestId, orders: Type.Array(CancelInputSchema, { minItems: 1, maxItems: 100 }) }, object);
21
+ export const CancelAllSchema = Type.Object({ request_id: RequestId, symbol: Type.Optional(SymbolName) }, object);
22
+ export const ListSchema = Type.Object({
23
+ source: Type.Optional(Type.Union([Type.Literal("open"), Type.Literal("local")])), symbol: Type.Optional(SymbolName), status: Type.Optional(Type.String({ maxLength: 60 })),
24
+ limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })), offset: Type.Optional(Type.Integer({ minimum: 0, maximum: 100000 })),
25
+ }, object);
26
+ export const GetSchema = Type.Object({ order_id: Type.String({ minLength: 1, maxLength: 80 }), include_events: Type.Optional(Type.Boolean()) }, object);
27
+ const NullableString = Type.Union([Type.String(), Type.Null()]);
28
+ export const OrderViewSchema = Type.Object({
29
+ id: Type.String(), requestId: NullableString, symbol: Type.String(), side: Type.String(), kind: Type.String(),
30
+ size: NullableString, price: NullableString, triggerPrice: NullableString, reduceOnly: Type.Boolean(),
31
+ cloid: NullableString, exchangeOid: NullableString,
32
+ commandStatus: Type.Union([Type.Literal("not_sent"), Type.Literal("accepted"), Type.Literal("rejected"), Type.Literal("unknown"), Type.Literal("reconciled")]),
33
+ orderStatus: Type.String(), filledSize: NullableString, averageFillPrice: NullableString,
34
+ updatedAt: Type.Number(), venueTimestamp: Type.Union([Type.Number(), Type.Null()]), source: Type.String(), error: NullableString,
35
+ }, object);
36
+ export const OperationSchema = Type.Object({
37
+ operationId: Type.String(), requestId: Type.String(), kind: Type.String(),
38
+ results: Type.Array(OrderViewSchema), uncertain: Type.Boolean(), warnings: Type.Array(Type.String()),
39
+ }, object);
40
+ export const EventSchema = Type.Object({ id: Type.Number(), source: Type.String(), time: Type.Number(), data: Type.String() }, object);
41
+ export const GetResultSchema = Type.Object({ order: Type.Union([OrderViewSchema, Type.Null()]), events: Type.Array(EventSchema), error: NullableString, observedAt: Type.Number() }, object);
42
+ export const ListResultSchema = Type.Object({ items: Type.Array(OrderViewSchema), source: Type.String(), observedAt: Type.Number(), nextOffset: Type.Union([Type.Number(), Type.Null()]), coverage: Type.String() }, object);