@reefclaw/connect 0.1.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 (415) hide show
  1. package/assets/bridge/bridge.d.ts +96 -0
  2. package/assets/bridge/bridge.js +969 -0
  3. package/assets/bridge/config.d.ts +43 -0
  4. package/assets/bridge/config.js +176 -0
  5. package/assets/bridge/connector.d.ts +52 -0
  6. package/assets/bridge/connector.js +293 -0
  7. package/assets/bridge/event-replay-buffer.d.ts +43 -0
  8. package/assets/bridge/event-replay-buffer.js +109 -0
  9. package/assets/bridge/gateway/event-parser.d.ts +209 -0
  10. package/assets/bridge/gateway/event-parser.js +793 -0
  11. package/assets/bridge/gateway/gateway-config.d.ts +39 -0
  12. package/assets/bridge/gateway/gateway-config.js +86 -0
  13. package/assets/bridge/gateway/gateway-http-client.d.ts +50 -0
  14. package/assets/bridge/gateway/gateway-http-client.js +165 -0
  15. package/assets/bridge/gateway/gateway-ws-client.d.ts +116 -0
  16. package/assets/bridge/gateway/gateway-ws-client.js +417 -0
  17. package/assets/bridge/gateway/poller.d.ts +146 -0
  18. package/assets/bridge/gateway/poller.js +505 -0
  19. package/assets/bridge/gateway/tool-discovery.d.ts +25 -0
  20. package/assets/bridge/gateway/tool-discovery.js +198 -0
  21. package/assets/bridge/index.d.ts +2 -0
  22. package/assets/bridge/index.js +253 -0
  23. package/assets/bridge/logger.d.ts +2 -0
  24. package/assets/bridge/logger.js +2 -0
  25. package/assets/bridge/provider.d.ts +156 -0
  26. package/assets/bridge/provider.js +2 -0
  27. package/assets/bridge/providers/emergency-commands.d.ts +54 -0
  28. package/assets/bridge/providers/emergency-commands.js +235 -0
  29. package/assets/bridge/providers/gateway.d.ts +322 -0
  30. package/assets/bridge/providers/gateway.js +2302 -0
  31. package/assets/bridge/providers/mock.d.ts +37 -0
  32. package/assets/bridge/providers/mock.js +385 -0
  33. package/assets/bridge/providers/onboarding-commands.d.ts +83 -0
  34. package/assets/bridge/providers/onboarding-commands.js +213 -0
  35. package/assets/bridge/providers/risk-calculator.d.ts +96 -0
  36. package/assets/bridge/providers/risk-calculator.js +369 -0
  37. package/assets/bridge/setup.d.ts +32 -0
  38. package/assets/bridge/setup.js +226 -0
  39. package/assets/bridge/types.d.ts +584 -0
  40. package/assets/bridge/types.js +50 -0
  41. package/assets/bridge/utils/reconnect.d.ts +6 -0
  42. package/assets/bridge/utils/reconnect.js +6 -0
  43. package/assets/bridge/utils/skill-signing.d.ts +51 -0
  44. package/assets/bridge/utils/skill-signing.js +138 -0
  45. package/assets/bridge/utils/skill-version.d.ts +17 -0
  46. package/assets/bridge/utils/skill-version.js +71 -0
  47. package/assets/plugin/audit/mode-transition-audit.d.ts +11 -0
  48. package/assets/plugin/audit/mode-transition-audit.js +29 -0
  49. package/assets/plugin/balance-utils.d.ts +36 -0
  50. package/assets/plugin/balance-utils.js +98 -0
  51. package/assets/plugin/ccxt/binance-ban-gate.d.ts +47 -0
  52. package/assets/plugin/ccxt/binance-ban-gate.js +409 -0
  53. package/assets/plugin/ccxt/binance-private.d.ts +325 -0
  54. package/assets/plugin/ccxt/binance-private.js +1415 -0
  55. package/assets/plugin/ccxt/binance-public.d.ts +18 -0
  56. package/assets/plugin/ccxt/binance-public.js +147 -0
  57. package/assets/plugin/config/agent-config-client.d.ts +55 -0
  58. package/assets/plugin/config/agent-config-client.js +145 -0
  59. package/assets/plugin/config/agent-config-poller.d.ts +25 -0
  60. package/assets/plugin/config/agent-config-poller.js +100 -0
  61. package/assets/plugin/config/brackets-config.d.ts +22 -0
  62. package/assets/plugin/config/brackets-config.js +58 -0
  63. package/assets/plugin/config/gate-store.d.ts +18 -0
  64. package/assets/plugin/config/gate-store.js +61 -0
  65. package/assets/plugin/config/plugin-config-io.d.ts +175 -0
  66. package/assets/plugin/config/plugin-config-io.js +84 -0
  67. package/assets/plugin/config/position-review-config.d.ts +35 -0
  68. package/assets/plugin/config/position-review-config.js +105 -0
  69. package/assets/plugin/config/tool-gate.d.ts +53 -0
  70. package/assets/plugin/config/tool-gate.js +125 -0
  71. package/assets/plugin/config/user-data-stream-config.d.ts +85 -0
  72. package/assets/plugin/config/user-data-stream-config.js +224 -0
  73. package/assets/plugin/exchange-adapter.d.ts +49 -0
  74. package/assets/plugin/exchange-adapter.js +4 -0
  75. package/assets/plugin/index.d.ts +30 -0
  76. package/assets/plugin/index.js +1989 -0
  77. package/assets/plugin/ingest/pending-entry-metadata.d.ts +52 -0
  78. package/assets/plugin/ingest/pending-entry-metadata.js +182 -0
  79. package/assets/plugin/ingest/position-auto-capture.d.ts +98 -0
  80. package/assets/plugin/ingest/position-auto-capture.js +394 -0
  81. package/assets/plugin/ingest/position-decisions-client.d.ts +318 -0
  82. package/assets/plugin/ingest/position-decisions-client.js +296 -0
  83. package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +13 -0
  84. package/assets/plugin/ingest/reconcile-db-vs-exchange.js +114 -0
  85. package/assets/plugin/ingest/reconciler-cleanup.d.ts +37 -0
  86. package/assets/plugin/ingest/reconciler-cleanup.js +147 -0
  87. package/assets/plugin/ingest/rest-gap-filler.d.ts +191 -0
  88. package/assets/plugin/ingest/rest-gap-filler.js +565 -0
  89. package/assets/plugin/ingest/touched-symbols-store.d.ts +25 -0
  90. package/assets/plugin/ingest/touched-symbols-store.js +96 -0
  91. package/assets/plugin/ingest/trade-store-client.d.ts +40 -0
  92. package/assets/plugin/ingest/trade-store-client.js +125 -0
  93. package/assets/plugin/ingest/ws-ingest.d.ts +43 -0
  94. package/assets/plugin/ingest/ws-ingest.js +126 -0
  95. package/assets/plugin/learning/setup-family.d.ts +21 -0
  96. package/assets/plugin/learning/setup-family.js +103 -0
  97. package/assets/plugin/lifecycle/install-signal-handlers.d.ts +33 -0
  98. package/assets/plugin/lifecycle/install-signal-handlers.js +112 -0
  99. package/assets/plugin/lifecycle/shutdown-coordinator.d.ts +43 -0
  100. package/assets/plugin/lifecycle/shutdown-coordinator.js +131 -0
  101. package/assets/plugin/live/bracket-id.d.ts +18 -0
  102. package/assets/plugin/live/bracket-id.js +81 -0
  103. package/assets/plugin/live/bracket-ledger.d.ts +54 -0
  104. package/assets/plugin/live/bracket-ledger.js +267 -0
  105. package/assets/plugin/live/bracket-manager.d.ts +82 -0
  106. package/assets/plugin/live/bracket-manager.js +478 -0
  107. package/assets/plugin/live/bracket-params.d.ts +22 -0
  108. package/assets/plugin/live/bracket-params.js +124 -0
  109. package/assets/plugin/live/bracket-reconciler.d.ts +95 -0
  110. package/assets/plugin/live/bracket-reconciler.js +573 -0
  111. package/assets/plugin/live/bracket-types.d.ts +102 -0
  112. package/assets/plugin/live/bracket-types.js +8 -0
  113. package/assets/plugin/live/deposit-tracker.d.ts +62 -0
  114. package/assets/plugin/live/deposit-tracker.js +97 -0
  115. package/assets/plugin/live/emergency-controls.d.ts +32 -0
  116. package/assets/plugin/live/emergency-controls.js +226 -0
  117. package/assets/plugin/live/exchange-errors.d.ts +12 -0
  118. package/assets/plugin/live/exchange-errors.js +130 -0
  119. package/assets/plugin/live/exchange-info-cache.d.ts +35 -0
  120. package/assets/plugin/live/exchange-info-cache.js +119 -0
  121. package/assets/plugin/live/fact-subscriber.d.ts +78 -0
  122. package/assets/plugin/live/fact-subscriber.js +182 -0
  123. package/assets/plugin/live/intent-journal.d.ts +42 -0
  124. package/assets/plugin/live/intent-journal.js +122 -0
  125. package/assets/plugin/live/listen-key-manager.d.ts +70 -0
  126. package/assets/plugin/live/listen-key-manager.js +169 -0
  127. package/assets/plugin/live/live-adapter.d.ts +264 -0
  128. package/assets/plugin/live/live-adapter.js +1665 -0
  129. package/assets/plugin/live/live-balance-enricher.d.ts +32 -0
  130. package/assets/plugin/live/live-balance-enricher.js +104 -0
  131. package/assets/plugin/live/live-bracket-api.d.ts +13 -0
  132. package/assets/plugin/live/live-bracket-api.js +20 -0
  133. package/assets/plugin/live/live-state-store.d.ts +194 -0
  134. package/assets/plugin/live/live-state-store.js +450 -0
  135. package/assets/plugin/live/local-signal-service.d.ts +57 -0
  136. package/assets/plugin/live/local-signal-service.js +146 -0
  137. package/assets/plugin/live/local-strategy-evaluator.d.ts +62 -0
  138. package/assets/plugin/live/local-strategy-evaluator.js +127 -0
  139. package/assets/plugin/live/microstructure-assembler.d.ts +54 -0
  140. package/assets/plugin/live/microstructure-assembler.js +148 -0
  141. package/assets/plugin/live/order-poller.d.ts +29 -0
  142. package/assets/plugin/live/order-poller.js +125 -0
  143. package/assets/plugin/live/position-state-store.d.ts +83 -0
  144. package/assets/plugin/live/position-state-store.js +237 -0
  145. package/assets/plugin/live/proposal-decision-listener.d.ts +64 -0
  146. package/assets/plugin/live/proposal-decision-listener.js +288 -0
  147. package/assets/plugin/live/proposal-manager.d.ts +76 -0
  148. package/assets/plugin/live/proposal-manager.js +140 -0
  149. package/assets/plugin/live/rate-limiter.d.ts +47 -0
  150. package/assets/plugin/live/rate-limiter.js +159 -0
  151. package/assets/plugin/live/reconciler.d.ts +39 -0
  152. package/assets/plugin/live/reconciler.js +175 -0
  153. package/assets/plugin/live/setup-buckets.d.ts +7 -0
  154. package/assets/plugin/live/setup-buckets.js +33 -0
  155. package/assets/plugin/live/slippage-tracker.d.ts +45 -0
  156. package/assets/plugin/live/slippage-tracker.js +78 -0
  157. package/assets/plugin/live/stop-watcher.d.ts +34 -0
  158. package/assets/plugin/live/stop-watcher.js +158 -0
  159. package/assets/plugin/live/user-data-active-probe.d.ts +54 -0
  160. package/assets/plugin/live/user-data-active-probe.js +180 -0
  161. package/assets/plugin/live/user-data-stream-controller.d.ts +200 -0
  162. package/assets/plugin/live/user-data-stream-controller.js +579 -0
  163. package/assets/plugin/live/user-data-stream-ws.d.ts +22 -0
  164. package/assets/plugin/live/user-data-stream-ws.js +63 -0
  165. package/assets/plugin/live/user-data-stream.d.ts +243 -0
  166. package/assets/plugin/live/user-data-stream.js +704 -0
  167. package/assets/plugin/logger.d.ts +2 -0
  168. package/assets/plugin/logger.js +2 -0
  169. package/assets/plugin/mfe.d.ts +21 -0
  170. package/assets/plugin/mfe.js +68 -0
  171. package/assets/plugin/onboarding/mode-ladder.d.ts +1 -0
  172. package/assets/plugin/onboarding/mode-ladder.js +3 -0
  173. package/assets/plugin/onboarding/runtime.d.ts +71 -0
  174. package/assets/plugin/onboarding/runtime.js +153 -0
  175. package/assets/plugin/openclaw.plugin.json +91 -0
  176. package/assets/plugin/paper-adapter.d.ts +24 -0
  177. package/assets/plugin/paper-adapter.js +91 -0
  178. package/assets/plugin/persistence/state-manager.d.ts +42 -0
  179. package/assets/plugin/persistence/state-manager.js +164 -0
  180. package/assets/plugin/pinned-plan.d.ts +9 -0
  181. package/assets/plugin/pinned-plan.js +23 -0
  182. package/assets/plugin/risk/pre-trade-check.d.ts +38 -0
  183. package/assets/plugin/risk/pre-trade-check.js +345 -0
  184. package/assets/plugin/risk/pre-trade-types.d.ts +60 -0
  185. package/assets/plugin/risk/pre-trade-types.js +3 -0
  186. package/assets/plugin/shadow/shadow-tracker.d.ts +36 -0
  187. package/assets/plugin/shadow/shadow-tracker.js +151 -0
  188. package/assets/plugin/shadow/types.d.ts +42 -0
  189. package/assets/plugin/shadow/types.js +20 -0
  190. package/assets/plugin/shared/indicators-extended.d.ts +52 -0
  191. package/assets/plugin/shared/indicators-extended.js +291 -0
  192. package/assets/plugin/shared/indicators.d.ts +15 -0
  193. package/assets/plugin/shared/indicators.js +114 -0
  194. package/assets/plugin/signals/conditions/registry.d.ts +16 -0
  195. package/assets/plugin/signals/conditions/registry.js +1274 -0
  196. package/assets/plugin/signals/conditions/types.d.ts +1 -0
  197. package/assets/plugin/signals/conditions/types.js +4 -0
  198. package/assets/plugin/signals/direction-rules.d.ts +3 -0
  199. package/assets/plugin/signals/direction-rules.js +24 -0
  200. package/assets/plugin/signals/entry-rules.d.ts +6 -0
  201. package/assets/plugin/signals/entry-rules.js +33 -0
  202. package/assets/plugin/signals/serialize-context.d.ts +4 -0
  203. package/assets/plugin/signals/serialize-context.js +39 -0
  204. package/assets/plugin/signals/stop-rules.d.ts +3 -0
  205. package/assets/plugin/signals/stop-rules.js +48 -0
  206. package/assets/plugin/signals/strategy-adapter.d.ts +14 -0
  207. package/assets/plugin/signals/strategy-adapter.js +122 -0
  208. package/assets/plugin/signals/types.d.ts +1 -0
  209. package/assets/plugin/signals/types.js +8 -0
  210. package/assets/plugin/simulator/exchange-simulator.d.ts +93 -0
  211. package/assets/plugin/simulator/exchange-simulator.js +684 -0
  212. package/assets/plugin/simulator/fill-engine.d.ts +53 -0
  213. package/assets/plugin/simulator/fill-engine.js +276 -0
  214. package/assets/plugin/simulator/paper-market-feed.d.ts +26 -0
  215. package/assets/plugin/simulator/paper-market-feed.js +104 -0
  216. package/assets/plugin/simulator/realistic-fills.d.ts +59 -0
  217. package/assets/plugin/simulator/realistic-fills.js +175 -0
  218. package/assets/plugin/simulator/types.d.ts +219 -0
  219. package/assets/plugin/simulator/types.js +43 -0
  220. package/assets/plugin/strategy/builtin-strategies.d.ts +2 -0
  221. package/assets/plugin/strategy/builtin-strategies.js +109 -0
  222. package/assets/plugin/strategy/condition-registry.d.ts +3 -0
  223. package/assets/plugin/strategy/condition-registry.js +153 -0
  224. package/assets/plugin/strategy/evaluator.d.ts +67 -0
  225. package/assets/plugin/strategy/evaluator.js +93 -0
  226. package/assets/plugin/tools/assessment-validation.d.ts +118 -0
  227. package/assets/plugin/tools/assessment-validation.js +415 -0
  228. package/assets/plugin/tools/attach-brackets.d.ts +34 -0
  229. package/assets/plugin/tools/attach-brackets.js +363 -0
  230. package/assets/plugin/tools/audit-bracket-protection.d.ts +49 -0
  231. package/assets/plugin/tools/audit-bracket-protection.js +527 -0
  232. package/assets/plugin/tools/cancel-all-orders.d.ts +7 -0
  233. package/assets/plugin/tools/cancel-all-orders.js +5 -0
  234. package/assets/plugin/tools/cancel-order.d.ts +10 -0
  235. package/assets/plugin/tools/cancel-order.js +14 -0
  236. package/assets/plugin/tools/check-position-health.d.ts +46 -0
  237. package/assets/plugin/tools/check-position-health.js +194 -0
  238. package/assets/plugin/tools/clear-exchange-credentials.d.ts +24 -0
  239. package/assets/plugin/tools/clear-exchange-credentials.js +70 -0
  240. package/assets/plugin/tools/close-position.d.ts +22 -0
  241. package/assets/plugin/tools/close-position.js +449 -0
  242. package/assets/plugin/tools/create-order.d.ts +54 -0
  243. package/assets/plugin/tools/create-order.js +338 -0
  244. package/assets/plugin/tools/exit-gate.d.ts +58 -0
  245. package/assets/plugin/tools/exit-gate.js +162 -0
  246. package/assets/plugin/tools/fetch-balance.d.ts +5 -0
  247. package/assets/plugin/tools/fetch-balance.js +4 -0
  248. package/assets/plugin/tools/fetch-ohlcv.d.ts +11 -0
  249. package/assets/plugin/tools/fetch-ohlcv.js +8 -0
  250. package/assets/plugin/tools/fetch-open-orders.d.ts +7 -0
  251. package/assets/plugin/tools/fetch-open-orders.js +4 -0
  252. package/assets/plugin/tools/fetch-positions.d.ts +7 -0
  253. package/assets/plugin/tools/fetch-positions.js +4 -0
  254. package/assets/plugin/tools/fetch-ticker.d.ts +11 -0
  255. package/assets/plugin/tools/fetch-ticker.js +5 -0
  256. package/assets/plugin/tools/get-agent-profile.d.ts +4 -0
  257. package/assets/plugin/tools/get-agent-profile.js +6 -0
  258. package/assets/plugin/tools/get-analytics.d.ts +6 -0
  259. package/assets/plugin/tools/get-analytics.js +7 -0
  260. package/assets/plugin/tools/get-backtest.d.ts +12 -0
  261. package/assets/plugin/tools/get-backtest.js +91 -0
  262. package/assets/plugin/tools/get-basis.d.ts +7 -0
  263. package/assets/plugin/tools/get-basis.js +7 -0
  264. package/assets/plugin/tools/get-bracket-config.d.ts +11 -0
  265. package/assets/plugin/tools/get-bracket-config.js +24 -0
  266. package/assets/plugin/tools/get-cascade-risk.d.ts +7 -0
  267. package/assets/plugin/tools/get-cascade-risk.js +8 -0
  268. package/assets/plugin/tools/get-crypto-metrics.d.ts +18 -0
  269. package/assets/plugin/tools/get-crypto-metrics.js +45 -0
  270. package/assets/plugin/tools/get-cvd.d.ts +6 -0
  271. package/assets/plugin/tools/get-cvd.js +6 -0
  272. package/assets/plugin/tools/get-divergences.d.ts +6 -0
  273. package/assets/plugin/tools/get-divergences.js +6 -0
  274. package/assets/plugin/tools/get-funding-context.d.ts +6 -0
  275. package/assets/plugin/tools/get-funding-context.js +16 -0
  276. package/assets/plugin/tools/get-liquidation-levels.d.ts +7 -0
  277. package/assets/plugin/tools/get-liquidation-levels.js +7 -0
  278. package/assets/plugin/tools/get-liquidation-pulse.d.ts +9 -0
  279. package/assets/plugin/tools/get-liquidation-pulse.js +22 -0
  280. package/assets/plugin/tools/get-market-breadth.d.ts +6 -0
  281. package/assets/plugin/tools/get-market-breadth.js +8 -0
  282. package/assets/plugin/tools/get-market-intel.d.ts +19 -0
  283. package/assets/plugin/tools/get-market-intel.js +116 -0
  284. package/assets/plugin/tools/get-market-structure.d.ts +47 -0
  285. package/assets/plugin/tools/get-market-structure.js +198 -0
  286. package/assets/plugin/tools/get-my-mined-patterns.d.ts +20 -0
  287. package/assets/plugin/tools/get-my-mined-patterns.js +61 -0
  288. package/assets/plugin/tools/get-my-proposed-learnings.d.ts +20 -0
  289. package/assets/plugin/tools/get-my-proposed-learnings.js +55 -0
  290. package/assets/plugin/tools/get-my-recent-reviews.d.ts +22 -0
  291. package/assets/plugin/tools/get-my-recent-reviews.js +66 -0
  292. package/assets/plugin/tools/get-orderbook.d.ts +21 -0
  293. package/assets/plugin/tools/get-orderbook.js +32 -0
  294. package/assets/plugin/tools/get-pattern-scan.d.ts +7 -0
  295. package/assets/plugin/tools/get-pattern-scan.js +8 -0
  296. package/assets/plugin/tools/get-regime.d.ts +6 -0
  297. package/assets/plugin/tools/get-regime.js +7 -0
  298. package/assets/plugin/tools/get-relevant-learnings.d.ts +21 -0
  299. package/assets/plugin/tools/get-relevant-learnings.js +65 -0
  300. package/assets/plugin/tools/get-resting-liquidity.d.ts +6 -0
  301. package/assets/plugin/tools/get-resting-liquidity.js +11 -0
  302. package/assets/plugin/tools/get-risk-scenario.d.ts +29 -0
  303. package/assets/plugin/tools/get-risk-scenario.js +47 -0
  304. package/assets/plugin/tools/get-risk-summary.d.ts +51 -0
  305. package/assets/plugin/tools/get-risk-summary.js +118 -0
  306. package/assets/plugin/tools/get-sentiment.d.ts +4 -0
  307. package/assets/plugin/tools/get-sentiment.js +6 -0
  308. package/assets/plugin/tools/get-session-review.d.ts +7 -0
  309. package/assets/plugin/tools/get-session-review.js +8 -0
  310. package/assets/plugin/tools/get-setup-detail.d.ts +7 -0
  311. package/assets/plugin/tools/get-setup-detail.js +303 -0
  312. package/assets/plugin/tools/get-signals.d.ts +15 -0
  313. package/assets/plugin/tools/get-signals.js +54 -0
  314. package/assets/plugin/tools/get-sizing.d.ts +6 -0
  315. package/assets/plugin/tools/get-sizing.js +6 -0
  316. package/assets/plugin/tools/get-trade-feedback.d.ts +7 -0
  317. package/assets/plugin/tools/get-trade-feedback.js +8 -0
  318. package/assets/plugin/tools/get-trade-flow.d.ts +7 -0
  319. package/assets/plugin/tools/get-trade-flow.js +7 -0
  320. package/assets/plugin/tools/get-volume-analysis.d.ts +21 -0
  321. package/assets/plugin/tools/get-volume-analysis.js +74 -0
  322. package/assets/plugin/tools/get-volume-profile.d.ts +7 -0
  323. package/assets/plugin/tools/get-volume-profile.js +7 -0
  324. package/assets/plugin/tools/helpers.d.ts +25 -0
  325. package/assets/plugin/tools/helpers.js +38 -0
  326. package/assets/plugin/tools/intel-api.d.ts +14 -0
  327. package/assets/plugin/tools/intel-api.js +52 -0
  328. package/assets/plugin/tools/intel-cache.d.ts +25 -0
  329. package/assets/plugin/tools/intel-cache.js +133 -0
  330. package/assets/plugin/tools/list-strategies.d.ts +7 -0
  331. package/assets/plugin/tools/list-strategies.js +6 -0
  332. package/assets/plugin/tools/modify-stop.d.ts +17 -0
  333. package/assets/plugin/tools/modify-stop.js +81 -0
  334. package/assets/plugin/tools/modify-target.d.ts +17 -0
  335. package/assets/plugin/tools/modify-target.js +71 -0
  336. package/assets/plugin/tools/propose-learning.d.ts +22 -0
  337. package/assets/plugin/tools/propose-learning.js +65 -0
  338. package/assets/plugin/tools/query-review-outcomes.d.ts +30 -0
  339. package/assets/plugin/tools/query-review-outcomes.js +64 -0
  340. package/assets/plugin/tools/query-trades.d.ts +21 -0
  341. package/assets/plugin/tools/query-trades.js +37 -0
  342. package/assets/plugin/tools/record-position-reviews.d.ts +38 -0
  343. package/assets/plugin/tools/record-position-reviews.js +147 -0
  344. package/assets/plugin/tools/save-strategy.d.ts +16 -0
  345. package/assets/plugin/tools/save-strategy.js +46 -0
  346. package/assets/plugin/tools/scan-pairs.d.ts +18 -0
  347. package/assets/plugin/tools/scan-pairs.js +220 -0
  348. package/assets/plugin/tools/score-setup.d.ts +31 -0
  349. package/assets/plugin/tools/score-setup.js +268 -0
  350. package/assets/plugin/tools/set-bracket-requirement.d.ts +18 -0
  351. package/assets/plugin/tools/set-bracket-requirement.js +81 -0
  352. package/assets/plugin/tools/set-exchange-credentials.d.ts +25 -0
  353. package/assets/plugin/tools/set-exchange-credentials.js +80 -0
  354. package/assets/plugin/tools/set-trading-mode.d.ts +26 -0
  355. package/assets/plugin/tools/set-trading-mode.js +135 -0
  356. package/assets/plugin/tools/test-exchange-credentials.d.ts +16 -0
  357. package/assets/plugin/tools/test-exchange-credentials.js +100 -0
  358. package/assets/plugin/tools/toggle-strategy.d.ts +8 -0
  359. package/assets/plugin/tools/toggle-strategy.js +8 -0
  360. package/assets/plugin/trading-params-cache.d.ts +26 -0
  361. package/assets/plugin/trading-params-cache.js +52 -0
  362. package/assets/plugin/types.d.ts +110 -0
  363. package/assets/plugin/types.js +7 -0
  364. package/assets/plugin/util/plugin-paths.d.ts +3 -0
  365. package/assets/plugin/util/plugin-paths.js +15 -0
  366. package/assets/shared/fills.d.ts +36 -0
  367. package/assets/shared/fills.js +20 -0
  368. package/assets/shared/index.d.ts +10 -0
  369. package/assets/shared/index.js +5 -0
  370. package/assets/shared/logger.d.ts +10 -0
  371. package/assets/shared/logger.js +34 -0
  372. package/assets/shared/protocol.d.ts +29 -0
  373. package/assets/shared/protocol.js +14 -0
  374. package/assets/shared/redact.d.ts +6 -0
  375. package/assets/shared/redact.js +31 -0
  376. package/assets/shared/shared/indicators-extended.d.ts +52 -0
  377. package/assets/shared/shared/indicators-extended.js +284 -0
  378. package/assets/shared/shared/indicators.d.ts +15 -0
  379. package/assets/shared/shared/indicators.js +107 -0
  380. package/assets/shared/signals/conditions/registry.d.ts +16 -0
  381. package/assets/shared/signals/conditions/registry.js +1267 -0
  382. package/assets/shared/signals/conditions/types.d.ts +65 -0
  383. package/assets/shared/signals/conditions/types.js +8 -0
  384. package/assets/shared/signals/direction-rules.d.ts +3 -0
  385. package/assets/shared/signals/direction-rules.js +18 -0
  386. package/assets/shared/signals/entry-rules.d.ts +6 -0
  387. package/assets/shared/signals/entry-rules.js +26 -0
  388. package/assets/shared/signals/indicators-extended.d.ts +52 -0
  389. package/assets/shared/signals/indicators-extended.js +284 -0
  390. package/assets/shared/signals/indicators.d.ts +15 -0
  391. package/assets/shared/signals/indicators.js +107 -0
  392. package/assets/shared/signals/serialize-context.d.ts +4 -0
  393. package/assets/shared/signals/serialize-context.js +41 -0
  394. package/assets/shared/signals/stop-rules.d.ts +3 -0
  395. package/assets/shared/signals/stop-rules.js +41 -0
  396. package/assets/shared/signals/strategy-adapter.d.ts +14 -0
  397. package/assets/shared/signals/strategy-adapter.js +117 -0
  398. package/assets/shared/signals/types.d.ts +187 -0
  399. package/assets/shared/signals/types.js +9 -0
  400. package/assets/shared/trading-mode.d.ts +16 -0
  401. package/assets/shared/trading-mode.js +49 -0
  402. package/assets/skill/SKILL.md +1357 -0
  403. package/dist/bridge.js +25 -0
  404. package/dist/bundle.js +33 -0
  405. package/dist/cli.js +120 -0
  406. package/dist/daemon.js +104 -0
  407. package/dist/deps.js +41 -0
  408. package/dist/exec.js +28 -0
  409. package/dist/openclaw.js +153 -0
  410. package/dist/paths.js +23 -0
  411. package/dist/plugin.js +48 -0
  412. package/dist/skill.js +35 -0
  413. package/dist/ui.js +29 -0
  414. package/dist/validate.js +28 -0
  415. package/package.json +32 -0
package/dist/bridge.js ADDED
@@ -0,0 +1,25 @@
1
+ // Install the ReefClaw connector (the relay bridge daemon). Places the skill
2
+ // dist, installs deps, vendors shared. The bridge reads ALL its config from
3
+ // ~/.openclaw/openclaw.json at startup (skills.entries.reefclaw for the relay
4
+ // token/userId/relayUrl, gateway.auth.token for the local gateway) — so we do
5
+ // NOT write a token here; the user supplies it later by pasting the connect
6
+ // message to their agent, and the bridge picks it up on its next restart.
7
+ import { join } from 'node:path';
8
+ import { BRIDGE_DIR, assetsDir, ASSET_BRIDGE, ASSET_SHARED } from './paths.js';
9
+ import { copyAsset, writePackageJson, npmInstall, vendorShared } from './deps.js';
10
+ import { step, ok, info, warn } from './ui.js';
11
+ // Bridge runtime deps — exact-pinned to match deploy-skill.py / the lockfile.
12
+ const BRIDGE_DEPS = { ws: '8.19.0', json5: '2.2.3' };
13
+ export function installBridge() {
14
+ step('Installing the ReefClaw connector');
15
+ const assets = assetsDir();
16
+ copyAsset(join(assets, ASSET_BRIDGE), BRIDGE_DIR);
17
+ info(`placed connector at ${BRIDGE_DIR}`);
18
+ writePackageJson(BRIDGE_DIR, 'reefclaw-bridge', BRIDGE_DEPS);
19
+ info('installing connector dependencies…');
20
+ if (!npmInstall(BRIDGE_DIR)) {
21
+ warn('npm install reported a problem; the connector may still start if deps resolved.');
22
+ }
23
+ vendorShared(BRIDGE_DIR, join(assets, ASSET_SHARED));
24
+ ok('connector files ready');
25
+ }
package/dist/bundle.js ADDED
@@ -0,0 +1,33 @@
1
+ // Parse the onboarding "connect message" (or a bare token) into its fields.
2
+ //
3
+ // Deterministic, order-independent, tolerant of any prose wrapped around it —
4
+ // so the user can paste the whole message from reefclaw.com/onboarding and we
5
+ // extract exactly the three fields the bridge needs. This is a standalone copy
6
+ // of skill/src/setup.ts:parseConnectBundle (the installer ships independently;
7
+ // the small parser is duplicated rather than shared, same rationale as the ×3
8
+ // redact.ts copies). Keep the two in sync.
9
+ export function parseConnectBundle(text) {
10
+ const out = {};
11
+ if (!text)
12
+ return out;
13
+ const tokenMatch = text.match(/rc_[A-Za-z0-9_-]{7,}/);
14
+ if (tokenMatch)
15
+ out.token = tokenMatch[0];
16
+ const uuidMatch = text.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/);
17
+ if (uuidMatch)
18
+ out.userId = uuidMatch[0];
19
+ const relayMatch = text.match(/wss:\/\/[^\s'"]+/);
20
+ if (relayMatch)
21
+ out.relayUrl = relayMatch[0];
22
+ return out;
23
+ }
24
+ const DEFAULT_RELAY_URL = 'wss://reefclaw.radunlupsa.partykit.dev';
25
+ /** A bundle is usable iff it carries at least a token + userId (relayUrl
26
+ * defaults). Token alone cannot reach the relay — the room URL is keyed by
27
+ * userId (skill/src/setup.ts). */
28
+ export function bundleIsComplete(b) {
29
+ return Boolean(b.token && b.userId);
30
+ }
31
+ export function withDefaults(b) {
32
+ return { ...b, relayUrl: b.relayUrl || DEFAULT_RELAY_URL };
33
+ }
package/dist/cli.js ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ // ReefClaw connect — `npx @reefclaw/connect`.
3
+ //
4
+ // Installs the ReefClaw trading plugin + connector into the user's OpenClaw and
5
+ // starts the connector as a background service. It does NOT take the connection
6
+ // token — the user links their account afterwards by pasting the connect
7
+ // message from reefclaw.com/onboarding to their agent (paste-to-agent stays the
8
+ // primary connect path). The bridge reads that config from openclaw.json and
9
+ // connects within seconds.
10
+ import { installPlugin } from './plugin.js';
11
+ import { installBridge } from './bridge.js';
12
+ import { installSkill } from './skill.js';
13
+ import { installDaemon } from './daemon.js';
14
+ import { checkGateway } from './validate.js';
15
+ import { readConfig, writeConfig, mergeReefClawConfig, gatewayAuthDowngradeNeeded, openClawInstalled, openClawConfigPath, readGatewayPort, } from './openclaw.js';
16
+ import { run, which } from './exec.js';
17
+ import { step, ok, info, warn, fail, banner, bold, green, cyan, dim } from './ui.js';
18
+ const DASHBOARD = 'https://www.reefclaw.com/dashboard';
19
+ const ONBOARDING = 'https://www.reefclaw.com/onboarding';
20
+ function preflight() {
21
+ const major = Number(process.versions.node.split('.')[0]);
22
+ if (Number.isFinite(major) && major < 20) {
23
+ fail(`Node ${process.versions.node} detected — OpenClaw + ReefClaw need Node 20+.`);
24
+ process.exit(1);
25
+ }
26
+ if (!openClawInstalled()) {
27
+ fail("Couldn't find an OpenClaw install (no ~/.openclaw directory).");
28
+ info('Install and run OpenClaw first, then re-run `npx @reefclaw/connect`.');
29
+ info(`(If your config lives elsewhere, set OPENCLAW_CONFIG_PATH. Looked at: ${openClawConfigPath()})`);
30
+ process.exit(1);
31
+ }
32
+ }
33
+ /** Re-write openclaw.json: preserve the user's existing config, overlay the
34
+ * ENTIRE plugins section the link wrote (the link can wipe other sections, so
35
+ * we start from the PRE snapshot — same approach as deploy-full.py), then
36
+ * ensure the sandbox allowlist + gateway scope flags + reefclaw skill entry.
37
+ *
38
+ * The whole plugins section — not just plugins.installs — must come from the
39
+ * POST config: `openclaw plugins install --link` writes plugins.load.paths
40
+ * (what the gateway actually loads from), plugins.entries.<id>.enabled, AND
41
+ * plugins.installs.<id>. Overlaying only `installs` silently drops
42
+ * load.paths, and the gateway never loads the plugin (verified live on
43
+ * 2026.6.11 — deploy-full.py gets away with it only because prod's PRE
44
+ * snapshot already contains load.paths from the original manual install). */
45
+ function wireConfig(pre) {
46
+ step('Wiring OpenClaw config');
47
+ const post = readConfig();
48
+ const base = { ...pre };
49
+ if (post.plugins) {
50
+ base.plugins = post.plugins;
51
+ }
52
+ // Disclose the local gateway auth relaxation the merge is about to apply —
53
+ // only when it actually changes something (the user's config didn't already
54
+ // have both flags set). Checked against the pre-link snapshot.
55
+ if (gatewayAuthDowngradeNeeded(pre)) {
56
+ warn('Relaxing local gateway device-identity auth (dangerouslyDisableDeviceAuth + allowInsecureAuth).');
57
+ info('This is required for OpenClaw v2026.4.2+ to keep operator scopes on the WS connection; keep the gateway bound to localhost.');
58
+ }
59
+ const merged = mergeReefClawConfig(base);
60
+ writeConfig(merged);
61
+ ok('sandbox allowlist (group:plugins) + gateway scope + reefclaw entry ensured');
62
+ return merged;
63
+ }
64
+ /** The gateway only loads plugins at startup — a plugin registered while it
65
+ * runs stays invisible until restart (the bridge would log "No trading tools
66
+ * found" forever). Best-effort: a user without a managed gateway just gets
67
+ * the manual hint. */
68
+ function restartGateway() {
69
+ step('Restarting the OpenClaw gateway to load the plugin');
70
+ if (!which('openclaw')) {
71
+ info('openclaw CLI not on PATH — restart your gateway manually to load the trading tools.');
72
+ return;
73
+ }
74
+ const r = run('openclaw', ['gateway', 'restart'], { timeoutMs: 120_000 });
75
+ if (r.ok) {
76
+ ok('gateway restarted');
77
+ }
78
+ else {
79
+ warn('could not restart the gateway automatically.');
80
+ info('Restart it yourself (e.g. `openclaw gateway restart`) so the trading tools load.');
81
+ }
82
+ }
83
+ function nextSteps() {
84
+ banner(green('✓ ReefClaw is installed.'));
85
+ process.stdout.write(`\n${bold('One step left — link your account:')}\n` +
86
+ ` 1. Open ${cyan(ONBOARDING)}\n` +
87
+ ` 2. Generate your token, then paste the ${bold('connect message')} to your OpenClaw agent.\n` +
88
+ ` 3. The dashboard lights up ${green('green / Connected')} on its own within a few seconds.\n\n` +
89
+ dim(`Dashboard: ${DASHBOARD}\n`));
90
+ }
91
+ async function main() {
92
+ banner(bold(cyan('ReefClaw connect')) + dim(' — link your OpenClaw agent to ReefClaw (paper trading)'));
93
+ preflight();
94
+ const pre = readConfig();
95
+ const plugin = installPlugin();
96
+ const merged = wireConfig(pre);
97
+ // After wireConfig: the config is schema-valid (flat legacy keys migrated),
98
+ // which `openclaw skills install` requires — the CLI refuses to run on an
99
+ // invalid config.
100
+ const skill = installSkill();
101
+ installBridge();
102
+ const startedService = installDaemon();
103
+ if (plugin.registered)
104
+ restartGateway();
105
+ await checkGateway(readGatewayPort(merged));
106
+ if (!plugin.registered) {
107
+ warn('The plugin was placed but not auto-registered — see the message above to finish it.');
108
+ }
109
+ if (!skill.installed) {
110
+ warn('The agent skill was placed but not registered — see the message above to finish it.');
111
+ }
112
+ if (!startedService) {
113
+ warn('The connector was installed but not auto-started — see the run command above.');
114
+ }
115
+ nextSteps();
116
+ }
117
+ main().catch((err) => {
118
+ fail(`Install failed: ${err instanceof Error ? err.message : String(err)}`);
119
+ process.exit(1);
120
+ });
package/dist/daemon.js ADDED
@@ -0,0 +1,104 @@
1
+ // Keep the bridge running across reboots. Linux/systemd-user is implemented
2
+ // fully; macOS and Windows fall back to printing the manual run command (a
3
+ // launchd/Task-Scheduler unit is a follow-up). The bridge reads its config from
4
+ // ~/.openclaw/openclaw.json, so until the user pastes their connect message the
5
+ // service will start, find no token, and restart — harmless; it connects within
6
+ // seconds of the agent writing the config.
7
+ import { writeFileSync, mkdirSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { homedir, userInfo } from 'node:os';
10
+ import { BRIDGE_DIR } from './paths.js';
11
+ import { run, which } from './exec.js';
12
+ import { step, ok, info, warn } from './ui.js';
13
+ const SERVICE_NAME = 'reefclaw-bridge';
14
+ const NODE = process.execPath; // absolute path to the node running the installer
15
+ /**
16
+ * Build the systemd user-unit text. Pure + exported so the path-quoting is
17
+ * unit-testable. Both `node` (process.execPath) and `bridgeDir` (under the
18
+ * user's home) can contain spaces. Quoting rules differ per directive:
19
+ * - ExecStart= is parsed with shell-like word splitting, so an unquoted
20
+ * `ExecStart=/home/a b/node …` reads the binary as `/home/a` — QUOTE both
21
+ * the binary and the script path.
22
+ * - WorkingDirectory= takes the raw value after `=` as a single path (no word
23
+ * splitting) — spaces are safe UNQUOTED, and quotes are treated as literal
24
+ * characters, failing the unit with "path is not absolute" (verified live
25
+ * on systemd 255 / Ubuntu 24.04). Do NOT quote it.
26
+ */
27
+ export function buildSystemdUnit(node, bridgeDir) {
28
+ const indexJs = join(bridgeDir, 'index.js');
29
+ return `[Unit]
30
+ Description=ReefClaw connector - bridges OpenClaw to the ReefClaw dashboard
31
+ After=network-online.target
32
+ Wants=network-online.target
33
+
34
+ [Service]
35
+ Type=simple
36
+ WorkingDirectory=${bridgeDir}
37
+ ExecStart="${node}" "${indexJs}" --provider gateway --log-level info
38
+ Restart=always
39
+ RestartSec=5s
40
+
41
+ [Install]
42
+ WantedBy=default.target
43
+ `;
44
+ }
45
+ function manualHint() {
46
+ warn('Could not set up an auto-start service on this OS yet.');
47
+ info('Keep the connector running with this command (leave it open / use your own service manager):');
48
+ info(` "${NODE}" "${join(BRIDGE_DIR, 'index.js')}" --provider gateway`);
49
+ }
50
+ function installSystemd() {
51
+ if (!which('systemctl'))
52
+ return false;
53
+ const unitDir = join(homedir(), '.config', 'systemd', 'user');
54
+ mkdirSync(unitDir, { recursive: true });
55
+ const unit = buildSystemdUnit(NODE, BRIDGE_DIR);
56
+ writeFileSync(join(unitDir, `${SERVICE_NAME}.service`), unit, 'utf-8');
57
+ run('systemctl', ['--user', 'daemon-reload']);
58
+ const enabled = run('systemctl', ['--user', 'enable', '--now', `${SERVICE_NAME}.service`]);
59
+ if (!enabled.ok) {
60
+ warn('systemd --user enable/start did not succeed:');
61
+ if (enabled.stderr.trim())
62
+ info(enabled.stderr.trim().split('\n').slice(-2).join('\n'));
63
+ info(`Try: systemctl --user enable --now ${SERVICE_NAME}.service`);
64
+ return false;
65
+ }
66
+ // `enable --now` can exit 0 while the unit failed to load (e.g. a bad unit
67
+ // file setting) — verify the unit actually came up before claiming ✓.
68
+ // 'active' = running; 'activating' = the expected pre-token restart loop
69
+ // (the bridge exits until the user pastes their connect message, and
70
+ // Restart=always re-launches it). Anything else (inactive/failed) means the
71
+ // unit never loaded.
72
+ const active = run('systemctl', ['--user', 'is-active', `${SERVICE_NAME}.service`]);
73
+ const state = active.stdout.trim();
74
+ if (state !== 'active' && state !== 'activating') {
75
+ warn(`the service did not come up (state: ${state || 'unknown'}).`);
76
+ info(`Inspect: systemctl --user status ${SERVICE_NAME}.service`);
77
+ return false;
78
+ }
79
+ // Linger lets the user service run without an active login session (servers).
80
+ // Best-effort: needs privileges; non-fatal if it fails.
81
+ const linger = run('loginctl', ['enable-linger', userInfo().username]);
82
+ if (linger.ok) {
83
+ info('enabled linger (service survives logout / reboot)');
84
+ }
85
+ else {
86
+ info('note: run `sudo loginctl enable-linger $USER` so the connector survives logout.');
87
+ }
88
+ return true;
89
+ }
90
+ export function installDaemon() {
91
+ step('Starting the connector as a background service');
92
+ if (process.platform === 'linux') {
93
+ if (installSystemd()) {
94
+ ok(`connector running as a systemd user service (${SERVICE_NAME})`);
95
+ info(`logs: journalctl --user -u ${SERVICE_NAME} -f`);
96
+ return true;
97
+ }
98
+ manualHint();
99
+ return false;
100
+ }
101
+ // macOS / Windows: manual for now (launchd / Task Scheduler unit is a follow-up).
102
+ manualHint();
103
+ return false;
104
+ }
package/dist/deps.js ADDED
@@ -0,0 +1,41 @@
1
+ // Dependency handling for the placed plugin/bridge dirs. Mirrors what the prod
2
+ // deploy scripts do remotely: write a package.json, `npm install --omit=dev`,
3
+ // then vendor the un-published @reefclaw/shared workspace package into
4
+ // node_modules AFTER install (so npm's prune doesn't drop it).
5
+ import { writeFileSync, cpSync, mkdirSync, existsSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { run } from './exec.js';
8
+ export function writePackageJson(dir, name, deps, extra = {}) {
9
+ const pkg = {
10
+ name,
11
+ version: '0.1.0',
12
+ private: true,
13
+ type: 'module',
14
+ main: 'index.js',
15
+ dependencies: deps,
16
+ ...extra,
17
+ };
18
+ writeFileSync(join(dir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
19
+ }
20
+ export function npmInstall(dir) {
21
+ const r = run('npm', ['install', '--omit=dev', '--no-audit', '--no-fund'], {
22
+ cwd: dir,
23
+ timeoutMs: 600_000,
24
+ });
25
+ return r.ok;
26
+ }
27
+ /** Vendor @reefclaw/shared (un-published workspace pkg) into <dir>/node_modules. */
28
+ export function vendorShared(dir, sharedAssetDir) {
29
+ const dest = join(dir, 'node_modules', '@reefclaw', 'shared');
30
+ mkdirSync(dest, { recursive: true });
31
+ // sharedAssetDir holds the shared package's dist/
32
+ cpSync(sharedAssetDir, join(dest, 'dist'), { recursive: true });
33
+ writeFileSync(join(dest, 'package.json'), JSON.stringify({ name: '@reefclaw/shared', version: '0.1.0', type: 'module', main: 'dist/index.js' }, null, 2) + '\n', 'utf-8');
34
+ }
35
+ export function copyAsset(srcDir, destDir) {
36
+ if (!existsSync(srcDir)) {
37
+ throw new Error(`bundled asset missing: ${srcDir} (was the package built with bundle-assets?)`);
38
+ }
39
+ mkdirSync(destDir, { recursive: true });
40
+ cpSync(srcDir, destDir, { recursive: true });
41
+ }
package/dist/exec.js ADDED
@@ -0,0 +1,28 @@
1
+ // Small wrappers around child_process for the installer. Synchronous (the
2
+ // install is a linear script) and resilient — callers decide whether a non-zero
3
+ // exit is fatal.
4
+ import { spawnSync } from 'node:child_process';
5
+ /** Run a command, capturing output. Never throws. */
6
+ export function run(cmd, args, opts = {}) {
7
+ const r = spawnSync(cmd, args, {
8
+ cwd: opts.cwd,
9
+ timeout: opts.timeoutMs ?? 600_000,
10
+ encoding: 'utf-8',
11
+ shell: false,
12
+ });
13
+ return {
14
+ ok: r.status === 0,
15
+ code: r.status,
16
+ stdout: (r.stdout ?? '').toString(),
17
+ stderr: (r.stderr ?? '').toString(),
18
+ };
19
+ }
20
+ /** True if a command resolves on PATH. */
21
+ export function which(cmd) {
22
+ const probe = process.platform === 'win32' ? 'where' : 'which';
23
+ const r = run(probe, [cmd], { timeoutMs: 10_000 });
24
+ if (!r.ok)
25
+ return null;
26
+ const first = r.stdout.split(/\r?\n/).map((s) => s.trim()).find(Boolean);
27
+ return first ?? null;
28
+ }
@@ -0,0 +1,153 @@
1
+ // OpenClaw config discovery + idempotent merge of the ReefClaw settings.
2
+ //
3
+ // We NEVER overwrite the user's openclaw.json — we read it, merge in only the
4
+ // keys ReefClaw needs (preserving everything else), and write it back 0600. The
5
+ // plugin itself is registered by shelling out to `openclaw plugins install
6
+ // --link` (which writes plugins.installs); that must run BEFORE this merge,
7
+ // because that command can wipe channels/gateway/skills sections (see
8
+ // deploy-full.py:145), and this merge then restores/sets our keys on top.
9
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'node:fs';
10
+ import { join, dirname } from 'node:path';
11
+ import { homedir } from 'node:os';
12
+ import JSON5 from 'json5';
13
+ /** Core sandbox tools OpenClaw needs PLUS group:plugins — without the latter,
14
+ * the plugin's tools are invisible to the agent (plugin-integration.md rule 2). */
15
+ export const REQUIRED_SANDBOX_TOOLS = [
16
+ 'exec',
17
+ 'process',
18
+ 'read',
19
+ 'write',
20
+ 'edit',
21
+ 'apply_patch',
22
+ 'image',
23
+ 'sessions_list',
24
+ 'sessions_history',
25
+ 'sessions_send',
26
+ 'sessions_spawn',
27
+ 'session_status',
28
+ 'group:plugins',
29
+ ];
30
+ export function openClawConfigPath() {
31
+ if (process.env.OPENCLAW_CONFIG_PATH)
32
+ return process.env.OPENCLAW_CONFIG_PATH;
33
+ return join(homedir(), '.openclaw', 'openclaw.json');
34
+ }
35
+ export function openClawInstalled(configPath = openClawConfigPath()) {
36
+ // The .openclaw dir existing is the signal OpenClaw has been run at least
37
+ // once; the config file itself may not exist yet on a brand-new install.
38
+ return existsSync(dirname(configPath));
39
+ }
40
+ export function readConfig(configPath = openClawConfigPath()) {
41
+ try {
42
+ return JSON5.parse(readFileSync(configPath, 'utf-8'));
43
+ }
44
+ catch {
45
+ return {};
46
+ }
47
+ }
48
+ function asObject(parent, key) {
49
+ if (typeof parent[key] !== 'object' || parent[key] === null || Array.isArray(parent[key])) {
50
+ parent[key] = {};
51
+ }
52
+ return parent[key];
53
+ }
54
+ /**
55
+ * Pure, idempotent merge. Returns a NEW config object with the ReefClaw keys
56
+ * ensured; never removes or reorders the user's existing settings.
57
+ * - tools.sandbox.tools.allow ⊇ REQUIRED_SANDBOX_TOOLS (union, de-duped)
58
+ * - gateway.controlUi.{dangerouslyDisableDeviceAuth, allowInsecureAuth} = true
59
+ * - skills.entries.reefclaw.{token,userId,relayUrl} set when provided
60
+ */
61
+ export function mergeReefClawConfig(input, connect = {}) {
62
+ const cfg = JSON.parse(JSON.stringify(input));
63
+ // --- sandbox allowlist (union) ---
64
+ const tools = asObject(cfg, 'tools');
65
+ const sandbox = asObject(tools, 'sandbox');
66
+ const sandboxTools = asObject(sandbox, 'tools');
67
+ const existingAllow = Array.isArray(sandboxTools.allow) ? sandboxTools.allow.map(String) : [];
68
+ const merged = [...existingAllow];
69
+ for (const t of REQUIRED_SANDBOX_TOOLS) {
70
+ if (!merged.includes(t))
71
+ merged.push(t);
72
+ }
73
+ sandboxTools.allow = merged;
74
+ // --- tool profile widening ---
75
+ // `openclaw setup` defaults tools.profile to "coding" (2026.6+), whose fixed
76
+ // core allowlist filters out ALL plugin tools — the agent would see none of
77
+ // the 62 trading tools. tools.alsoAllow explicitly widens the profile;
78
+ // group:plugins covers every plugin-provided tool. Union, never replace.
79
+ const existingAlsoAllow = Array.isArray(tools.alsoAllow) ? tools.alsoAllow.map(String) : [];
80
+ if (!existingAlsoAllow.includes('group:plugins')) {
81
+ tools.alsoAllow = [...existingAlsoAllow, 'group:plugins'];
82
+ }
83
+ // --- gateway controlUi scope flags (v2026.4.2+ WS scope preservation) ---
84
+ const gateway = asObject(cfg, 'gateway');
85
+ const controlUi = asObject(gateway, 'controlUi');
86
+ controlUi.dangerouslyDisableDeviceAuth = true;
87
+ controlUi.allowInsecureAuth = true;
88
+ // --- skills.entries.reefclaw (connection config) ---
89
+ // OpenClaw's skills.entries.<name> schema only allows {enabled, apiKey, env,
90
+ // config} — custom fields MUST nest under `config`. Flat fields fail config
91
+ // validation on OpenClaw 2026.6+ and the GATEWAY REFUSES TO BOOT (verified
92
+ // live: `skills.entries.reefclaw: Invalid input` → crash loop). Migrate any
93
+ // legacy flat keys into the nested shape.
94
+ const skills = asObject(cfg, 'skills');
95
+ const entries = asObject(skills, 'entries');
96
+ const reefclaw = asObject(entries, 'reefclaw');
97
+ const entryConfig = asObject(reefclaw, 'config');
98
+ for (const key of ['token', 'userId', 'relayUrl']) {
99
+ if (typeof reefclaw[key] === 'string' && entryConfig[key] === undefined) {
100
+ entryConfig[key] = reefclaw[key];
101
+ }
102
+ delete reefclaw[key];
103
+ }
104
+ if (connect.token)
105
+ entryConfig.token = connect.token;
106
+ if (connect.userId)
107
+ entryConfig.userId = connect.userId;
108
+ if (connect.relayUrl)
109
+ entryConfig.relayUrl = connect.relayUrl;
110
+ return cfg;
111
+ }
112
+ export function writeConfig(config, configPath = openClawConfigPath()) {
113
+ mkdirSync(dirname(configPath), { recursive: true, mode: 0o700 });
114
+ // File holds the connection token → owner-only.
115
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', { encoding: 'utf-8', mode: 0o600 });
116
+ // writeFileSync's `mode` is ONLY applied when the file is created; the common
117
+ // case here is re-writing an existing openclaw.json, which keeps its old
118
+ // (possibly world-readable) perms. chmod unconditionally so a token-bearing
119
+ // config is never left readable by other users. Best-effort — chmod is a
120
+ // no-op / unsupported on some Windows filesystems, so failure is non-fatal.
121
+ try {
122
+ chmodSync(configPath, 0o600);
123
+ }
124
+ catch {
125
+ /* best-effort: some filesystems (Windows) don't support POSIX modes */
126
+ }
127
+ }
128
+ /**
129
+ * True when writing our config would flip gateway.controlUi device-identity
130
+ * auth OFF (either flag not already `true`). The installer sets these to
131
+ * preserve WS operator scopes on OpenClaw v2026.4.2+, but it relaxes local
132
+ * gateway auth, so the CLI discloses it to the user when it actually changes
133
+ * something. Pure so it's unit-testable and callable before the merge.
134
+ */
135
+ export function gatewayAuthDowngradeNeeded(config) {
136
+ const gateway = config.gateway;
137
+ const controlUi = gateway?.controlUi;
138
+ return controlUi?.dangerouslyDisableDeviceAuth !== true || controlUi?.allowInsecureAuth !== true;
139
+ }
140
+ /** Read the gateway auth token OpenClaw already configured — the bridge needs
141
+ * it to call the local gateway. Returns undefined if not set. */
142
+ export function readGatewayToken(config = readConfig()) {
143
+ const gateway = config.gateway;
144
+ const auth = gateway?.auth;
145
+ const token = auth?.token;
146
+ return typeof token === 'string' ? token : undefined;
147
+ }
148
+ /** Read the gateway port (default 18789). */
149
+ export function readGatewayPort(config = readConfig()) {
150
+ const gateway = config.gateway;
151
+ const port = gateway?.port;
152
+ return typeof port === 'number' ? port : 18789;
153
+ }
package/dist/paths.js ADDED
@@ -0,0 +1,23 @@
1
+ // Filesystem layout for a local ReefClaw install.
2
+ //
3
+ // OpenClaw owns ~/.openclaw (config + its own state). ReefClaw's mechanism code
4
+ // lives under ~/.reefclaw so an uninstall is a single rm -rf and we never write
5
+ // into OpenClaw's tree except its config file (via openclaw.ts).
6
+ import { join } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { dirname } from 'node:path';
10
+ export const REEFCLAW_HOME = join(homedir(), '.reefclaw');
11
+ export const PLUGIN_DIR = join(REEFCLAW_HOME, 'plugin');
12
+ export const BRIDGE_DIR = join(REEFCLAW_HOME, 'bridge');
13
+ /** Directory holding the bundled plugin/bridge/shared dist, shipped inside the
14
+ * published npm package. Resolved relative to the compiled cli.js
15
+ * (dist/cli.js → ../assets). */
16
+ export function assetsDir() {
17
+ const here = dirname(fileURLToPath(import.meta.url)); // .../installer/dist
18
+ return join(here, '..', 'assets');
19
+ }
20
+ export const ASSET_PLUGIN = 'plugin';
21
+ export const ASSET_BRIDGE = 'bridge';
22
+ export const ASSET_SHARED = 'shared';
23
+ export const ASSET_SKILL = 'skill';
package/dist/plugin.js ADDED
@@ -0,0 +1,48 @@
1
+ // Install + register the ReefClaw trading plugin (reefclaw-paper-trading) into
2
+ // the user's OpenClaw. Mirrors deploy-full.py: place dist, install deps, vendor
3
+ // shared, then `openclaw plugins install --link`.
4
+ import { join } from 'node:path';
5
+ import { PLUGIN_DIR, assetsDir, ASSET_PLUGIN, ASSET_SHARED } from './paths.js';
6
+ import { copyAsset, writePackageJson, npmInstall, vendorShared } from './deps.js';
7
+ import { run, which } from './exec.js';
8
+ import { step, ok, info, warn, fail } from './ui.js';
9
+ // Plugin runtime deps (mirror plugin/package.json). ws + ccxt; ccxt is large.
10
+ const PLUGIN_DEPS = { ccxt: '^4.4.0', ws: '^8.18.0' };
11
+ export function installPlugin() {
12
+ step('Installing the ReefClaw trading plugin');
13
+ const assets = assetsDir();
14
+ copyAsset(join(assets, ASSET_PLUGIN), PLUGIN_DIR);
15
+ info(`placed plugin at ${PLUGIN_DIR}`);
16
+ // `openclaw.extensions` is required by `openclaw plugins install --link`
17
+ // (2026.6+ hard-fails without it). The placed dir holds the built dist at top
18
+ // level, so the entry is ./index.js — NOT ./src/index.ts like the repo's
19
+ // plugin/package.json (see CLAUDE.md "dist/package.json's openclaw entry").
20
+ writePackageJson(PLUGIN_DIR, 'reefclaw-paper-trading', PLUGIN_DEPS, {
21
+ openclaw: { extensions: ['./index.js'] },
22
+ });
23
+ info('installing plugin dependencies (this can take a minute — ccxt is large)…');
24
+ if (!npmInstall(PLUGIN_DIR)) {
25
+ warn('npm install reported a problem; the plugin may still work if deps resolved.');
26
+ }
27
+ vendorShared(PLUGIN_DIR, join(assets, ASSET_SHARED));
28
+ ok('plugin files ready');
29
+ // Register into OpenClaw. The CLI writes plugins.installs in openclaw.json and
30
+ // is the canonical path; without it on PATH we cannot reliably register.
31
+ const cli = which('openclaw');
32
+ if (!cli) {
33
+ fail('the `openclaw` CLI is not on your PATH — cannot register the plugin.');
34
+ info(`Once OpenClaw is on PATH, run: openclaw plugins install --link ${PLUGIN_DIR}`);
35
+ return { registered: false };
36
+ }
37
+ info('registering the plugin with OpenClaw…');
38
+ const r = run('openclaw', ['plugins', 'install', '--link', PLUGIN_DIR], { timeoutMs: 300_000 });
39
+ if (!r.ok) {
40
+ warn('`openclaw plugins install --link` returned non-zero:');
41
+ if (r.stderr.trim())
42
+ info(r.stderr.trim().split('\n').slice(-3).join('\n'));
43
+ info(`Retry manually: openclaw plugins install --link ${PLUGIN_DIR}`);
44
+ return { registered: false };
45
+ }
46
+ ok('plugin registered with OpenClaw');
47
+ return { registered: true };
48
+ }
package/dist/skill.js ADDED
@@ -0,0 +1,35 @@
1
+ // Install the ReefClaw bootstrap skill (SKILL.md) into the user's OpenClaw
2
+ // workspace via `openclaw skills install`. This is the local half of the
3
+ // distribution split (docs/TOOL_DISTRIBUTION_ARCHITECTURE.md): the agent needs
4
+ // the config schema + connect instructions BEFORE it has ever connected
5
+ // (chicken-and-egg — there is no central channel yet). Post-connect content
6
+ // updates arrive through the relay OTA channel, not reinstalls.
7
+ import { join } from 'node:path';
8
+ import { REEFCLAW_HOME, assetsDir, ASSET_SKILL } from './paths.js';
9
+ import { copyAsset } from './deps.js';
10
+ import { run, which } from './exec.js';
11
+ import { step, ok, info, warn } from './ui.js';
12
+ const SKILL_DIR = join(REEFCLAW_HOME, 'skill');
13
+ export function installSkill() {
14
+ step('Installing the ReefClaw agent skill');
15
+ const assets = assetsDir();
16
+ copyAsset(join(assets, ASSET_SKILL), SKILL_DIR);
17
+ info(`placed skill at ${SKILL_DIR}`);
18
+ const cli = which('openclaw');
19
+ if (!cli) {
20
+ warn('the `openclaw` CLI is not on your PATH — cannot register the skill.');
21
+ info(`Once OpenClaw is on PATH, run: openclaw skills install ${SKILL_DIR}`);
22
+ return { installed: false };
23
+ }
24
+ // Idempotent: re-install overwrites the workspace copy.
25
+ const r = run('openclaw', ['skills', 'install', SKILL_DIR], { timeoutMs: 120_000 });
26
+ if (!r.ok) {
27
+ warn('`openclaw skills install` returned non-zero:');
28
+ if (r.stderr.trim())
29
+ info(r.stderr.trim().split('\n').slice(-3).join('\n'));
30
+ info(`Retry manually: openclaw skills install ${SKILL_DIR}`);
31
+ return { installed: false };
32
+ }
33
+ ok('agent skill installed into the OpenClaw workspace');
34
+ return { installed: true };
35
+ }
package/dist/ui.js ADDED
@@ -0,0 +1,29 @@
1
+ // Tiny zero-dependency terminal UI helpers. Colour only when stdout is a TTY.
2
+ const isTTY = process.stdout.isTTY;
3
+ const c = (code, s) => (isTTY ? `\x1b[${code}m${s}\x1b[0m` : s);
4
+ export const bold = (s) => c('1', s);
5
+ export const dim = (s) => c('2', s);
6
+ export const green = (s) => c('32', s);
7
+ export const yellow = (s) => c('33', s);
8
+ export const red = (s) => c('31', s);
9
+ export const cyan = (s) => c('36', s);
10
+ let stepN = 0;
11
+ export function step(msg) {
12
+ stepN += 1;
13
+ process.stdout.write(`\n${bold(cyan(`[${stepN}]`))} ${bold(msg)}\n`);
14
+ }
15
+ export function ok(msg) {
16
+ process.stdout.write(` ${green('✓')} ${msg}\n`);
17
+ }
18
+ export function info(msg) {
19
+ process.stdout.write(` ${dim(msg)}\n`);
20
+ }
21
+ export function warn(msg) {
22
+ process.stdout.write(` ${yellow('!')} ${msg}\n`);
23
+ }
24
+ export function fail(msg) {
25
+ process.stdout.write(` ${red('✗')} ${msg}\n`);
26
+ }
27
+ export function banner(msg) {
28
+ process.stdout.write(`\n${bold(msg)}\n`);
29
+ }