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,137 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { and, desc, eq } from "drizzle-orm";
3
+ import { bodyHash, canonical } from "../canonical.js";
4
+ import { hvIndicators, hvIndicatorOperations, hvIndicatorVersions } from "../db/indicator-schema.js";
5
+ import { applicationDatabase } from "../db/shared-database.js";
6
+ import { indicatorEngine, indicatorLimits, indicatorWrapperVersion } from "./contracts.js";
7
+ import { IndicatorError, parseIndicatorId, validateSource } from "./validation.js";
8
+ export function indicatorPage(offset = 0, limit = indicatorLimits.listLimit) {
9
+ if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > indicatorLimits.maxListLimit)
10
+ throw new IndicatorError("Invalid indicator page");
11
+ return { offset, limit };
12
+ }
13
+ function validateSave(request) {
14
+ for (const [value, max, field] of [[request.name, 100, "name"], [request.description, 2000, "description"], [request.interpretation, 8000, "interpretation"]]) {
15
+ if (typeof value !== "string" || value.length > max || (field === "name" && !value.trim()))
16
+ throw new IndicatorError(`Invalid indicator ${field}`);
17
+ }
18
+ validateSource(request.source);
19
+ if (request.indicatorId) {
20
+ if (parseIndicatorId(request.indicatorId).kind !== "custom")
21
+ throw new IndicatorError("Built-in indicators are read-only");
22
+ if (!Number.isSafeInteger(request.expectedVersion) || request.expectedVersion < 1)
23
+ throw new IndicatorError("expectedVersion is required on updates");
24
+ }
25
+ else if (request.expectedVersion !== undefined)
26
+ throw new IndicatorError("New indicators cannot specify expectedVersion");
27
+ }
28
+ /** Application-owned immutable source history. Network/VM validation occurs outside the short SQL transaction. */
29
+ export class IndicatorStore {
30
+ database;
31
+ db;
32
+ constructor(database) {
33
+ this.database = database;
34
+ this.db = applicationDatabase(database);
35
+ }
36
+ async agentTx(tx, agentId) {
37
+ const agent = await tx.get("SELECT state FROM hv_agents WHERE id=?", agentId);
38
+ if (!agent)
39
+ throw new IndicatorError("Agent not found", 404);
40
+ if (agent.state === "stopping" || agent.state === "stopped")
41
+ throw new IndicatorError("Agent is being deleted", 409);
42
+ }
43
+ async assertAgent(agentId) { await this.agentTx(this.database, agentId); }
44
+ async list(agentId) {
45
+ await this.assertAgent(agentId);
46
+ // A hard 100-definition quota bounds this metadata-only merge with the static catalog.
47
+ const definitions = await this.db.select().from(hvIndicators).where(eq(hvIndicators.agentId, agentId)).orderBy(desc(hvIndicators.updatedAt)).all();
48
+ return Promise.all(definitions.map((definition) => this.get(agentId, `custom:${definition.id}`).then((entry) => entry.descriptor)));
49
+ }
50
+ async get(agentId, id, version) {
51
+ const parsed = parseIndicatorId(id);
52
+ if (parsed.kind !== "custom")
53
+ throw new IndicatorError("Not a custom indicator");
54
+ if (version !== undefined && (!Number.isSafeInteger(version) || version < 1))
55
+ throw new IndicatorError("Invalid indicator version");
56
+ await this.assertAgent(agentId);
57
+ const definition = await this.db.select().from(hvIndicators).where(and(eq(hvIndicators.id, parsed.uuid), eq(hvIndicators.agentId, agentId))).get();
58
+ if (!definition)
59
+ throw new IndicatorError("Indicator not found", 404);
60
+ const saved = await this.db.select().from(hvIndicatorVersions).where(and(eq(hvIndicatorVersions.indicatorId, definition.id), eq(hvIndicatorVersions.version, version ?? definition.currentVersion))).get();
61
+ if (!saved)
62
+ throw new IndicatorError("Indicator version not found", 404);
63
+ const metadata = JSON.parse(saved.metadata);
64
+ return { source: saved.source, createdAt: saved.createdAt, descriptor: { id: `custom:${definition.id}`, builtIn: false, name: definition.name, description: definition.description, interpretation: definition.interpretation,
65
+ version: saved.version, sourceHash: saved.sourceHash, inputs: metadata.inputs, overlay: metadata.overlay } };
66
+ }
67
+ async versions(agentId, id, options = {}) {
68
+ await this.get(agentId, id);
69
+ const parsed = parseIndicatorId(id);
70
+ if (parsed.kind !== "custom")
71
+ throw new IndicatorError("Not a custom indicator");
72
+ const { offset, limit } = indicatorPage(options.offset, options.limit);
73
+ const rows = await this.db.select({ version: hvIndicatorVersions.version, sourceHash: hvIndicatorVersions.sourceHash, createdAt: hvIndicatorVersions.createdAt, actorKind: hvIndicatorVersions.actorKind }).from(hvIndicatorVersions)
74
+ .where(eq(hvIndicatorVersions.indicatorId, parsed.uuid)).orderBy(desc(hvIndicatorVersions.version)).offset(offset).limit(limit + 1).all();
75
+ return { versions: rows.slice(0, limit), nextOffset: rows.length > limit ? offset + limit : null };
76
+ }
77
+ async save(agentId, request, operationKey, actor, validate, signal, engineVersion = indicatorEngine.version) {
78
+ validateSave(request);
79
+ if (!operationKey || operationKey.length > 200)
80
+ throw new IndicatorError("Invalid indicator operation key");
81
+ await this.assertAgent(agentId);
82
+ const hash = bodyHash(canonical(request));
83
+ const replay = async () => {
84
+ const receipt = await this.db.select().from(hvIndicatorOperations).where(and(eq(hvIndicatorOperations.agentId, agentId), eq(hvIndicatorOperations.key, operationKey))).get();
85
+ if (!receipt)
86
+ return undefined;
87
+ if (receipt.hash !== hash)
88
+ throw new IndicatorError("Operation key was used with different content", 409);
89
+ return JSON.parse(receipt.result);
90
+ };
91
+ const previousReceipt = await replay();
92
+ if (previousReceipt)
93
+ return previousReceipt;
94
+ const previous = request.indicatorId ? await this.get(agentId, request.indicatorId) : undefined;
95
+ if (previous && request.expectedVersion !== previous.descriptor.version)
96
+ throw new IndicatorError("Indicator changed; reread before saving", 409);
97
+ const sourceChanged = !previous || previous.source !== request.source;
98
+ if (sourceChanged && !request.validation)
99
+ throw new IndicatorError("A real closed-candle validation window is required for source changes");
100
+ signal?.throwIfAborted();
101
+ const metadata = sourceChanged ? await validate() : { inputs: previous.descriptor.inputs, overlay: previous.descriptor.overlay };
102
+ signal?.throwIfAborted();
103
+ const uuid = previous ? parseIndicatorId(previous.descriptor.id) : undefined;
104
+ const id = uuid?.kind === "custom" ? uuid.uuid : randomUUID();
105
+ const sourceHash = bodyHash(request.source), now = Date.now();
106
+ return this.database.appTransaction(async (db, tx) => {
107
+ signal?.throwIfAborted();
108
+ await this.agentTx(tx, agentId);
109
+ const receipt = await db.select().from(hvIndicatorOperations).where(and(eq(hvIndicatorOperations.agentId, agentId), eq(hvIndicatorOperations.key, operationKey))).get();
110
+ if (receipt) {
111
+ if (receipt.hash !== hash)
112
+ throw new IndicatorError("Operation key was used with different content", 409);
113
+ return JSON.parse(receipt.result);
114
+ }
115
+ const current = await db.select().from(hvIndicators).where(and(eq(hvIndicators.id, id), eq(hvIndicators.agentId, agentId))).get();
116
+ if (previous && (!current || current.currentVersion !== request.expectedVersion))
117
+ throw new IndicatorError("Indicator changed; reread before saving", 409);
118
+ const version = current ? current.currentVersion + (sourceChanged ? 1 : 0) : 1;
119
+ if (version > indicatorLimits.versions)
120
+ throw new IndicatorError("Indicator source-version limit (200) reached", 409);
121
+ if (!current) {
122
+ const quota = await tx.get("SELECT count(*) AS count FROM hv_indicators WHERE agent_id=?", agentId);
123
+ if ((quota?.count ?? 0) >= indicatorLimits.customPerAgent)
124
+ throw new IndicatorError("Custom indicator limit (100) reached", 409);
125
+ await db.insert(hvIndicators).values({ id, agentId, name: request.name, description: request.description, interpretation: request.interpretation, currentVersion: version, createdAt: now, updatedAt: now }).run();
126
+ }
127
+ else
128
+ await db.update(hvIndicators).set({ name: request.name, description: request.description, interpretation: request.interpretation, currentVersion: version, updatedAt: now }).where(eq(hvIndicators.id, id)).run();
129
+ if (sourceChanged)
130
+ await db.insert(hvIndicatorVersions).values({ indicatorId: id, version, source: request.source, sourceHash, metadata: JSON.stringify(metadata), engineVersion, wrapperVersion: indicatorWrapperVersion,
131
+ createdAt: now, actorKind: actor.kind, userId: actor.userId, subagentId: actor.subagentId, runId: actor.runId, conversationId: actor.conversationId, taskId: actor.taskId }).run();
132
+ const result = { indicatorId: `custom:${id}`, version, sourceHash };
133
+ await db.insert(hvIndicatorOperations).values({ agentId, key: operationKey, hash, result: JSON.stringify(result) }).run();
134
+ return result;
135
+ });
136
+ }
137
+ }
@@ -0,0 +1,149 @@
1
+ /** Self-contained trusted function, serialized into QuickJS. No host capabilities or module captures. */
2
+ export function normalizePineContext(raw, args) {
3
+ const row = (value) => {
4
+ if (!value || typeof value !== "object" || Array.isArray(value))
5
+ throw new Error("Malformed PineTS output object");
6
+ return value;
7
+ };
8
+ const array = (value) => { if (!Array.isArray(value))
9
+ throw new Error("Malformed PineTS output collection"); return value; };
10
+ const num = (value) => { if (typeof value !== "number" || !Number.isFinite(value))
11
+ throw new Error("Non-finite PineTS coordinate/value"); return value; };
12
+ const integer = (value) => { const n = num(value); if (!Number.isSafeInteger(n))
13
+ throw new Error("Invalid PineTS integer"); return n; };
14
+ const text = (value, fallback = "") => { if (value === undefined || value === null)
15
+ return fallback; if (typeof value !== "string")
16
+ throw new Error("Invalid PineTS text"); return value; };
17
+ const optionalText = (value) => value === undefined || value === null ? undefined : text(value);
18
+ const numberOrNull = (value) => value === null || value === undefined || (typeof value === "number" && Number.isNaN(value)) ? null : num(value);
19
+ const context = row(raw), declaration = row(context.indicator), plots = row(context.plots);
20
+ const overlay = declaration.overlay === true;
21
+ const outputs = [], levels = [], fills = [], markers = [], drawings = [];
22
+ const times = new Set(args.candles.map((c) => c.openTime / 1000));
23
+ const timeIndexes = new Map(args.candles.map((c, index) => [c.openTime / 1000, index]));
24
+ const time = (value) => { const t = num(value) / 1000; if (!times.has(t))
25
+ throw new Error("Plot time is outside the input candles"); return t; };
26
+ const pane = (options) => ({ overlay: options.overlay === true || (options.overlay === undefined && overlay), forceOverlay: options.force_overlay === true });
27
+ const style = (options) => ({
28
+ color: optionalText(options.color), width: options.linewidth === undefined ? undefined : num(options.linewidth),
29
+ lineStyle: optionalText(options.linestyle), hidden: options.display === 0 || options.display === "none",
30
+ offset: options.offset === undefined ? 0 : integer(options.offset), showLast: options.show_last === undefined ? undefined : integer(options.show_last),
31
+ });
32
+ const anchor = (x, y, xloc) => {
33
+ const price = num(y);
34
+ if (xloc === "bt" || xloc === "bar_time")
35
+ return { time: num(x) / 1000, price };
36
+ if (xloc !== "bi" && xloc !== "bar_index" && xloc !== undefined)
37
+ throw new Error(`Unsupported drawing xloc: ${String(xloc)}`);
38
+ const barIndex = integer(x), candle = args.candles[barIndex];
39
+ const first = args.candles[0];
40
+ if (!first)
41
+ throw new Error("Drawing requires input candles");
42
+ return { time: (candle?.openTime ?? first.openTime + barIndex * args.intervalMs) / 1000, price, barIndex };
43
+ };
44
+ const extension = (value) => {
45
+ if (value === "r" || value === "right")
46
+ return "right";
47
+ if (value === "l" || value === "left")
48
+ return "left";
49
+ if (value === "b" || value === "both")
50
+ return "both";
51
+ if (value === undefined || value === "n" || value === "none")
52
+ return "none";
53
+ throw new Error(`Unsupported drawing extension: ${String(value)}`);
54
+ };
55
+ let markerOutputs = 0;
56
+ for (const [id, rawPlot] of Object.entries(plots)) {
57
+ if (["__proto__", "constructor", "prototype"].includes(id))
58
+ throw new Error("Unsafe PineTS plot ID");
59
+ const plot = row(rawPlot), data = array(plot.data), options = row(plot.options ?? {});
60
+ if (!id.startsWith("__") && data.length > args.limits.candles)
61
+ throw new Error("Output point limit exceeded");
62
+ if (id.startsWith("__")) {
63
+ const objects = data.flatMap((point) => array(row(point).value));
64
+ const live = objects.map(row).filter((object) => object._deleted !== true);
65
+ if (!["__lines__", "__boxes__", "__labels__"].includes(id)) {
66
+ if (live.length)
67
+ throw new Error(`Unsupported nonempty PineTS output: ${id}`);
68
+ continue;
69
+ }
70
+ for (const object of live) {
71
+ if (drawings.length >= args.limits.drawings)
72
+ throw new Error("Generated drawing limit exceeded");
73
+ const base = { id: `${id}:${String(object.id)}`, ...pane({ ...options, force_overlay: object.force_overlay }),
74
+ color: optionalText(object.color ?? object.border_color), width: object.width === undefined && object.border_width === undefined ? undefined : num(object.width ?? object.border_width),
75
+ lineStyle: optionalText(object.style ?? object.border_style), extend: extension(object.extend) };
76
+ if (id === "__lines__")
77
+ drawings.push({ ...base, kind: "line", from: anchor(object.x1, object.y1, object.xloc), to: anchor(object.x2, object.y2, object.xloc) });
78
+ else if (id === "__boxes__")
79
+ drawings.push({ ...base, kind: "box", from: anchor(object.left, object.top, object.xloc), to: anchor(object.right, object.bottom, object.xloc), background: optionalText(object.bgcolor), text: text(object.text), textColor: optionalText(object.text_color), size: optionalText(object.text_size) });
80
+ else
81
+ drawings.push({ ...base, kind: "label", at: anchor(object.x, object.y, object.xloc), text: text(object.text), textColor: optionalText(object.textcolor), size: optionalText(object.size), shape: optionalText(object.style), location: text(object.yloc, "pr") });
82
+ }
83
+ continue;
84
+ }
85
+ const title = text(plot.title, id), kind = text(options.style, "style_line"), settings = style(options);
86
+ const visible = (t) => !settings.hidden && (settings.showLast === undefined || timeIndexes.get(t) >= args.candles.length - settings.showLast);
87
+ if (kind === "fill") {
88
+ fills.push({ id, title, from: text(plot.plot1 ?? options.plot1), to: text(plot.plot2 ?? options.plot2), color: optionalText(options.color), hidden: settings.hidden,
89
+ points: data.flatMap((item) => { const p = row(item), opts = row(p.options ?? {}), t = time(p.time); return visible(t) ? [{ time: t, color: optionalText(opts.color ?? options.color) }] : []; }) });
90
+ continue;
91
+ }
92
+ if (kind === "hline") {
93
+ const values = data.map((p) => numberOrNull(row(p).value)).filter((v) => v !== null);
94
+ if (values.length && values.some((v) => v !== values[0]))
95
+ throw new Error("Horizontal level changed within calculation");
96
+ if (values.length)
97
+ levels.push({ id, title, value: values[0], ...pane(options), style: settings });
98
+ continue;
99
+ }
100
+ if (["shape", "char", "arrow"].includes(kind)) {
101
+ if (++markerOutputs > args.limits.markerOutputs)
102
+ throw new Error("Marker output limit exceeded");
103
+ const markerKind = text(plot._callsiteId).startsWith("plotarrow") || kind === "arrow" ? "arrow" : kind === "char" ? "char" : "shape";
104
+ for (const [index, item] of data.entries()) {
105
+ const p = row(item), opts = { ...options, ...row(p.options ?? {}) }, value = p.value;
106
+ if (value === null || value === undefined || value === false || value === 0 || (typeof value === "number" && Number.isNaN(value)))
107
+ continue;
108
+ if (typeof value !== "boolean")
109
+ num(value);
110
+ const pointSettings = style(opts), sourceTime = time(p.time);
111
+ if (!visible(sourceTime) || pointSettings.hidden)
112
+ continue;
113
+ if (markers.length >= args.limits.markerEvents)
114
+ throw new Error("Marker event limit exceeded");
115
+ markers.push({ id: `${id}:${index}`, outputId: id, kind: markerKind, time: sourceTime,
116
+ displayTime: sourceTime + pointSettings.offset * args.intervalMs / 1000, offset: pointSettings.offset,
117
+ value: value, ...pane(opts), location: text(opts.location, "AboveBar"), shape: optionalText(opts.shape),
118
+ text: optionalText(opts.text), character: optionalText(opts.char), color: optionalText(opts.color), textColor: optionalText(opts.textcolor), size: optionalText(opts.size) });
119
+ }
120
+ continue;
121
+ }
122
+ if (!["style_line", "style_linebr", "style_histogram", "style_columns"].includes(kind)) {
123
+ if (data.some((p) => { const v = row(p).value; return v !== null && v !== undefined && !(typeof v === "number" && Number.isNaN(v)); }))
124
+ throw new Error(`Unsupported nonempty PineTS output style: ${kind}`);
125
+ continue;
126
+ }
127
+ if (outputs.length >= args.limits.numericOutputs)
128
+ throw new Error("Numeric output limit exceeded");
129
+ const points = data.map((item) => {
130
+ const p = row(item), opts = { ...options, ...row(p.options ?? {}) }, t = time(p.time);
131
+ return { time: t, displayTime: t + style(opts).offset * args.intervalMs / 1000, value: numberOrNull(p.value), color: optionalText(opts.color) };
132
+ });
133
+ const finite = points.filter((p) => p.value !== null);
134
+ outputs.push({ id, title, kind: kind === "style_histogram" ? "histogram" : kind === "style_columns" ? "columns" : "line", ...pane(options), style: settings,
135
+ finiteCount: finite.length, firstFiniteTime: finite[0]?.time ?? null,
136
+ points: points.map((p) => ({ ...p, ...(visible(p.time) ? {} : { color: "#00000000" }) })) });
137
+ }
138
+ if (outputs.length + levels.length > args.limits.numericOutputs)
139
+ throw new Error("Numeric output limit exceeded");
140
+ for (const fill of fills)
141
+ if (![outputs, levels].flat().some((p) => p.id === fill.from) || ![outputs, levels].flat().some((p) => p.id === fill.to))
142
+ throw new Error("Fill references an unsupported output");
143
+ markers.sort((a, b) => a.time - b.time || a.outputId.localeCompare(b.outputId) || a.id.localeCompare(b.id));
144
+ const byTime = new Map(outputs.map((output) => [output.id, new Map(output.points.map((p) => [p.time, p.value]))]));
145
+ const values = args.candles.map((c) => ({ time: c.openTime / 1000, value: Object.fromEntries(outputs.map((o) => [o.id, byTime.get(o.id)?.get(c.openTime / 1000) ?? null])) }));
146
+ const warnings = array(context.warnings ?? []).map((w) => typeof w === "string" ? w : JSON.stringify(w));
147
+ return { title: text(declaration.title), overlay, outputs, levels, fills, markers, drawings, values,
148
+ warnings: warnings.slice(0, args.limits.warnings), warningsOmitted: Math.max(0, warnings.length - args.limits.warnings) };
149
+ }
@@ -0,0 +1,79 @@
1
+ import { Type, validateToolArguments } from "@earendil-works/pi-ai";
2
+ import { indicatorLimits } from "./contracts.js";
3
+ import { resolveInputs } from "./validation.js";
4
+ import { ArtifactMetaSchema } from "../research/contracts.js";
5
+ const object = { additionalProperties: false };
6
+ const str = Type.String();
7
+ const num = Type.Number();
8
+ const epochSeconds = Type.Number({ description: "Unix epoch seconds (UTC)" });
9
+ const nullableEpochSeconds = Type.Union([epochSeconds, Type.Null()]);
10
+ const epochMilliseconds = Type.Number({ description: "Unix epoch milliseconds (UTC)" });
11
+ const optStr = Type.Optional(str);
12
+ const optNum = Type.Optional(num);
13
+ const scalar = Type.Union([num, str, Type.Boolean()]);
14
+ const nullable = Type.Union([num, Type.Null()]);
15
+ const pane = { overlay: Type.Boolean(), forceOverlay: Type.Boolean() };
16
+ const anchor = Type.Object({ time: epochSeconds, price: num, barIndex: Type.Optional(Type.Integer()) }, object);
17
+ const style = Type.Object({ color: optStr, width: optNum, lineStyle: optStr, hidden: Type.Boolean(), offset: Type.Integer(), showLast: Type.Optional(Type.Integer({ minimum: 0 })) }, object);
18
+ const drawing = { id: str, ...pane, color: optStr, width: optNum, lineStyle: optStr, extend: Type.Union([Type.Literal("none"), Type.Literal("left"), Type.Literal("right"), Type.Literal("both")]) };
19
+ export const NormalizedIndicatorSchema = Type.Object({
20
+ title: str, overlay: Type.Boolean(),
21
+ inputs: Type.Array(Type.Object({ key: str, runtimeId: str, variable: optStr, title: str,
22
+ type: Type.Union(["int", "float", "bool", "string", "source", "color"].map((v) => Type.Literal(v))),
23
+ default: scalar, min: optNum, max: optNum, step: optNum, options: Type.Optional(Type.Array(scalar)), group: optStr, tooltip: optStr }, object), { maxItems: indicatorLimits.inputs }),
24
+ resolvedInputs: Type.Record(Type.String(), scalar),
25
+ outputs: Type.Array(Type.Object({ id: str, title: str, kind: Type.Union([Type.Literal("line"), Type.Literal("histogram"), Type.Literal("columns")]), ...pane, style,
26
+ finiteCount: Type.Integer({ minimum: 0 }), firstFiniteTime: nullableEpochSeconds,
27
+ points: Type.Array(Type.Object({ time: epochSeconds, displayTime: epochSeconds, value: nullable, color: optStr }, object), { maxItems: indicatorLimits.candles }) }, object), { maxItems: indicatorLimits.numericOutputs }),
28
+ levels: Type.Array(Type.Object({ id: str, title: str, value: num, ...pane, style }, object), { maxItems: indicatorLimits.numericOutputs }),
29
+ fills: Type.Array(Type.Object({ id: str, title: str, from: str, to: str, color: optStr, hidden: Type.Boolean(), points: Type.Array(Type.Object({ time: epochSeconds, color: optStr }, object), { maxItems: indicatorLimits.candles }) }, object)),
30
+ markers: Type.Array(Type.Object({ id: str, outputId: str, kind: Type.Union([Type.Literal("shape"), Type.Literal("char"), Type.Literal("arrow")]), time: epochSeconds, displayTime: epochSeconds, value: Type.Union([num, Type.Boolean()]), offset: Type.Integer(), ...pane,
31
+ location: str, shape: optStr, text: optStr, character: optStr, color: optStr, textColor: optStr, size: optStr }, object), { maxItems: indicatorLimits.markerEvents }),
32
+ drawings: Type.Array(Type.Union([
33
+ Type.Object({ ...drawing, kind: Type.Literal("line"), from: anchor, to: anchor }, object),
34
+ Type.Object({ ...drawing, kind: Type.Literal("box"), from: anchor, to: anchor, background: optStr, text: str, textColor: optStr, size: optStr }, object),
35
+ Type.Object({ ...drawing, kind: Type.Literal("label"), at: anchor, text: str, textColor: optStr, size: optStr, shape: optStr, location: str }, object),
36
+ ]), { maxItems: indicatorLimits.drawings }),
37
+ values: Type.Array(Type.Object({ time: epochSeconds, value: Type.Record(Type.String(), nullable) }, object), { maxItems: indicatorLimits.candles }),
38
+ warnings: Type.Array(str, { maxItems: indicatorLimits.warnings }), warningsOmitted: Type.Integer({ minimum: 0 }),
39
+ }, object);
40
+ const bound = Type.Object({ count: Type.Integer(), firstOpenTime: epochSeconds, lastOpenTime: epochSeconds }, object);
41
+ const outputBound = Type.Object({ count: Type.Integer(), firstTime: nullableEpochSeconds, lastTime: nullableEpochSeconds }, object);
42
+ const coverage = Type.Object({ complete: Type.Boolean(), closedOnly: Type.Literal(true), expected: Type.Integer(), returned: Type.Integer(), seedCoverage: Type.Union([Type.Literal("complete"), Type.Literal("limited")]) }, object);
43
+ const provenance = { ...Type.Omit(NormalizedIndicatorSchema, ["outputs", "levels", "fills", "drawings", "values", "markers"]).properties,
44
+ schemaVersion: Type.Literal(1), indicatorId: str, builtIn: Type.Boolean(), version: Type.Integer(), sourceHash: str,
45
+ engine: Type.Object({ name: Type.Literal("pinets"), version: Type.String({ pattern: "^\\d+\\.\\d+\\.\\d+" }) }, object), wrapperVersion: Type.Integer(), coin: str, interval: str, start: epochMilliseconds, end: epochMilliseconds,
46
+ inputSchemaHash: str, computedAt: epochMilliseconds, candleHash: str, resultHash: str, dataset: bound, outputDataset: outputBound, coverage };
47
+ export const IndicatorToolResultSchema = Type.Union([
48
+ Type.Object({ ...provenance, outputs: Type.Array(Type.Omit(NormalizedIndicatorSchema.properties.outputs.items, ["points"])), levels: NormalizedIndicatorSchema.properties.levels, fillCount: Type.Integer(),
49
+ values: NormalizedIndicatorSchema.properties.values, numericalCoverage: Type.Object({ available: Type.Integer(), returned: Type.Integer() }, object),
50
+ markers: NormalizedIndicatorSchema.properties.markers, markerCoverage: Type.Object({ available: Type.Integer(), returned: Type.Integer(), firstSourceTime: nullableEpochSeconds, lastSourceTime: nullableEpochSeconds }, object),
51
+ drawings: Type.Object({ count: Type.Integer(), byKind: Type.Object({ line: Type.Integer(), box: Type.Integer(), label: Type.Integer() }, object) }, object) }, object),
52
+ Type.Object({ artifact: ArtifactMetaSchema, reference: str, summary: Type.Object({ ...provenance, exportScope: Type.Literal("full") }, object) }, object),
53
+ ]);
54
+ /** Revalidate untrusted VM transport, including finite numbers (JSON must not hide NaN/infinity). */
55
+ export function validateNormalizedIndicatorResult(value, limits = indicatorLimits) {
56
+ const visit = (item) => {
57
+ if (typeof item === "number" && !Number.isFinite(item))
58
+ throw new Error("Non-finite normalized result");
59
+ if (item && typeof item === "object")
60
+ for (const [key, child] of Object.entries(item)) {
61
+ if (["__proto__", "constructor", "prototype"].includes(key))
62
+ throw new Error("Unsafe normalized result key");
63
+ visit(child);
64
+ }
65
+ };
66
+ visit(value);
67
+ const json = JSON.stringify(value);
68
+ if (!json || Buffer.byteLength(json) > limits.resultBytes)
69
+ throw new Error("Normalized indicator result exceeds byte limit");
70
+ const tool = { name: "indicator_result", description: "Validate VM result", parameters: NormalizedIndicatorSchema };
71
+ const result = validateToolArguments(tool, { type: "toolCall", id: "result", name: tool.name, arguments: value });
72
+ if (result.inputs.length > limits.inputs || result.outputs.length + result.levels.length > limits.numericOutputs || result.markers.length > limits.markerEvents || result.drawings.length > limits.drawings || result.values.length > limits.candles || result.warnings.length > limits.warnings)
73
+ throw new Error("Normalized indicator result exceeds limits");
74
+ const ids = [...result.outputs, ...result.levels].map((output) => output.id);
75
+ if (new Set(ids).size !== ids.length || new Set(result.inputs.map((input) => input.key)).size !== result.inputs.length)
76
+ throw new Error("Duplicate normalized result identity");
77
+ resolveInputs(result.inputs, result.resolvedInputs);
78
+ return result;
79
+ }
@@ -0,0 +1,52 @@
1
+ /** Serialized, trusted VM entry. The parameters are supplied only by the trusted runtime. */
2
+ export async function runHyperVibesIndicator(args, lib, normalize, unknownInputsMessage) {
3
+ const program = new lib.Indicator(args.source);
4
+ if (program.getDeclarationType() !== "indicator")
5
+ throw new Error("Only indicator() programs are supported.");
6
+ const metadata = program.getInputsMeta();
7
+ if (metadata.length > args.limits.inputs)
8
+ throw new Error("Input declaration limit exceeded");
9
+ const safeKey = (key) => !["__proto__", "constructor", "prototype"].includes(key);
10
+ const scalar = (value) => typeof value === "string" || typeof value === "boolean" || (typeof value === "number" && Number.isFinite(value));
11
+ const counts = new Map();
12
+ for (const input of metadata)
13
+ if (input.varId)
14
+ counts.set(input.varId, (counts.get(input.varId) ?? 0) + 1);
15
+ const inputs = metadata.map((input) => {
16
+ if (!["int", "float", "bool", "string", "source", "color"].includes(input.type))
17
+ throw new Error(`Unsupported input widget: ${input.type}`);
18
+ const key = input.varId && counts.get(input.varId) === 1 ? input.varId : input.id;
19
+ if (!safeKey(key) || !safeKey(input.id) || !scalar(input.defval) || input.options?.some((value) => !scalar(value)))
20
+ throw new Error("Invalid indicator input metadata");
21
+ return { key, runtimeId: input.id, variable: input.varId, title: input.title ?? input.name,
22
+ type: input.type, default: input.defval, min: input.minval, max: input.maxval, step: input.step,
23
+ options: input.options, group: input.group, tooltip: input.tooltip };
24
+ });
25
+ if (new Set(inputs.map((input) => input.key)).size !== inputs.length)
26
+ throw new Error("Ambiguous indicator input keys");
27
+ const validKeys = inputs.map((input) => input.key);
28
+ const unknownKeys = Object.keys(args.inputs).filter((key) => !validKeys.includes(key));
29
+ if (unknownKeys.length)
30
+ throw new Error(unknownInputsMessage(unknownKeys, validKeys));
31
+ for (const [key, value] of Object.entries(args.inputs)) {
32
+ const binding = inputs.find((input) => input.key === key);
33
+ if (!safeKey(key) || !binding || !scalar(value))
34
+ throw new Error(`Unknown or invalid input: ${key}`);
35
+ program.input[binding.runtimeId] = value;
36
+ }
37
+ const resolvedInputs = Object.fromEntries(inputs.map((input) => [input.key, Object.hasOwn(args.inputs, input.key) ? args.inputs[input.key] : input.default]));
38
+ const pine = new lib.PineTS(args.candles, args.coin, args.pineTimeframe);
39
+ pine.setMaxLoops(args.limits.maxLoops);
40
+ const context = await pine.run(program);
41
+ const result = { ...normalize(context, args), inputs, resolvedInputs };
42
+ // QuickJS may not expose TextEncoder. Count UTF-8 bytes without host APIs or silent JSON coercion.
43
+ const json = JSON.stringify(result);
44
+ let bytes = 0;
45
+ for (const char of json) {
46
+ const code = char.codePointAt(0);
47
+ bytes += code < 0x80 ? 1 : code < 0x800 ? 2 : code < 0x10000 ? 3 : 4;
48
+ }
49
+ if (bytes > args.limits.resultBytes)
50
+ throw new Error("Normalized indicator result exceeds byte limit");
51
+ return result;
52
+ }
@@ -0,0 +1,201 @@
1
+ import { CodemodeSandbox } from "@earendil-works/pi-codemode";
2
+ import { readFile } from "node:fs/promises";
3
+ import { indicatorEngine, indicatorLimits } from "./contracts.js";
4
+ import { normalizePineContext } from "./normalize.js";
5
+ import { runHyperVibesIndicator } from "./runtime-wrapper.js";
6
+ import { validateNormalizedIndicatorResult } from "./result-schema.js";
7
+ import { IndicatorError, unknownIndicatorInputsMessage, validateInputs, validateSource } from "./validation.js";
8
+ import { IndicatorWorkerQueue } from "./worker-queue.js";
9
+ /** Startup drift message; null when the installed pin matches the validated pin. */
10
+ export function pineVersionDrift(installed, expected) {
11
+ return installed === expected ? null : `pinets@${installed} is installed, but this HyperVibes build was validated against pinets@${expected}. Indicators run on the installed engine and record that version in results and source history. Update indicatorEngine in src/indicators/contracts.ts and re-run pnpm test:server src/indicators when upgrading.`;
12
+ }
13
+ /** One application-owned no-capability execution owner; capacity lasts until actual worker exit. */
14
+ export class IndicatorRuntime {
15
+ reportVersionDrift;
16
+ limits;
17
+ bundle;
18
+ initializing;
19
+ stopping = false;
20
+ closing;
21
+ queue;
22
+ exits = new Map();
23
+ calls = new Set();
24
+ deleted = new Set();
25
+ engineInfo = indicatorEngine;
26
+ /** The engine version actually installed; recorded in results and source history. Available after initialize(). */
27
+ get engine() { return this.engineInfo; }
28
+ constructor(limits = {}, reportVersionDrift = () => { }) {
29
+ this.reportVersionDrift = reportVersionDrift;
30
+ this.limits = { ...indicatorLimits, ...limits };
31
+ for (const key of Object.keys(this.limits)) {
32
+ const value = this.limits[key];
33
+ if (!Number.isSafeInteger(value) || value < 1 || value > indicatorLimits[key])
34
+ throw new Error(`Invalid indicator budget: ${key}`);
35
+ }
36
+ this.queue = new IndicatorWorkerQueue(this.limits.workers, this.limits.queuedCalls);
37
+ }
38
+ initialize() {
39
+ if (this.stopping)
40
+ return Promise.reject(new IndicatorError("Indicator runtime is closed", 503));
41
+ return this.initializing ??= (async () => {
42
+ const entry = new URL(import.meta.resolve("pinets"));
43
+ const pkg = JSON.parse(await readFile(new URL("../package.json", entry), "utf8"));
44
+ // Structural failures stay fatal: the wrong/missing package or an unreadable
45
+ // version makes every result's provenance a lie. A mere version drift does
46
+ // not: execution continues on the installed engine and records its actual
47
+ // version, so a routine dependency bump can never brick startup.
48
+ if (pkg.name !== "pinets" || typeof pkg.version !== "string" || !/^\d+\.\d+\.\d+(-[\w.+-]+)?$/.test(pkg.version))
49
+ throw new Error("The installed pinets package is missing or unreadable; indicator execution is unavailable");
50
+ this.engineInfo = { name: "pinets", version: pkg.version };
51
+ if (pkg.version !== indicatorEngine.version) {
52
+ const drift = pineVersionDrift(pkg.version, indicatorEngine.version);
53
+ if (drift)
54
+ this.reportVersionDrift(drift);
55
+ }
56
+ const bundle = await readFile(new URL("pinets.min.browser.js", entry), "utf8");
57
+ if (!this.stopping)
58
+ this.bundle = bundle;
59
+ })();
60
+ }
61
+ admit(agentId) {
62
+ if (this.stopping || this.deleted.has(agentId))
63
+ throw new IndicatorError("Indicator execution is shutting down", 503, "indicator_closed");
64
+ }
65
+ async withWorker(agentId, signal, operation) {
66
+ const controller = new AbortController();
67
+ const combined = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
68
+ let settled;
69
+ const call = { agentId, controller, done: new Promise((resolve) => { settled = resolve; }) };
70
+ this.calls.add(call);
71
+ // Queueing and VM execution share one deadline. Keep workers observable until
72
+ // actual exit, including during startup before the host has a listening socket.
73
+ const timeout = new IndicatorError("Indicator execution timed out (including queue wait)", 408, "indicator_timeout");
74
+ const deadline = Date.now() + this.limits.timeoutMs;
75
+ const timer = setTimeout(() => controller.abort(timeout), this.limits.timeoutMs);
76
+ const keepAlive = setInterval(() => { }, 1000);
77
+ let release;
78
+ let started = false;
79
+ let finished = false;
80
+ let sandbox;
81
+ const check = () => {
82
+ if (Date.now() >= deadline)
83
+ controller.abort(timeout);
84
+ combined.throwIfAborted();
85
+ this.admit(agentId);
86
+ if (finished)
87
+ throw new IndicatorError("Indicator execution has already ended", 503, "indicator_closed");
88
+ };
89
+ try {
90
+ release = await this.queue.acquire(combined);
91
+ check();
92
+ sandbox = new CodemodeSandbox({ tools: [], globals: [], memoryLimitBytes: this.limits.memoryLimitBytes,
93
+ // WASM loading may finish after cancellation/result settlement. Never
94
+ // launch that stale worker after its reservation has been released.
95
+ acquireWorker: () => { check(); return () => { release?.(); clearInterval(keepAlive); }; },
96
+ onWorkerStarted: (exit) => { started = true; this.exits.set(exit, agentId); void exit.then(() => this.exits.delete(exit)); },
97
+ });
98
+ const result = await operation(sandbox, combined, Math.max(1, deadline - Date.now()));
99
+ check();
100
+ return result;
101
+ }
102
+ catch (error) {
103
+ if (combined.aborted)
104
+ throw combined.reason;
105
+ throw error;
106
+ }
107
+ finally {
108
+ finished = true;
109
+ clearTimeout(timer);
110
+ try {
111
+ await sandbox?.close();
112
+ }
113
+ finally {
114
+ if (!started) {
115
+ release?.();
116
+ clearInterval(keepAlive);
117
+ }
118
+ this.calls.delete(call);
119
+ settled();
120
+ }
121
+ }
122
+ }
123
+ prepare(request) {
124
+ validateSource(request.source, this.limits.sourceBytes);
125
+ const inputs = validateInputs(request.inputs);
126
+ if (!request.candles.length || request.candles.length > this.limits.candles)
127
+ throw new IndicatorError("Invalid indicator candle count");
128
+ if (!Number.isSafeInteger(request.intervalMs) || request.intervalMs <= 0)
129
+ throw new IndicatorError("Invalid indicator interval");
130
+ for (const [index, candle] of request.candles.entries()) {
131
+ if (!Object.values(candle).every((value) => typeof value === "number" && Number.isFinite(value)) || !Number.isSafeInteger(candle.openTime) || candle.closeTime !== candle.openTime + request.intervalMs
132
+ || candle.volume < 0 || candle.low > Math.min(candle.open, candle.close) || candle.high < Math.max(candle.open, candle.close)
133
+ || (index > 0 && request.candles[index - 1].closeTime !== candle.openTime))
134
+ throw new IndicatorError("Invalid or gapped indicator candles");
135
+ }
136
+ return { ...request, inputs, limits: this.limits };
137
+ }
138
+ async execute(agentId, request, signal) {
139
+ signal?.throwIfAborted();
140
+ this.admit(agentId);
141
+ if (!this.bundle)
142
+ throw new IndicatorError("Indicator runtime is not initialized", 503);
143
+ const payload = this.prepare(request);
144
+ return this.withWorker(agentId, signal, async (sandbox, combined, timeoutMs) => {
145
+ // tsx emits esbuild's __name helper inside function bodies. Bind that trusted
146
+ // compiler helper in the VM too; never capture a Node closure in serialized code.
147
+ const code = `${this.bundle}\nreturn await ((__name) => (${runHyperVibesIndicator.toString()})(${JSON.stringify(payload)}, PineTSLib, (${normalizePineContext.toString()}), (${unknownIndicatorInputsMessage.toString()})))((target, name) => Object.defineProperty(target, "name", { value: name, configurable: true }));`;
148
+ const result = await sandbox.execute(code, { signal: combined, timeoutMs });
149
+ if (!result.ok)
150
+ throw new IndicatorError(`PineTS ${result.error.kind}: ${result.error.message}`, result.error.kind === "aborted" ? 499 : 400, `indicator_${result.error.kind}`);
151
+ if (result.calls.length)
152
+ throw new IndicatorError("Indicator attempted a host tool call");
153
+ // storeWrites are deliberately discarded; indicator calculations have no persistent capabilities.
154
+ return validateNormalizedIndicatorResult(result.value, this.limits);
155
+ });
156
+ }
157
+ /** One worker for several trusted calculations (startup built-in validation): a
158
+ * single bundle parse and VM spawn instead of one per program. */
159
+ async executeBatch(agentId, requests, signal) {
160
+ signal?.throwIfAborted();
161
+ if (!requests.length || requests.length > 16)
162
+ throw new IndicatorError("Invalid indicator batch");
163
+ this.admit(agentId);
164
+ if (!this.bundle)
165
+ throw new IndicatorError("Indicator runtime is not initialized", 503);
166
+ const payloads = requests.map((request) => this.prepare(request));
167
+ return this.withWorker(agentId, signal, async (sandbox, combined, timeoutMs) => {
168
+ const code = `${this.bundle}\nreturn await ((__name) => (async () => { const results = []; for (const request of ${JSON.stringify(payloads)}) results.push(await (${runHyperVibesIndicator.toString()})(request, PineTSLib, (${normalizePineContext.toString()}), (${unknownIndicatorInputsMessage.toString()}))); return results; })())((target, name) => Object.defineProperty(target, "name", { value: name, configurable: true }));`;
169
+ const result = await sandbox.execute(code, { signal: combined, timeoutMs });
170
+ if (!result.ok)
171
+ throw new IndicatorError(`PineTS ${result.error.kind}: ${result.error.message}`, result.error.kind === "aborted" ? 499 : 400, `indicator_${result.error.kind}`);
172
+ if (result.calls.length)
173
+ throw new IndicatorError("Indicator attempted a host tool call");
174
+ const values = result.value;
175
+ if (!Array.isArray(values) || values.length !== payloads.length)
176
+ throw new IndicatorError("Malformed indicator batch result");
177
+ return values.map((value) => validateNormalizedIndicatorResult(value, this.limits));
178
+ });
179
+ }
180
+ async abortAgent(agentId) {
181
+ this.deleted.add(agentId);
182
+ const active = [...this.calls].filter((call) => call.agentId === agentId);
183
+ for (const call of active)
184
+ call.controller.abort(new Error("Agent deleted"));
185
+ await Promise.all(active.map((call) => call.done));
186
+ // Exits may include other Agents; deletion must not wait for their work.
187
+ await Promise.all([...this.exits].filter(([, owner]) => owner === agentId).map(([exit]) => exit));
188
+ }
189
+ close() {
190
+ return this.closing ??= (async () => {
191
+ this.stopping = true;
192
+ for (const call of this.calls)
193
+ call.controller.abort(new Error("Indicator runtime closed"));
194
+ await Promise.all([...this.calls].map((call) => call.done));
195
+ await Promise.allSettled(this.exits.keys());
196
+ await this.initializing?.catch(() => { });
197
+ this.bundle = undefined;
198
+ this.deleted.clear();
199
+ })();
200
+ }
201
+ }