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,648 @@
1
+ import { enqueueAccountEvent } from "../agents/worker-events.js";
2
+ import { InfoClient, SubscriptionClient, WebSocketTransport } from "@nktkas/hyperliquid";
3
+ import { randomUUID } from "node:crypto";
4
+ import { HyperliquidError } from "./errors.js";
5
+ import { amount } from "./journal-decimal.js";
6
+ import { chartFillRange } from "../charts/trading-contracts.js";
7
+ import { buildTrades, fillEvent, fundingEvent, ledgerEvent, wsFundingEvent } from "./journal-model.js";
8
+ /** Subscribes one account to exchange push events on the shared read-only socket. */
9
+ export const openJournalFeed = (address, events, sharedTransport) => {
10
+ const transport = sharedTransport ?? new WebSocketTransport();
11
+ const client = new SubscriptionClient({ transport });
12
+ const abort = new AbortController();
13
+ const connected = () => events.connected();
14
+ const disconnected = () => events.disconnected();
15
+ transport.socket.addEventListener("open", connected);
16
+ transport.socket.addEventListener("close", disconnected);
17
+ if (transport.socket.readyState === 1)
18
+ queueMicrotask(() => { if (!abort.signal.aborted)
19
+ connected(); });
20
+ const user = address;
21
+ const options = { signal: abort.signal, onError: () => events.failed() };
22
+ // A malformed push invalidates the whole batch; HTTP catch-up re-verifies it.
23
+ const emit = (stream, map, rows) => {
24
+ if (rows.length === 0)
25
+ return;
26
+ try {
27
+ events.push(stream, rows.map(map));
28
+ }
29
+ catch {
30
+ events.failed();
31
+ }
32
+ };
33
+ const tasks = [
34
+ client.orderUpdates({ user }, (updates) => { if (!abort.signal.aborted)
35
+ events.orders?.(updates); }, options),
36
+ client.userFills({ user, aggregateByTime: false }, (event) => {
37
+ if (event.user.toLowerCase() === address)
38
+ emit("fill", fillEvent, event.fills);
39
+ }, options),
40
+ client.userFundings({ user }, (event) => {
41
+ if (event.user.toLowerCase() === address)
42
+ emit("funding", wsFundingEvent, event.fundings);
43
+ }, options),
44
+ client.userNonFundingLedgerUpdates({ user }, (event) => {
45
+ if (event.user.toLowerCase() === address)
46
+ emit("ledger", (row) => ledgerEvent(address, row), event.nonFundingLedgerUpdates);
47
+ }, options),
48
+ ];
49
+ for (const task of tasks)
50
+ void task.catch(() => { if (!abort.signal.aborted)
51
+ events.failed(); });
52
+ return { async close() {
53
+ transport.socket.removeEventListener("open", connected);
54
+ transport.socket.removeEventListener("close", disconnected);
55
+ abort.abort();
56
+ if (!sharedTransport)
57
+ transport.close();
58
+ const subscriptions = await Promise.allSettled(tasks);
59
+ await Promise.allSettled(subscriptions.flatMap((result) => result.status === "fulfilled" ? [result.value.unsubscribe()] : []));
60
+ } };
61
+ };
62
+ const FULL_SCAN_MS = 86_400_000;
63
+ const SYNC_RETRY_MS = 30_000;
64
+ const FEED_RETRY_MS = 5_000;
65
+ const sleep = (ms, signal) => new Promise((resolve) => {
66
+ const finish = () => { clearTimeout(timer); signal.removeEventListener("abort", finish); resolve(); };
67
+ const timer = setTimeout(finish, ms);
68
+ timer.unref();
69
+ signal.addEventListener("abort", finish, { once: true });
70
+ });
71
+ export function exchangeHistory(transport) {
72
+ const info = new InfoClient({ transport });
73
+ return async (account, stream, startTime, endTime, cancellation) => {
74
+ const signal = AbortSignal.any([cancellation, AbortSignal.timeout(10_000)]);
75
+ const params = { user: account, startTime, endTime };
76
+ if (stream === "fill")
77
+ return (await info.userFillsByTime({ ...params, aggregateByTime: false, reversed: false }, signal)).map(fillEvent);
78
+ if (stream === "funding")
79
+ return (await info.userFunding(params, signal)).map(fundingEvent);
80
+ return (await info.userNonFundingLedgerUpdates(params, signal)).map((row) => ledgerEvent(account, row));
81
+ };
82
+ }
83
+ /** Backend-owned, single-flight account ingestion. No exchange I/O in SQLite transactions. */
84
+ export class JournalService {
85
+ db;
86
+ fetchHistory;
87
+ log;
88
+ feedFactory;
89
+ notifications;
90
+ workers = new Map();
91
+ stopped = false;
92
+ balanceWatches = new Map();
93
+ /** Shared per-account refresh work. Attach before reading so commits cannot be lost. */
94
+ watchBalanceHistory(account, publish) {
95
+ account = account.toLowerCase();
96
+ if (this.stopped)
97
+ throw new Error("Journal is closed");
98
+ let watch = this.balanceWatches.get(account);
99
+ if (!watch) {
100
+ watch = { listeners: new Set(), pending: false };
101
+ this.balanceWatches.set(account, watch);
102
+ }
103
+ watch.listeners.add(publish);
104
+ if (watch.value !== undefined) {
105
+ try {
106
+ publish(watch.value);
107
+ }
108
+ catch (error) {
109
+ this.log?.error({ err: error, account }, "Balance history subscriber failed");
110
+ }
111
+ }
112
+ else if (!watch.task)
113
+ this.balanceChanged(account);
114
+ const current = watch;
115
+ return Object.assign(async () => {
116
+ current.listeners.delete(publish);
117
+ if (current.listeners.size === 0) {
118
+ clearTimeout(current.timer);
119
+ if (this.balanceWatches.get(account) === current)
120
+ this.balanceWatches.delete(account);
121
+ await current.task;
122
+ }
123
+ }, { ready: current.task ?? Promise.resolve() });
124
+ }
125
+ balanceChanged(account) {
126
+ const watch = this.balanceWatches.get(account);
127
+ if (!watch || this.stopped)
128
+ return;
129
+ watch.pending = true;
130
+ clearTimeout(watch.timer);
131
+ if (watch.task)
132
+ return;
133
+ watch.task = (async () => {
134
+ while (watch.pending && !this.stopped && this.balanceWatches.get(account) === watch) {
135
+ watch.pending = false;
136
+ let result;
137
+ try {
138
+ result = await this.readBalanceHistory(account, Date.now());
139
+ }
140
+ catch (error) {
141
+ this.log?.error({ err: error, account }, "Unable to refresh balance history");
142
+ result = { history: null, nextChange: null };
143
+ }
144
+ if (this.stopped || this.balanceWatches.get(account) !== watch)
145
+ return;
146
+ // A commit during the read invalidates its result; drain the newer state first.
147
+ if (watch.pending)
148
+ continue;
149
+ const unchangedUnavailable = watch.value === null && result.history === null;
150
+ watch.value = result.history;
151
+ if (!unchangedUnavailable)
152
+ for (const listener of watch.listeners) {
153
+ try {
154
+ listener(result.history);
155
+ }
156
+ catch (error) {
157
+ this.log?.error({ err: error, account }, "Balance history subscriber failed");
158
+ }
159
+ }
160
+ if (result.nextChange !== null && !watch.pending) {
161
+ watch.timer = setTimeout(() => this.balanceChanged(account), Math.max(1, result.nextChange - Date.now()));
162
+ watch.timer.unref();
163
+ }
164
+ }
165
+ })().finally(() => {
166
+ watch.task = undefined;
167
+ if (watch.pending && this.balanceWatches.get(account) === watch)
168
+ this.balanceChanged(account);
169
+ });
170
+ }
171
+ shutdown = new AbortController();
172
+ syncs = new Map();
173
+ catchups = new Map();
174
+ eventTasks = new Set();
175
+ constructor(db, fetchHistory, log, feedFactory) {
176
+ this.db = db;
177
+ this.fetchHistory = fetchHistory;
178
+ this.log = log;
179
+ this.feedFactory = feedFactory;
180
+ }
181
+ async reconcile(addresses) {
182
+ if (this.stopped)
183
+ return;
184
+ const retiring = [];
185
+ const desired = new Set(addresses.map((a) => a.toLowerCase()));
186
+ if (desired.size > 0 && this.workers.size === 0)
187
+ this.log?.info({ accounts: desired.size }, "Synchronizing trade journals");
188
+ for (const [account, worker] of this.workers)
189
+ if (!desired.has(account)) {
190
+ worker.controller.abort();
191
+ clearTimeout(worker.feedTimer);
192
+ clearTimeout(worker.dailyTimer);
193
+ const feed = worker.feed;
194
+ retiring.push((async () => {
195
+ await Promise.all([feed?.close(), worker.task, worker.chain]);
196
+ worker.feed = undefined;
197
+ if (this.workers.get(account) === worker)
198
+ this.workers.delete(account);
199
+ })());
200
+ }
201
+ for (const account of desired) {
202
+ if (this.workers.has(account))
203
+ continue;
204
+ this.workers.set(account, this.createWorker(account));
205
+ }
206
+ await Promise.all(retiring);
207
+ }
208
+ /** One worker per account: an initial and daily full repair scan, exchange
209
+ * push ingestion, and a catch-up scan on every feed (re)connection. */
210
+ createWorker(account) {
211
+ const controller = new AbortController();
212
+ const signal = controller.signal;
213
+ const worker = { controller, chain: Promise.resolve() };
214
+ const healthy = async (fullScan) => {
215
+ try {
216
+ await this.syncAccount(account, signal, Date.now(), fullScan);
217
+ const rows = await this.db.all("SELECT error FROM hv_journal_sync WHERE account=?", account);
218
+ return rows.length === 3 && rows.every((row) => row.error === null);
219
+ }
220
+ catch (error) {
221
+ if (!signal.aborted)
222
+ this.log?.error({ err: error, account }, "Unable to synchronize trade journal; retrying");
223
+ return false;
224
+ }
225
+ };
226
+ const sync = (fullScan) => {
227
+ worker.chain = worker.chain.then(async () => {
228
+ let ok = await healthy(fullScan);
229
+ while (!ok && !signal.aborted) {
230
+ await sleep(SYNC_RETRY_MS, signal);
231
+ if (signal.aborted)
232
+ return;
233
+ ok = await healthy(false);
234
+ }
235
+ });
236
+ return worker.chain;
237
+ };
238
+ const ingestPush = async (stream, events) => {
239
+ if (signal.aborted || events.length === 0)
240
+ return;
241
+ try {
242
+ if (await this.ingest(account, stream, events)) {
243
+ await this.project(account);
244
+ this.log?.debug({ account, stream, count: events.length }, "Ingested pushed trade journal events");
245
+ }
246
+ }
247
+ catch (error) {
248
+ if (!signal.aborted)
249
+ this.log?.error({ err: error, account }, "Unable to ingest pushed trade journal events");
250
+ }
251
+ };
252
+ const openFeed = () => {
253
+ if (signal.aborted || worker.feed || !this.feedFactory)
254
+ return;
255
+ try {
256
+ worker.feed = this.feedFactory(account, {
257
+ connected: () => { if (!signal.aborted)
258
+ void sync(false); },
259
+ disconnected: () => { },
260
+ failed: reopen,
261
+ push: (stream, events) => { this.trackEvent(ingestPush(stream, events)); },
262
+ orders: (updates) => { if (!signal.aborted)
263
+ this.trackEvent(this.ingestOrderUpdates(account, updates)); },
264
+ });
265
+ }
266
+ catch {
267
+ reopen();
268
+ }
269
+ };
270
+ const reopen = () => {
271
+ if (signal.aborted || !this.feedFactory)
272
+ return;
273
+ clearTimeout(worker.feedTimer);
274
+ const feed = worker.feed;
275
+ worker.feed = undefined;
276
+ void feed?.close();
277
+ worker.feedTimer = setTimeout(() => { worker.feedTimer = undefined; openFeed(); }, FEED_RETRY_MS);
278
+ worker.feedTimer.unref();
279
+ };
280
+ const scheduleDaily = () => {
281
+ if (signal.aborted)
282
+ return;
283
+ worker.dailyTimer = setTimeout(() => {
284
+ worker.dailyTimer = undefined;
285
+ void sync(true).then(scheduleDaily);
286
+ }, FULL_SCAN_MS);
287
+ worker.dailyTimer.unref();
288
+ };
289
+ worker.task = sync(true).then(() => {
290
+ if (signal.aborted)
291
+ return;
292
+ openFeed();
293
+ scheduleDaily();
294
+ });
295
+ return worker;
296
+ }
297
+ trackEvent(task) {
298
+ const tracked = task.then(() => { }, (error) => { this.log?.error(error, "Unable to persist exchange event"); }).finally(() => this.eventTasks.delete(tracked));
299
+ this.eventTasks.add(tracked);
300
+ }
301
+ async ingestOrderUpdates(account, updates) {
302
+ await this.db.transaction(async (tx) => {
303
+ for (const update of updates) {
304
+ // Fills have their own deduplicated journal trigger; routine acknowledgments do not wake a model.
305
+ if (["open", "filled", "triggered"].includes(update.status))
306
+ continue;
307
+ await enqueueAccountEvent(tx, account, `order:${update.order.oid}:${update.status}:${update.statusTimestamp}`, "order_status", `Order status change: ${JSON.stringify(update)}. Inspect current account/orders and decide whether action is needed. Do not blindly replace canceled or rejected orders.`, update.statusTimestamp);
308
+ }
309
+ });
310
+ }
311
+ async close() {
312
+ this.stopped = true;
313
+ this.shutdown.abort();
314
+ const balanceTasks = [...this.balanceWatches.values()].map((watch) => {
315
+ clearTimeout(watch.timer);
316
+ watch.listeners.clear();
317
+ return watch.task;
318
+ });
319
+ this.balanceWatches.clear();
320
+ await Promise.all(balanceTasks);
321
+ const workers = [...this.workers.values()];
322
+ for (const worker of workers) {
323
+ worker.controller.abort();
324
+ clearTimeout(worker.feedTimer);
325
+ clearTimeout(worker.dailyTimer);
326
+ }
327
+ await Promise.all(workers.map(async (worker) => {
328
+ await Promise.allSettled([worker.task, worker.chain]);
329
+ const feed = worker.feed;
330
+ worker.feed = undefined;
331
+ if (feed)
332
+ await feed.close().catch(() => { });
333
+ }));
334
+ this.workers.clear();
335
+ await Promise.allSettled([...this.syncs.values()]);
336
+ await Promise.all(this.eventTasks);
337
+ }
338
+ /** Shared with background repair: never overlap HTTP scans of one account. */
339
+ syncAccount(account, signal, now = Date.now(), fullScan = false) {
340
+ account = account.toLowerCase();
341
+ const key = account;
342
+ const task = (this.syncs.get(key) ?? Promise.resolve()).catch(() => { }).then(async () => {
343
+ signal.throwIfAborted();
344
+ await this.synchronize(key, signal, now, fullScan);
345
+ });
346
+ this.syncs.set(key, task);
347
+ const clean = () => { if (this.syncs.get(key) === task)
348
+ this.syncs.delete(key); };
349
+ void task.then(clean, clean);
350
+ return task;
351
+ }
352
+ /** Bounded, single-flight catch-up. Failure leaves previously ingested evidence
353
+ * readable; the caller still checks actual coverage, never assumes success. */
354
+ async ensureThrough(account, end, cancellation) {
355
+ if (!Number.isSafeInteger(end) || end < 0 || end > Date.now())
356
+ return { attempted: false, limitation: "Review boundary is invalid or in the future; coverage is not guaranteed" };
357
+ account = account.toLowerCase();
358
+ if (this.stopped)
359
+ return { attempted: false, limitation: "Journal is shutting down" };
360
+ const rows = await this.db.all("SELECT cursor,error,updated_at FROM hv_journal_sync WHERE account=?", account);
361
+ if (rows.length === 3 && rows.every((row) => row.cursor >= end && row.updated_at !== null && !row.error)) {
362
+ await this.project(account);
363
+ return { attempted: false, limitation: null };
364
+ }
365
+ const deadline = AbortSignal.any([this.shutdown.signal, AbortSignal.timeout(20_000)]);
366
+ let task = this.catchups.get(account);
367
+ if (!task) {
368
+ task = this.syncAccount(account, deadline);
369
+ this.catchups.set(account, task);
370
+ const key = account, work = task;
371
+ const clean = () => { if (this.catchups.get(key) === work)
372
+ this.catchups.delete(key); };
373
+ void work.then(clean, clean);
374
+ }
375
+ const signal = AbortSignal.any([deadline, ...(cancellation ? [cancellation] : [])]);
376
+ let abort = () => { };
377
+ try {
378
+ await Promise.race([task, new Promise((_resolve, reject) => {
379
+ abort = () => reject(signal.reason);
380
+ signal.addEventListener("abort", abort, { once: true });
381
+ if (signal.aborted)
382
+ abort();
383
+ })]);
384
+ return { attempted: true, limitation: null };
385
+ }
386
+ catch {
387
+ cancellation?.throwIfAborted();
388
+ return { attempted: true, limitation: "Journal catch-up did not finish within its deadline; inspect coverage and disclose incomplete evidence" };
389
+ }
390
+ finally {
391
+ signal.removeEventListener("abort", abort);
392
+ }
393
+ }
394
+ async synchronize(account, signal, now, fullScan) {
395
+ await this.db.run("INSERT INTO hv_journal_accounts(account) VALUES (?) ON CONFLICT DO NOTHING", account);
396
+ for (const stream of ["fill", "funding", "ledger"]) {
397
+ if (signal.aborted)
398
+ return;
399
+ await this.db.run("INSERT INTO hv_journal_sync(account,stream) VALUES (?,?) ON CONFLICT DO NOTHING", account, stream);
400
+ const state = await this.db.get("SELECT cursor,updated_at FROM hv_journal_sync WHERE account=? AND stream=?", account, stream);
401
+ // Wide funding windows repair sparse hourly results; fills/ledger use a
402
+ // short overlap. Startup and daily full rescans repair older corrections.
403
+ // Per-page checkpoints survive crashes without skipping source data.
404
+ const overlap = stream === "funding" ? 7 * 86_400_000 : 120_000;
405
+ const start = fullScan ? 0 : Math.max(0, (state?.cursor ?? 0) - overlap);
406
+ try {
407
+ await this.window(account, stream, start, now, signal);
408
+ if (stream === "fill" && state?.updated_at === null) {
409
+ const count = await this.db.get("SELECT count(*) AS total FROM hv_journal_entries WHERE account=? AND kind='fill'", account);
410
+ // The API exposes only the latest 10,000 fills. Conservatively flag an
411
+ // initial import reaching that boundary; do not assert a full balance.
412
+ if ((count?.total ?? 0) >= 10_000) {
413
+ const result = await this.db.get("UPDATE hv_journal_accounts SET history_limited=1 WHERE account=? AND history_limited=0 RETURNING account", account);
414
+ if (result)
415
+ this.balanceChanged(account);
416
+ }
417
+ }
418
+ const availability = state?.updated_at === null || (await this.db.get("SELECT error FROM hv_journal_sync WHERE account=? AND stream=?", account, stream))?.error;
419
+ await this.db.run("UPDATE hv_journal_sync SET updated_at=?,error=NULL WHERE account=? AND stream=?", now, account, stream);
420
+ if (availability)
421
+ this.balanceChanged(account);
422
+ }
423
+ catch (error) {
424
+ if (signal.aborted)
425
+ return;
426
+ const message = error instanceof HistoryCoverageError ? error.message : "History sync failed; retrying. Previously imported data is retained.";
427
+ const result = await this.db.get("UPDATE hv_journal_sync SET error=? WHERE account=? AND stream=? AND error IS NOT ? RETURNING account", message, account, stream, message);
428
+ if (result)
429
+ this.balanceChanged(account);
430
+ }
431
+ }
432
+ if (!signal.aborted) {
433
+ this.log?.debug({ account }, "Synchronized trade journal");
434
+ await this.project(account);
435
+ }
436
+ }
437
+ async window(account, stream, start, end, signal) {
438
+ signal.throwIfAborted();
439
+ const rows = await this.fetchHistory(account, stream, start, end, signal);
440
+ if (rows.some((e) => e.kind !== stream || !Number.isSafeInteger(e.time) || e.time < start || e.time > end))
441
+ throw new Error("Invalid history response");
442
+ // Time endpoints cap either elements or distinct blocks. Conservatively split
443
+ // at 500, even for fills (whose element cap is 2000). Never skip timestamp ties.
444
+ if (rows.length >= 500) {
445
+ if (start === end) {
446
+ await this.ingest(account, stream, rows, start);
447
+ throw new HistoryCoverageError("Exchange history is saturated at one timestamp; coverage is incomplete.");
448
+ }
449
+ const middle = start + Math.floor((end - start) / 2);
450
+ await this.window(account, stream, start, middle, signal);
451
+ await this.window(account, stream, middle + 1, end, signal);
452
+ return;
453
+ }
454
+ signal.throwIfAborted();
455
+ await this.ingest(account, stream, rows, end);
456
+ }
457
+ async ingest(account, stream, events, cursor) {
458
+ account = account.toLowerCase();
459
+ let notifiedAgents = [];
460
+ const changed = await this.db.transaction(async (tx) => {
461
+ await tx.run("INSERT INTO hv_journal_accounts(account) VALUES (?) ON CONFLICT DO NOTHING", account);
462
+ const newFills = [];
463
+ let changed = false;
464
+ for (const event of events) {
465
+ const data = JSON.stringify(event);
466
+ const previous = await tx.get("SELECT data FROM hv_journal_entries WHERE account=? AND id=?", account, event.id);
467
+ if (previous?.data === data)
468
+ continue;
469
+ changed = true;
470
+ await tx.run(`INSERT INTO hv_journal_entries(account,id,kind,time,data) VALUES (?,?,?,?,?)
471
+ ON CONFLICT(account,id) DO UPDATE SET data=excluded.data,time=excluded.time`, account, event.id, event.kind, event.time, data);
472
+ if (!previous && event.kind === "fill") {
473
+ newFills.push(event);
474
+ await enqueueAccountEvent(tx, account, `fill:${event.id}`, "fill", `Exchange fill ${event.id}: ${JSON.stringify({ instrument: event.symbol, time: event.time, fill: event.fill })}. Refresh account and orders, inspect actual position size and TP/SL coverage. A fill is evidence, not a new-entry instruction.`, event.time);
475
+ }
476
+ }
477
+ notifiedAgents = await this.notifications?.fillsTx(tx, account, newFills) ?? [];
478
+ if (changed)
479
+ await tx.run("UPDATE hv_journal_accounts SET revision=revision+1 WHERE account=?", account);
480
+ // Pushed events never advance cursors; only fetched windows checkpoint progress.
481
+ if (cursor !== undefined)
482
+ await tx.run(`INSERT INTO hv_journal_sync(account,stream,cursor) VALUES (?,?,?)
483
+ ON CONFLICT(account,stream) DO UPDATE SET cursor=max(cursor,excluded.cursor)`, account, stream, cursor);
484
+ return changed;
485
+ });
486
+ if (changed)
487
+ this.balanceChanged(account);
488
+ for (const agentId of notifiedAgents)
489
+ this.notifications?.changed(agentId);
490
+ return changed;
491
+ }
492
+ async project(account) {
493
+ account = account.toLowerCase();
494
+ const snapshot = await this.db.transaction(async (tx) => {
495
+ const state = await tx.get("SELECT revision,projected_revision FROM hv_journal_accounts WHERE account=?", account);
496
+ if (!state || state.revision === state.projected_revision)
497
+ return null;
498
+ return { revision: state.revision, rows: await tx.all("SELECT id,kind,time,data,balance FROM hv_journal_entries WHERE account=? AND kind<>'trade' ORDER BY time,id", account) };
499
+ });
500
+ if (!snapshot)
501
+ return;
502
+ const events = snapshot.rows.map((row) => JSON.parse(row.data));
503
+ const trades = buildTrades(account, events);
504
+ let balance = amount("0");
505
+ const balances = events.map((event) => {
506
+ balance = balance === null || event.delta === null ? null : balance.add(amount(event.delta));
507
+ return { id: event.id, balance: balance?.toString() ?? null };
508
+ });
509
+ const committed = await this.db.transaction(async (tx) => {
510
+ const current = await tx.get("SELECT revision,projected_revision FROM hv_journal_accounts WHERE account=?", account);
511
+ if (current?.revision !== snapshot.revision || current.projected_revision === snapshot.revision)
512
+ return false; // Leave durable dirty revision for retry.
513
+ await tx.run("UPDATE hv_journal_entries SET active=0 WHERE account=? AND kind='trade'", account);
514
+ for (const trade of trades)
515
+ await tx.run(`INSERT INTO hv_journal_entries(account,id,kind,time,data) VALUES (?,?,'trade',?,?)
516
+ ON CONFLICT(account,id) DO UPDATE SET time=excluded.time,data=excluded.data,active=1`, account, trade.id, trade.lastActivityAt, JSON.stringify(trade));
517
+ for (const row of balances)
518
+ await tx.run("UPDATE hv_journal_entries SET balance=? WHERE account=? AND id=?", row.balance, account, row.id);
519
+ await tx.run("UPDATE hv_journal_accounts SET projected_revision=? WHERE account=?", snapshot.revision, account);
520
+ return true;
521
+ });
522
+ if (committed)
523
+ this.balanceChanged(account);
524
+ }
525
+ /** Realized USDC balance, including transfers, fees and funding; not equity.
526
+ * Carry the preceding balance into each window and sample hourly/daily closes. */
527
+ async balanceHistory(account, now = Date.now()) {
528
+ return (await this.readBalanceHistory(account.toLowerCase(), now)).history;
529
+ }
530
+ async readBalanceHistory(account, now) {
531
+ return this.db.transaction(async (tx) => {
532
+ const state = await tx.get("SELECT revision,projected_revision,history_limited FROM hv_journal_accounts WHERE account=?", account);
533
+ const sync = await tx.all("SELECT updated_at,error FROM hv_journal_sync WHERE account=?", account);
534
+ if (!state || state.revision !== state.projected_revision || state.history_limited || sync.length !== 3 || sync.some((s) => s.updated_at === null || s.error))
535
+ return { history: null, nextChange: null };
536
+ const start = now - 30 * 86_400_000;
537
+ const previous = await tx.get("SELECT balance FROM hv_journal_entries WHERE account=? AND kind<>'trade' AND time<=? ORDER BY time DESC,id DESC LIMIT 1", account, start);
538
+ const rows = await tx.all("SELECT time,balance FROM hv_journal_entries WHERE account=? AND kind<>'trade' AND time>? AND time<=? ORDER BY time,id", account, start, now);
539
+ if (previous?.balance === null || rows.some((row) => row.balance === null))
540
+ return { history: null, nextChange: null };
541
+ const sample = (duration, bucket) => {
542
+ let balance = previous?.balance ?? "0";
543
+ let index = 0;
544
+ const points = [];
545
+ for (let time = now - duration; time <= now; time += bucket) {
546
+ while (index < rows.length && rows[index].time <= time)
547
+ balance = rows[index++].balance;
548
+ points.push({ time, balance });
549
+ }
550
+ return points;
551
+ };
552
+ // A moving sample changes when it crosses an event timestamp. Include
553
+ // every sample (including both baselines), not just hour/day boundaries.
554
+ let nextChange = null;
555
+ for (const row of rows) {
556
+ for (const [bucket, count] of [[3_600_000, 24], [86_400_000, 30]]) {
557
+ const step = Math.floor((now - row.time) / bucket) + 1;
558
+ if (step <= count) {
559
+ const next = row.time + step * bucket;
560
+ if (nextChange === null || next < nextChange)
561
+ nextChange = next;
562
+ }
563
+ }
564
+ }
565
+ return { history: { day: sample(86_400_000, 3_600_000), month: sample(30 * 86_400_000, 86_400_000) }, nextChange };
566
+ });
567
+ }
568
+ async page(account, view, requestedPage) {
569
+ const empty = { linked: account !== null, view, page: 1, pages: 1, total: 0, trades: [], activity: [], sync: [], pending: true, historyLimited: false };
570
+ if (!account)
571
+ return { ...empty, pending: false };
572
+ account = account.toLowerCase();
573
+ return this.db.transaction(async (tx) => {
574
+ const filter = view === "trades" ? "kind='trade' AND active=1" : "kind<>'trade'";
575
+ const count = await tx.get(`SELECT count(*) AS total FROM hv_journal_entries WHERE account=? AND ${filter}`, account);
576
+ const total = count?.total ?? 0;
577
+ const pages = Math.max(1, Math.ceil(total / 25));
578
+ const page = Math.max(1, Math.min(pages, requestedPage));
579
+ const rows = await tx.all(`SELECT e.*, (SELECT count(*) FROM hv_journal_notes n WHERE n.account=e.account AND n.target=e.id) AS noteCount
580
+ FROM hv_journal_entries e WHERE account=? AND ${filter} ORDER BY time DESC,id DESC LIMIT 25 OFFSET ?`, account, (page - 1) * 25);
581
+ const sync = await tx.all("SELECT stream,cursor,updated_at,error FROM hv_journal_sync WHERE account=? ORDER BY stream", account);
582
+ const state = await tx.get("SELECT revision,projected_revision,history_limited FROM hv_journal_accounts WHERE account=?", account);
583
+ const result = { ...empty, page, pages, total, sync, pending: !state || state.revision !== state.projected_revision, historyLimited: state?.history_limited === 1 };
584
+ if (view === "trades")
585
+ result.trades = rows.map((row) => ({ ...JSON.parse(row.data), noteCount: row.noteCount }));
586
+ else
587
+ result.activity = rows.map((row) => {
588
+ const { raw, ...event } = JSON.parse(row.data);
589
+ void raw; // Exchange payloads stay local; only normalized fields cross the UI boundary.
590
+ return { ...event, balance: row.balance, noteCount: row.noteCount };
591
+ });
592
+ // Funding may be numerically zero but is not authoritative until its stream
593
+ // has finished backfill. Avoid reporting a partial import as final net P&L.
594
+ if (sync.length < 3 || sync.some((s) => !s.updated_at || s.error) || result.pending) {
595
+ result.trades = result.trades.map((trade) => ({ ...trade, funding: null, net: null }));
596
+ result.activity = result.activity.map((event) => ({ ...event, balance: null }));
597
+ }
598
+ if (result.historyLimited)
599
+ result.activity = result.activity.map((event) => ({ ...event, balance: null }));
600
+ return result;
601
+ });
602
+ }
603
+ /** Raw fills, not reconstructed trade segments (a position flip is one fill).
604
+ * Reads ingested journal evidence only; never initiates exchange requests. */
605
+ async chartFills(account, coin, range) {
606
+ const { from, to, cursor } = chartFillRange({ ...range });
607
+ account = account.toLowerCase();
608
+ return this.db.transaction(async (tx) => {
609
+ const rows = await tx.all(`SELECT id,time,
610
+ json_extract(data,'$.fill.side') AS side, json_extract(data,'$.fill.size') AS size,
611
+ json_extract(data,'$.fill.price') AS price FROM hv_journal_entries
612
+ WHERE account=? AND kind='fill' AND time>=? AND time<? AND json_extract(data,'$.symbol')=?
613
+ AND json_extract(data,'$.fill.side') IN ('B','A','buy','sell')
614
+ AND (? IS NULL OR time<? OR (time=? AND id<?))
615
+ ORDER BY time DESC,id DESC LIMIT 501`, account, from, to, coin, cursor?.time ?? null, cursor?.time ?? null, cursor?.time ?? null, cursor?.id ?? null);
616
+ const state = await tx.get("SELECT history_limited FROM hv_journal_accounts WHERE account=?", account);
617
+ const sync = await tx.get("SELECT updated_at AS updatedAt,error FROM hv_journal_sync WHERE account=? AND stream='fill'", account);
618
+ const page = rows.slice(0, 500), last = page.at(-1);
619
+ return {
620
+ fills: page.map((row) => ({ ...row, side: row.side === "B" || row.side === "buy" ? "Buy" : "Sell" })),
621
+ nextCursor: rows.length > 500 && last ? { time: last.time, id: last.id } : null,
622
+ historyLimited: state?.history_limited === 1,
623
+ sync: sync ?? null,
624
+ };
625
+ });
626
+ }
627
+ async notes(account, target) {
628
+ account = account.toLowerCase();
629
+ const found = await this.db.get("SELECT id FROM hv_journal_entries WHERE account=? AND id=?", account, target);
630
+ if (!found)
631
+ throw new HyperliquidError("Journal entry not found", 404);
632
+ return this.db.all("SELECT id,body,author_id AS authorId,created_at AS createdAt FROM hv_journal_notes WHERE account=? AND target=? ORDER BY created_at,id", account, target);
633
+ }
634
+ async addNote(account, target, authorId, body) {
635
+ account = account.toLowerCase();
636
+ body = body.trim();
637
+ if (!body || body.length > 4000)
638
+ throw new HyperliquidError("Notes must contain 1–4000 characters.");
639
+ await this.db.transaction(async (tx) => {
640
+ const found = await tx.get("SELECT id FROM hv_journal_entries WHERE account=? AND id=?", account, target);
641
+ if (!found)
642
+ throw new HyperliquidError("Journal entry not found", 404);
643
+ await tx.run("INSERT INTO hv_journal_notes(id,account,target,author_id,body,created_at) VALUES (?,?,?,?,?,?)", randomUUID(), account, target, authorId, body, Date.now());
644
+ });
645
+ }
646
+ }
647
+ class HistoryCoverageError extends Error {
648
+ }