@reefclaw/connect 0.1.12 → 0.1.14

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 (391) hide show
  1. package/assets/plugin/audit/mode-transition-audit.d.ts +11 -0
  2. package/assets/plugin/audit/mode-transition-audit.js +29 -0
  3. package/assets/plugin/balance-utils.d.ts +36 -0
  4. package/assets/plugin/balance-utils.js +98 -0
  5. package/assets/plugin/ccxt/binance-ban-gate.d.ts +47 -0
  6. package/assets/plugin/ccxt/binance-ban-gate.js +420 -0
  7. package/assets/plugin/ccxt/binance-private.d.ts +346 -0
  8. package/assets/plugin/ccxt/binance-private.js +1525 -0
  9. package/assets/plugin/ccxt/binance-public.d.ts +34 -0
  10. package/assets/plugin/ccxt/binance-public.js +180 -0
  11. package/assets/plugin/ccxt/intel-public.d.ts +25 -0
  12. package/assets/plugin/ccxt/intel-public.js +80 -0
  13. package/assets/plugin/ccxt/public-market-data-api.d.ts +26 -0
  14. package/assets/plugin/ccxt/public-market-data-api.js +23 -0
  15. package/assets/plugin/config/agent-config-client.d.ts +77 -0
  16. package/assets/plugin/config/agent-config-client.js +188 -0
  17. package/assets/plugin/config/agent-config-poller.d.ts +32 -0
  18. package/assets/plugin/config/agent-config-poller.js +101 -0
  19. package/assets/plugin/config/brackets-config.d.ts +22 -0
  20. package/assets/plugin/config/brackets-config.js +58 -0
  21. package/assets/plugin/config/entitlement-gate.d.ts +51 -0
  22. package/assets/plugin/config/entitlement-gate.js +137 -0
  23. package/assets/plugin/config/gate-store.d.ts +18 -0
  24. package/assets/plugin/config/gate-store.js +61 -0
  25. package/assets/plugin/config/plugin-config-io.d.ts +222 -0
  26. package/assets/plugin/config/plugin-config-io.js +126 -0
  27. package/assets/plugin/config/position-review-config.d.ts +35 -0
  28. package/assets/plugin/config/position-review-config.js +105 -0
  29. package/assets/plugin/config/tool-gate.d.ts +53 -0
  30. package/assets/plugin/config/tool-gate.js +128 -0
  31. package/assets/plugin/config/user-data-stream-config.d.ts +89 -0
  32. package/assets/plugin/config/user-data-stream-config.js +239 -0
  33. package/assets/plugin/connector-supervisor.d.ts +36 -0
  34. package/assets/plugin/connector-supervisor.js +149 -0
  35. package/assets/plugin/exchange-adapter.d.ts +65 -0
  36. package/assets/plugin/exchange-adapter.js +4 -0
  37. package/assets/plugin/index.d.ts +30 -0
  38. package/assets/plugin/index.js +2763 -0
  39. package/assets/plugin/ingest/pending-entry-metadata.d.ts +74 -0
  40. package/assets/plugin/ingest/pending-entry-metadata.js +236 -0
  41. package/assets/plugin/ingest/position-auto-capture.d.ts +171 -0
  42. package/assets/plugin/ingest/position-auto-capture.js +709 -0
  43. package/assets/plugin/ingest/position-decisions-client.d.ts +327 -0
  44. package/assets/plugin/ingest/position-decisions-client.js +306 -0
  45. package/assets/plugin/ingest/readiness-reporter.d.ts +42 -0
  46. package/assets/plugin/ingest/readiness-reporter.js +163 -0
  47. package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +51 -0
  48. package/assets/plugin/ingest/reconcile-db-vs-exchange.js +170 -0
  49. package/assets/plugin/ingest/reconciler-cleanup.d.ts +37 -0
  50. package/assets/plugin/ingest/reconciler-cleanup.js +147 -0
  51. package/assets/plugin/ingest/rest-gap-filler.d.ts +191 -0
  52. package/assets/plugin/ingest/rest-gap-filler.js +565 -0
  53. package/assets/plugin/ingest/touched-symbols-store.d.ts +25 -0
  54. package/assets/plugin/ingest/touched-symbols-store.js +96 -0
  55. package/assets/plugin/ingest/trade-store-client.d.ts +40 -0
  56. package/assets/plugin/ingest/trade-store-client.js +125 -0
  57. package/assets/plugin/ingest/ws-ingest.d.ts +43 -0
  58. package/assets/plugin/ingest/ws-ingest.js +126 -0
  59. package/assets/plugin/learning/setup-family.d.ts +21 -0
  60. package/assets/plugin/learning/setup-family.js +103 -0
  61. package/assets/plugin/lifecycle/install-signal-handlers.d.ts +33 -0
  62. package/assets/plugin/lifecycle/install-signal-handlers.js +112 -0
  63. package/assets/plugin/lifecycle/shutdown-coordinator.d.ts +43 -0
  64. package/assets/plugin/lifecycle/shutdown-coordinator.js +131 -0
  65. package/assets/plugin/lifecycle/trading-operation-lock.d.ts +17 -0
  66. package/assets/plugin/lifecycle/trading-operation-lock.js +14 -0
  67. package/assets/plugin/live/bracket-id.d.ts +26 -0
  68. package/assets/plugin/live/bracket-id.js +112 -0
  69. package/assets/plugin/live/bracket-ledger.d.ts +54 -0
  70. package/assets/plugin/live/bracket-ledger.js +267 -0
  71. package/assets/plugin/live/bracket-manager.d.ts +82 -0
  72. package/assets/plugin/live/bracket-manager.js +478 -0
  73. package/assets/plugin/live/bracket-params.d.ts +22 -0
  74. package/assets/plugin/live/bracket-params.js +124 -0
  75. package/assets/plugin/live/bracket-reconciler.d.ts +95 -0
  76. package/assets/plugin/live/bracket-reconciler.js +573 -0
  77. package/assets/plugin/live/bracket-types.d.ts +102 -0
  78. package/assets/plugin/live/bracket-types.js +8 -0
  79. package/assets/plugin/live/deposit-tracker.d.ts +62 -0
  80. package/assets/plugin/live/deposit-tracker.js +97 -0
  81. package/assets/plugin/live/emergency-controls.d.ts +32 -0
  82. package/assets/plugin/live/emergency-controls.js +226 -0
  83. package/assets/plugin/live/exchange-errors.d.ts +12 -0
  84. package/assets/plugin/live/exchange-errors.js +130 -0
  85. package/assets/plugin/live/exchange-info-cache.d.ts +37 -0
  86. package/assets/plugin/live/exchange-info-cache.js +134 -0
  87. package/assets/plugin/live/fact-subscriber.d.ts +78 -0
  88. package/assets/plugin/live/fact-subscriber.js +182 -0
  89. package/assets/plugin/live/fill-price.d.ts +13 -0
  90. package/assets/plugin/live/fill-price.js +37 -0
  91. package/assets/plugin/live/intent-journal.d.ts +42 -0
  92. package/assets/plugin/live/intent-journal.js +122 -0
  93. package/assets/plugin/live/listen-key-manager.d.ts +70 -0
  94. package/assets/plugin/live/listen-key-manager.js +169 -0
  95. package/assets/plugin/live/live-adapter.d.ts +319 -0
  96. package/assets/plugin/live/live-adapter.js +1906 -0
  97. package/assets/plugin/live/live-balance-enricher.d.ts +32 -0
  98. package/assets/plugin/live/live-balance-enricher.js +104 -0
  99. package/assets/plugin/live/live-bracket-api.d.ts +13 -0
  100. package/assets/plugin/live/live-bracket-api.js +20 -0
  101. package/assets/plugin/live/live-state-store.d.ts +194 -0
  102. package/assets/plugin/live/live-state-store.js +450 -0
  103. package/assets/plugin/live/local-signal-service.d.ts +57 -0
  104. package/assets/plugin/live/local-signal-service.js +151 -0
  105. package/assets/plugin/live/local-strategy-evaluator.d.ts +62 -0
  106. package/assets/plugin/live/local-strategy-evaluator.js +131 -0
  107. package/assets/plugin/live/microstructure-assembler.d.ts +54 -0
  108. package/assets/plugin/live/microstructure-assembler.js +148 -0
  109. package/assets/plugin/live/order-poller.d.ts +29 -0
  110. package/assets/plugin/live/order-poller.js +125 -0
  111. package/assets/plugin/live/position-state-store.d.ts +87 -0
  112. package/assets/plugin/live/position-state-store.js +237 -0
  113. package/assets/plugin/live/proposal-decision-listener.d.ts +70 -0
  114. package/assets/plugin/live/proposal-decision-listener.js +292 -0
  115. package/assets/plugin/live/proposal-manager.d.ts +76 -0
  116. package/assets/plugin/live/proposal-manager.js +140 -0
  117. package/assets/plugin/live/rate-limiter.d.ts +47 -0
  118. package/assets/plugin/live/rate-limiter.js +159 -0
  119. package/assets/plugin/live/reconciler.d.ts +39 -0
  120. package/assets/plugin/live/reconciler.js +175 -0
  121. package/assets/plugin/live/setup-buckets.d.ts +7 -0
  122. package/assets/plugin/live/setup-buckets.js +33 -0
  123. package/assets/plugin/live/slippage-tracker.d.ts +45 -0
  124. package/assets/plugin/live/slippage-tracker.js +78 -0
  125. package/assets/plugin/live/stop-watcher.d.ts +67 -0
  126. package/assets/plugin/live/stop-watcher.js +218 -0
  127. package/assets/plugin/live/user-data-active-probe.d.ts +54 -0
  128. package/assets/plugin/live/user-data-active-probe.js +180 -0
  129. package/assets/plugin/live/user-data-stream-controller.d.ts +200 -0
  130. package/assets/plugin/live/user-data-stream-controller.js +579 -0
  131. package/assets/plugin/live/user-data-stream-ws.d.ts +22 -0
  132. package/assets/plugin/live/user-data-stream-ws.js +63 -0
  133. package/assets/plugin/live/user-data-stream.d.ts +243 -0
  134. package/assets/plugin/live/user-data-stream.js +704 -0
  135. package/assets/plugin/logger.d.ts +2 -0
  136. package/assets/plugin/logger.js +2 -0
  137. package/assets/plugin/mfe.d.ts +21 -0
  138. package/assets/plugin/mfe.js +68 -0
  139. package/assets/plugin/onboarding/mode-ladder.d.ts +1 -0
  140. package/assets/plugin/onboarding/mode-ladder.js +3 -0
  141. package/assets/plugin/onboarding/runtime.d.ts +102 -0
  142. package/assets/plugin/onboarding/runtime.js +215 -0
  143. package/assets/plugin/openclaw.plugin.json +92 -0
  144. package/assets/plugin/paper-adapter.d.ts +24 -0
  145. package/assets/plugin/paper-adapter.js +91 -0
  146. package/assets/plugin/persistence/state-manager.d.ts +66 -0
  147. package/assets/plugin/persistence/state-manager.js +222 -0
  148. package/assets/plugin/pinned-plan.d.ts +9 -0
  149. package/assets/plugin/pinned-plan.js +23 -0
  150. package/assets/plugin/portfolio/reentry-tracker.d.ts +36 -0
  151. package/assets/plugin/portfolio/reentry-tracker.js +127 -0
  152. package/assets/plugin/portfolio/wave9-admission.d.ts +67 -0
  153. package/assets/plugin/portfolio/wave9-admission.js +262 -0
  154. package/assets/plugin/portfolio/wave9-policy.d.ts +36 -0
  155. package/assets/plugin/portfolio/wave9-policy.js +183 -0
  156. package/assets/plugin/risk/pre-trade-check.d.ts +38 -0
  157. package/assets/plugin/risk/pre-trade-check.js +345 -0
  158. package/assets/plugin/risk/pre-trade-types.d.ts +60 -0
  159. package/assets/plugin/risk/pre-trade-types.js +3 -0
  160. package/assets/plugin/shadow/shadow-tracker.d.ts +36 -0
  161. package/assets/plugin/shadow/shadow-tracker.js +151 -0
  162. package/assets/plugin/shadow/types.d.ts +42 -0
  163. package/assets/plugin/shadow/types.js +20 -0
  164. package/assets/plugin/shared/indicators-extended.d.ts +52 -0
  165. package/assets/plugin/shared/indicators-extended.js +291 -0
  166. package/assets/plugin/shared/indicators.d.ts +15 -0
  167. package/assets/plugin/shared/indicators.js +114 -0
  168. package/assets/plugin/signals/conditions/registry.d.ts +16 -0
  169. package/assets/plugin/signals/conditions/registry.js +1333 -0
  170. package/assets/plugin/signals/conditions/types.d.ts +1 -0
  171. package/assets/plugin/signals/conditions/types.js +4 -0
  172. package/assets/plugin/signals/direction-rules.d.ts +3 -0
  173. package/assets/plugin/signals/direction-rules.js +24 -0
  174. package/assets/plugin/signals/entry-rules.d.ts +6 -0
  175. package/assets/plugin/signals/entry-rules.js +33 -0
  176. package/assets/plugin/signals/serialize-context.d.ts +4 -0
  177. package/assets/plugin/signals/serialize-context.js +39 -0
  178. package/assets/plugin/signals/stop-rules.d.ts +3 -0
  179. package/assets/plugin/signals/stop-rules.js +48 -0
  180. package/assets/plugin/signals/strategy-adapter.d.ts +47 -0
  181. package/assets/plugin/signals/strategy-adapter.js +209 -0
  182. package/assets/plugin/signals/types.d.ts +1 -0
  183. package/assets/plugin/signals/types.js +8 -0
  184. package/assets/plugin/simulator/exchange-simulator.d.ts +105 -0
  185. package/assets/plugin/simulator/exchange-simulator.js +759 -0
  186. package/assets/plugin/simulator/fill-engine.d.ts +53 -0
  187. package/assets/plugin/simulator/fill-engine.js +280 -0
  188. package/assets/plugin/simulator/paper-market-feed.d.ts +26 -0
  189. package/assets/plugin/simulator/paper-market-feed.js +104 -0
  190. package/assets/plugin/simulator/realistic-fills.d.ts +59 -0
  191. package/assets/plugin/simulator/realistic-fills.js +175 -0
  192. package/assets/plugin/simulator/types.d.ts +228 -0
  193. package/assets/plugin/simulator/types.js +43 -0
  194. package/assets/plugin/strategy/builtin-strategies.d.ts +2 -0
  195. package/assets/plugin/strategy/builtin-strategies.js +113 -0
  196. package/assets/plugin/strategy/condition-registry.d.ts +3 -0
  197. package/assets/plugin/strategy/condition-registry.js +153 -0
  198. package/assets/plugin/strategy/evaluator.d.ts +70 -0
  199. package/assets/plugin/strategy/evaluator.js +98 -0
  200. package/assets/plugin/tools/assessment-validation.d.ts +141 -0
  201. package/assets/plugin/tools/assessment-validation.js +473 -0
  202. package/assets/plugin/tools/attach-brackets.d.ts +39 -0
  203. package/assets/plugin/tools/attach-brackets.js +564 -0
  204. package/assets/plugin/tools/audit-bracket-protection.d.ts +49 -0
  205. package/assets/plugin/tools/audit-bracket-protection.js +683 -0
  206. package/assets/plugin/tools/bracket-control.d.ts +12 -0
  207. package/assets/plugin/tools/bracket-control.js +35 -0
  208. package/assets/plugin/tools/cancel-all-orders.d.ts +9 -0
  209. package/assets/plugin/tools/cancel-all-orders.js +8 -0
  210. package/assets/plugin/tools/cancel-order.d.ts +14 -0
  211. package/assets/plugin/tools/cancel-order.js +60 -0
  212. package/assets/plugin/tools/check-position-health.d.ts +46 -0
  213. package/assets/plugin/tools/check-position-health.js +194 -0
  214. package/assets/plugin/tools/clear-exchange-credentials.d.ts +24 -0
  215. package/assets/plugin/tools/clear-exchange-credentials.js +70 -0
  216. package/assets/plugin/tools/close-position.d.ts +45 -0
  217. package/assets/plugin/tools/close-position.js +722 -0
  218. package/assets/plugin/tools/create-order.d.ts +89 -0
  219. package/assets/plugin/tools/create-order.js +1555 -0
  220. package/assets/plugin/tools/exit-gate.d.ts +58 -0
  221. package/assets/plugin/tools/exit-gate.js +162 -0
  222. package/assets/plugin/tools/fetch-balance.d.ts +5 -0
  223. package/assets/plugin/tools/fetch-balance.js +4 -0
  224. package/assets/plugin/tools/fetch-ohlcv.d.ts +11 -0
  225. package/assets/plugin/tools/fetch-ohlcv.js +8 -0
  226. package/assets/plugin/tools/fetch-open-orders.d.ts +7 -0
  227. package/assets/plugin/tools/fetch-open-orders.js +4 -0
  228. package/assets/plugin/tools/fetch-positions.d.ts +7 -0
  229. package/assets/plugin/tools/fetch-positions.js +4 -0
  230. package/assets/plugin/tools/fetch-ticker.d.ts +11 -0
  231. package/assets/plugin/tools/fetch-ticker.js +5 -0
  232. package/assets/plugin/tools/get-agent-profile.d.ts +4 -0
  233. package/assets/plugin/tools/get-agent-profile.js +6 -0
  234. package/assets/plugin/tools/get-analytics.d.ts +6 -0
  235. package/assets/plugin/tools/get-analytics.js +7 -0
  236. package/assets/plugin/tools/get-backtest.d.ts +12 -0
  237. package/assets/plugin/tools/get-backtest.js +91 -0
  238. package/assets/plugin/tools/get-basis.d.ts +7 -0
  239. package/assets/plugin/tools/get-basis.js +7 -0
  240. package/assets/plugin/tools/get-bracket-config.d.ts +11 -0
  241. package/assets/plugin/tools/get-bracket-config.js +24 -0
  242. package/assets/plugin/tools/get-cascade-risk.d.ts +7 -0
  243. package/assets/plugin/tools/get-cascade-risk.js +8 -0
  244. package/assets/plugin/tools/get-crypto-metrics.d.ts +18 -0
  245. package/assets/plugin/tools/get-crypto-metrics.js +62 -0
  246. package/assets/plugin/tools/get-cvd.d.ts +6 -0
  247. package/assets/plugin/tools/get-cvd.js +6 -0
  248. package/assets/plugin/tools/get-divergences.d.ts +6 -0
  249. package/assets/plugin/tools/get-divergences.js +6 -0
  250. package/assets/plugin/tools/get-funding-context.d.ts +6 -0
  251. package/assets/plugin/tools/get-funding-context.js +16 -0
  252. package/assets/plugin/tools/get-liquidation-levels.d.ts +7 -0
  253. package/assets/plugin/tools/get-liquidation-levels.js +7 -0
  254. package/assets/plugin/tools/get-liquidation-pulse.d.ts +9 -0
  255. package/assets/plugin/tools/get-liquidation-pulse.js +22 -0
  256. package/assets/plugin/tools/get-market-breadth.d.ts +6 -0
  257. package/assets/plugin/tools/get-market-breadth.js +8 -0
  258. package/assets/plugin/tools/get-market-intel.d.ts +19 -0
  259. package/assets/plugin/tools/get-market-intel.js +116 -0
  260. package/assets/plugin/tools/get-market-structure.d.ts +47 -0
  261. package/assets/plugin/tools/get-market-structure.js +198 -0
  262. package/assets/plugin/tools/get-my-mined-patterns.d.ts +20 -0
  263. package/assets/plugin/tools/get-my-mined-patterns.js +61 -0
  264. package/assets/plugin/tools/get-my-proposed-learnings.d.ts +20 -0
  265. package/assets/plugin/tools/get-my-proposed-learnings.js +55 -0
  266. package/assets/plugin/tools/get-my-recent-reviews.d.ts +22 -0
  267. package/assets/plugin/tools/get-my-recent-reviews.js +66 -0
  268. package/assets/plugin/tools/get-orderbook.d.ts +21 -0
  269. package/assets/plugin/tools/get-orderbook.js +32 -0
  270. package/assets/plugin/tools/get-pattern-scan.d.ts +7 -0
  271. package/assets/plugin/tools/get-pattern-scan.js +8 -0
  272. package/assets/plugin/tools/get-regime.d.ts +6 -0
  273. package/assets/plugin/tools/get-regime.js +7 -0
  274. package/assets/plugin/tools/get-relevant-learnings.d.ts +21 -0
  275. package/assets/plugin/tools/get-relevant-learnings.js +65 -0
  276. package/assets/plugin/tools/get-resting-liquidity.d.ts +6 -0
  277. package/assets/plugin/tools/get-resting-liquidity.js +11 -0
  278. package/assets/plugin/tools/get-risk-scenario.d.ts +29 -0
  279. package/assets/plugin/tools/get-risk-scenario.js +47 -0
  280. package/assets/plugin/tools/get-risk-summary.d.ts +51 -0
  281. package/assets/plugin/tools/get-risk-summary.js +118 -0
  282. package/assets/plugin/tools/get-sentiment.d.ts +4 -0
  283. package/assets/plugin/tools/get-sentiment.js +6 -0
  284. package/assets/plugin/tools/get-session-review.d.ts +7 -0
  285. package/assets/plugin/tools/get-session-review.js +8 -0
  286. package/assets/plugin/tools/get-setup-detail.d.ts +7 -0
  287. package/assets/plugin/tools/get-setup-detail.js +322 -0
  288. package/assets/plugin/tools/get-signals.d.ts +15 -0
  289. package/assets/plugin/tools/get-signals.js +54 -0
  290. package/assets/plugin/tools/get-sizing.d.ts +6 -0
  291. package/assets/plugin/tools/get-sizing.js +6 -0
  292. package/assets/plugin/tools/get-trade-feedback.d.ts +7 -0
  293. package/assets/plugin/tools/get-trade-feedback.js +8 -0
  294. package/assets/plugin/tools/get-trade-flow.d.ts +7 -0
  295. package/assets/plugin/tools/get-trade-flow.js +7 -0
  296. package/assets/plugin/tools/get-volume-analysis.d.ts +21 -0
  297. package/assets/plugin/tools/get-volume-analysis.js +74 -0
  298. package/assets/plugin/tools/get-volume-profile.d.ts +7 -0
  299. package/assets/plugin/tools/get-volume-profile.js +7 -0
  300. package/assets/plugin/tools/get-wave9-status.d.ts +127 -0
  301. package/assets/plugin/tools/get-wave9-status.js +796 -0
  302. package/assets/plugin/tools/helpers.d.ts +26 -0
  303. package/assets/plugin/tools/helpers.js +39 -0
  304. package/assets/plugin/tools/intel-api.d.ts +34 -0
  305. package/assets/plugin/tools/intel-api.js +119 -0
  306. package/assets/plugin/tools/intel-cache.d.ts +25 -0
  307. package/assets/plugin/tools/intel-cache.js +148 -0
  308. package/assets/plugin/tools/list-strategies.d.ts +17 -0
  309. package/assets/plugin/tools/list-strategies.js +23 -0
  310. package/assets/plugin/tools/modify-stop.d.ts +21 -0
  311. package/assets/plugin/tools/modify-stop.js +120 -0
  312. package/assets/plugin/tools/modify-target.d.ts +21 -0
  313. package/assets/plugin/tools/modify-target.js +110 -0
  314. package/assets/plugin/tools/propose-learning.d.ts +22 -0
  315. package/assets/plugin/tools/propose-learning.js +65 -0
  316. package/assets/plugin/tools/query-review-outcomes.d.ts +30 -0
  317. package/assets/plugin/tools/query-review-outcomes.js +64 -0
  318. package/assets/plugin/tools/query-trades.d.ts +21 -0
  319. package/assets/plugin/tools/query-trades.js +37 -0
  320. package/assets/plugin/tools/record-position-reviews.d.ts +38 -0
  321. package/assets/plugin/tools/record-position-reviews.js +147 -0
  322. package/assets/plugin/tools/save-strategy.d.ts +16 -0
  323. package/assets/plugin/tools/save-strategy.js +46 -0
  324. package/assets/plugin/tools/scan-pairs.d.ts +22 -0
  325. package/assets/plugin/tools/scan-pairs.js +234 -0
  326. package/assets/plugin/tools/score-setup.d.ts +31 -0
  327. package/assets/plugin/tools/score-setup.js +268 -0
  328. package/assets/plugin/tools/set-bracket-requirement.d.ts +18 -0
  329. package/assets/plugin/tools/set-bracket-requirement.js +81 -0
  330. package/assets/plugin/tools/set-exchange-credentials.d.ts +25 -0
  331. package/assets/plugin/tools/set-exchange-credentials.js +80 -0
  332. package/assets/plugin/tools/set-trading-mode.d.ts +26 -0
  333. package/assets/plugin/tools/set-trading-mode.js +152 -0
  334. package/assets/plugin/tools/test-exchange-credentials.d.ts +16 -0
  335. package/assets/plugin/tools/test-exchange-credentials.js +100 -0
  336. package/assets/plugin/tools/toggle-strategy.d.ts +8 -0
  337. package/assets/plugin/tools/toggle-strategy.js +15 -0
  338. package/assets/plugin/trading-params-cache.d.ts +26 -0
  339. package/assets/plugin/trading-params-cache.js +52 -0
  340. package/assets/plugin/types.d.ts +134 -0
  341. package/assets/plugin/types.js +7 -0
  342. package/assets/plugin/util/plugin-paths.d.ts +3 -0
  343. package/assets/plugin/util/plugin-paths.js +15 -0
  344. package/assets/plugin/venues/hyperliquid/hl-balance.d.ts +116 -0
  345. package/assets/plugin/venues/hyperliquid/hl-balance.js +145 -0
  346. package/assets/plugin/venues/hyperliquid/hl-bracket-coordinator.d.ts +123 -0
  347. package/assets/plugin/venues/hyperliquid/hl-bracket-coordinator.js +533 -0
  348. package/assets/plugin/venues/hyperliquid/hl-brackets.d.ts +102 -0
  349. package/assets/plugin/venues/hyperliquid/hl-brackets.js +172 -0
  350. package/assets/plugin/venues/hyperliquid/hl-cloid.d.ts +22 -0
  351. package/assets/plugin/venues/hyperliquid/hl-cloid.js +82 -0
  352. package/assets/plugin/venues/hyperliquid/hl-info-cache.d.ts +46 -0
  353. package/assets/plugin/venues/hyperliquid/hl-info-cache.js +125 -0
  354. package/assets/plugin/venues/hyperliquid/hl-live-adapter.d.ts +146 -0
  355. package/assets/plugin/venues/hyperliquid/hl-live-adapter.js +728 -0
  356. package/assets/plugin/venues/hyperliquid/hl-precision.d.ts +61 -0
  357. package/assets/plugin/venues/hyperliquid/hl-precision.js +176 -0
  358. package/assets/plugin/venues/hyperliquid/hl-private.d.ts +88 -0
  359. package/assets/plugin/venues/hyperliquid/hl-private.js +357 -0
  360. package/assets/plugin/venues/hyperliquid/hl-public.d.ts +79 -0
  361. package/assets/plugin/venues/hyperliquid/hl-public.js +436 -0
  362. package/assets/plugin/venues/hyperliquid/hl-rate-gate.d.ts +57 -0
  363. package/assets/plugin/venues/hyperliquid/hl-rate-gate.js +220 -0
  364. package/assets/plugin/venues/hyperliquid/hl-user-stream.d.ts +90 -0
  365. package/assets/plugin/venues/hyperliquid/hl-user-stream.js +220 -0
  366. package/assets/plugin/venues/registry.d.ts +38 -0
  367. package/assets/plugin/venues/registry.js +46 -0
  368. package/assets/plugin/venues/symbols.d.ts +43 -0
  369. package/assets/plugin/venues/symbols.js +107 -0
  370. package/assets/plugin/wave9/live-account-capture.d.ts +67 -0
  371. package/assets/plugin/wave9/live-account-capture.js +435 -0
  372. package/assets/plugin/wave9/live-autonomous-protection.d.ts +39 -0
  373. package/assets/plugin/wave9/live-autonomous-protection.js +112 -0
  374. package/assets/plugin/wave9/live-durable-reconciliation-scheduler.d.ts +33 -0
  375. package/assets/plugin/wave9/live-durable-reconciliation-scheduler.js +115 -0
  376. package/assets/plugin/wave9/live-execution-ledger.d.ts +107 -0
  377. package/assets/plugin/wave9/live-execution-ledger.js +498 -0
  378. package/assets/plugin/wave9/live-position-confirmation.d.ts +18 -0
  379. package/assets/plugin/wave9/live-position-confirmation.js +111 -0
  380. package/assets/plugin/wave9/live-residual-protection.d.ts +18 -0
  381. package/assets/plugin/wave9/live-residual-protection.js +250 -0
  382. package/assets/plugin/wave9/live-startup-reconciliation.d.ts +38 -0
  383. package/assets/plugin/wave9/live-startup-reconciliation.js +454 -0
  384. package/assets/plugin/wave9/live-symbol-ownership.d.ts +20 -0
  385. package/assets/plugin/wave9/live-symbol-ownership.js +132 -0
  386. package/assets/plugin/wave9/paper-admission-guard.d.ts +199 -0
  387. package/assets/plugin/wave9/paper-admission-guard.js +650 -0
  388. package/assets/plugin/wave9/usdm-evidence-provider.d.ts +42 -0
  389. package/assets/plugin/wave9/usdm-evidence-provider.js +133 -0
  390. package/dist/plugin.js +24 -15
  391. package/package.json +1 -1
@@ -0,0 +1,222 @@
1
+ import type { TradingMode, ExchangeConfig } from '../types.js';
2
+ /** The connection the AGENT saves during onboarding lives in OpenClaw's own
3
+ * config (`skills.entries.reefclaw.config` in ~/.openclaw/openclaw.json) —
4
+ * the connector reads it there, and since the chat-install flow never writes
5
+ * ~/.reefclaw/plugin-config.json, the PLUGIN must fall back to it too or
6
+ * every fresh install has working dashboards but token-starved intel tools,
7
+ * journaling ingest, and config polling (hit live on the first real user,
8
+ * 2026-07-06). Nested `.config.*` is the schema-valid shape; legacy flat
9
+ * fields are read as a fallback. Fail-soft: {} on any problem. */
10
+ export declare function readOpenClawConnection(): {
11
+ token?: string;
12
+ userId?: string;
13
+ relayUrl?: string;
14
+ };
15
+ /** Full on-disk schema. Unknown keys are preserved on round-trip. */
16
+ export interface PluginConfigFile {
17
+ connectionToken?: string;
18
+ /** 'on' → the plugin spawns + restarts the relay connector as a child of
19
+ * the gateway process (no systemd — OpenClaw is the process manager).
20
+ * Written by the npx installer on fresh installs. MUST stay defaulted off:
21
+ * prod runs the bridge under systemd and a supervisor there would
22
+ * double-connect the relay room. Kill-switch: RC_CONNECTOR_SUPERVISOR=off. */
23
+ connectorSupervisor?: 'on' | 'off';
24
+ /** Where PAPER mode reads market-data prices from. 'binance' (default) hits
25
+ * Binance public endpoints directly; 'intel' routes them through the intel
26
+ * service (GET /api/price/:symbol) so a host that Binance geo-blocks (HTTP
27
+ * 451) can still paper-trade. PAPER-ONLY + advisory: live trading always
28
+ * uses the real exchange, and readiness still probes real Binance to detect
29
+ * the 451. Kill-switch: RC_PAPER_MARKET_DATA=binance forces the default. */
30
+ paperMarketDataSource?: 'binance' | 'intel';
31
+ apiBaseUrl?: string;
32
+ intelligenceUrl?: string;
33
+ /** Exchange credentials + venue selection. `exchange.venue` picks the
34
+ * trading venue ('binance' default | 'hyperliquid'); it is LOCAL mechanism
35
+ * (never central-pushable) per docs/HYPERLIQUID_INTEGRATION_PLAN.md §5.2.
36
+ * Until Phase 3 ships the hyperliquid adapter, a non-PAPER mode on
37
+ * venue='hyperliquid' falls back to PAPER at boot. NOTE: updatePluginConfig
38
+ * replaces this block wholesale (the documented `exchange: null` clears
39
+ * credentials), so any writer (set_exchange_credentials, SSH edits) must
40
+ * carry `venue` through or it resets to the binance default. */
41
+ exchange?: ExchangeConfig;
42
+ tradingMode?: TradingMode;
43
+ /** Hyperliquid-specific knobs (Phase 3). `marketSlippagePct` bounds the IOC
44
+ * "market" order — HL has no native market order, and ccxt's 5% default is far
45
+ * too loose to ever rely on. Clamped to ≤2% adapter-side. */
46
+ hl?: {
47
+ marketSlippagePct?: number;
48
+ };
49
+ microLive?: {
50
+ sizeCapPercent?: number;
51
+ maxPositionUSDT?: number;
52
+ };
53
+ /** Exchange-native bracket orders (STOP_MARKET + TAKE_PROFIT_MARKET).
54
+ * mode='off' (default) keeps legacy stop-watcher behaviour.
55
+ * mode='observe' submits brackets AND keeps the watcher active (rollout stage).
56
+ * mode='enforce' disables watcher for live; brackets are the sole protection.
57
+ *
58
+ * requireStopLoss / requireTakeProfit (default both true) control whether
59
+ * the pre-trade gate rejects live entries that don't include the matching
60
+ * price. Operator can untick via the Trading Parameters panel; UI shows a
61
+ * red warning (stop off) or amber warning (target off) with typed confirm.
62
+ * Migration note: these flags move to intelligence DB per-user alongside
63
+ * Phase 2.5 (ledger mirror). Plugin-config is the temporary home. */
64
+ brackets?: {
65
+ mode?: 'off' | 'observe' | 'enforce';
66
+ requireStopLoss?: boolean;
67
+ requireTakeProfit?: boolean;
68
+ };
69
+ /** Facts-out signal evaluation (docs/FACTS_OUT_ARCHITECTURE.md step 5).
70
+ * evaluator='central' (default) → get_signals calls the intel engine as today.
71
+ * 'shadow' → also evaluate locally (via the SSE fact stream) and log the
72
+ * comparison; central is still authoritative (zero behaviour change).
73
+ * 'enforce' → get_signals returns the locally-computed snapshot (falling back
74
+ * to central when no fact has arrived for a symbol yet).
75
+ * `symbols` is the set the local service streams + evaluates; required when
76
+ * evaluator != 'central'. Requires the intel fact stream to be on
77
+ * (RC_INTEL_FACTS_STREAM=on). */
78
+ signals?: {
79
+ evaluator?: 'central' | 'shadow' | 'enforce';
80
+ symbols?: string[];
81
+ };
82
+ /** Binance user-data WebSocket stream (positions/balance/orders via push).
83
+ * mode='off' (default) keeps legacy REST polling authoritative.
84
+ * mode='shadow' runs the WS alongside REST and logs diffs; REST still authoritative.
85
+ * mode='observe' makes WS authoritative for reads; REST drops to 30-60s truth-check.
86
+ * mode='enforce' full cutover — skill-side pollers disabled, REST at 60s truth-check only.
87
+ *
88
+ * listenKeyRefreshMs / reconnectBaseMs / reconnectCapMs are escape-hatch tunables
89
+ * for runbook use; defaults are production-safe. staleEventWatchdogMs triggers a
90
+ * forced reconnect if no events arrive within the window (catches silent drops). */
91
+ userDataStream?: {
92
+ mode?: 'off' | 'shadow' | 'observe' | 'enforce';
93
+ listenKeyRefreshMs?: number;
94
+ reconnectBaseMs?: number;
95
+ reconnectCapMs?: number;
96
+ staleEventWatchdogMs?: number;
97
+ /** Interval for REST-refreshing algo orders into the store. Binance WS
98
+ * never pushes algo-order state changes until trigger, so this loop fills
99
+ * the gap. 0 = disabled. Default 15_000 (15s). */
100
+ algoRefreshMs?: number;
101
+ /** @deprecated since 2026-04-25 (ping-aware watchdog refactor). Field is
102
+ * still parsed and clamped so existing config files don't fail validation,
103
+ * but the runtime no longer reads it — the single `staleEventWatchdogMs`
104
+ * (default 6 min, ping-aware) plus the active REST probe replace it. */
105
+ activeStaleEventWatchdogMs?: number;
106
+ /** Active REST probe interval — polls fetchMyTrades for every open-position
107
+ * symbol; if a trade timestamp exceeds the WS lastEventAt, the WS missed
108
+ * a fill and the probe forces a reconnect. 0 = disabled. Default 60_000. */
109
+ activeProbeIntervalMs?: number;
110
+ /** Audit-trail write path (TRADE_AUDIT_TRAIL_PLAN Phase 1).
111
+ * 'off' (default) — WS ingest doesn't write to the trades table.
112
+ * 'on' — WsIngest forwards each TRADE event to the webapp's
113
+ * /api/internal/trades endpoint. Idempotent on the
114
+ * (exchange, exchange_trade_id) unique index, so it's
115
+ * safe to run alongside the legacy poller-write path.
116
+ * Orthogonal to `mode`: `mode` controls the read path; `dbWrite` controls
117
+ * the audit-write path. Both must be enabled (mode≠'off' AND dbWrite='on')
118
+ * for WS rows to land in the trades table. */
119
+ dbWrite?: 'off' | 'on';
120
+ /** Webapp base URL for the WS ingest POST. Defaults to the production
121
+ * reefclaw.com if absent; an explicit value overrides for staging /
122
+ * local-dev / on-prem deployments. */
123
+ ingestBaseUrl?: string;
124
+ };
125
+ /** Position Decision Journal — per-heartbeat-per-open-position review tool
126
+ * + stale-review gate. See docs/POSITION_DECISION_JOURNAL_PLAN.md.
127
+ *
128
+ * mode='off' (default) — `record_position_reviews` tool exists but no
129
+ * SKILL.md mandate; stale-gate is no-op.
130
+ * mode='shadow' — SKILL.md mandate live; per-heartbeat call required.
131
+ * No gate. Operator reads reviews to confirm quality.
132
+ * mode='observe' — `create_order` returns soft warning on stale review.
133
+ * mode='enforce' — `create_order` hard-rejects on stale review.
134
+ *
135
+ * staleAfterMs caps how old the most recent review can be before the gate
136
+ * fires. Default = 2 × heartbeatIntervalMs (60 min for a 30 min heartbeat).
137
+ *
138
+ * Entry/close auto-capture is always-on (independent of `mode`) once the
139
+ * webapp ingest URL + token are configured. */
140
+ positionReview?: {
141
+ mode?: 'off' | 'shadow' | 'observe' | 'enforce';
142
+ staleAfterMs?: number;
143
+ /** Exit-gate flag — prevents premature close_position calls per
144
+ * docs/EXIT_GATE_DESIGN.md. Orthogonal to `mode`: `mode` drives the
145
+ * per-heartbeat review requirement; `exitGate` drives the per-exit
146
+ * tier check.
147
+ *
148
+ * exitGate='off' (default) — gate never runs; behaviour identical to today.
149
+ * exitGate='shadow' — gate runs, result logged to close_assessment.metadata.gate_eval,
150
+ * `close_position` always proceeds.
151
+ * exitGate='observe' — gate runs; on BLOCK returns a soft warning in the
152
+ * tool result but `close_position` still proceeds.
153
+ * exitGate='enforce' — gate runs; on BLOCK rejects the tool call. */
154
+ exitGate?: 'off' | 'shadow' | 'observe' | 'enforce';
155
+ };
156
+ /** Approval Mode — per-user operator-approval-before-trade gate.
157
+ * Plugin emits a proposal via /api/internal/proposed_orders; operator decides
158
+ * in the browser; ProposalDecisionListener fires the order on approve via the
159
+ * existing create_order backend path. See docs/APPROVAL_MODE_DESIGN.md.
160
+ *
161
+ * mode='off' (default) — fully autonomous; create_order fires immediately.
162
+ * Toggle-off is byte-identical to today's behaviour.
163
+ * mode='per_trade' — every create_order emits a proposal and returns
164
+ * {status:'pending_approval'} to the agent. Listener
165
+ * fires the order when the operator clicks Approve.
166
+ *
167
+ * pollIntervalMs caps how often the listener checks for approved-but-unfired
168
+ * proposals via GET /api/internal/proposed_orders/pending-decisions. Default
169
+ * 3 sec — well under typical human approval latency. */
170
+ approval?: {
171
+ mode?: 'off' | 'per_trade';
172
+ pollIntervalMs?: number;
173
+ };
174
+ /** Public Binance market microstructure features (cross-market liquidation
175
+ * pulse + banded resting liquidity). Data layer lives on the intelligence
176
+ * VPS (separate workstream — see docs/MARKET_MICROSTRUCTURE_STREAMS.md);
177
+ * this flag controls whether the plugin attaches a per-symbol microstructure
178
+ * block to position-aware tool results (e.g. check_position_health) so the
179
+ * agent sees orderbook context every heartbeat without an extra tool call.
180
+ *
181
+ * heartbeatPush='off' (default) — no auto-attach. Agent can still call
182
+ * get_resting_liquidity / get_liquidation_pulse
183
+ * explicitly.
184
+ * heartbeatPush='on' — block attached when intel data is fresh. */
185
+ microstructure?: {
186
+ heartbeatPush?: 'off' | 'on';
187
+ };
188
+ /** EFFICIENCY_QUICK_WINS Change 1 — operator override for the legacy
189
+ * PositionWatcher poll cadence. Default 10000 (see stop-watcher.ts).
190
+ * Lets the operator revert the 3s→10s cut with zero deploy if a soak
191
+ * criterion fails. */
192
+ stopWatcher?: {
193
+ intervalMs?: number;
194
+ };
195
+ [extra: string]: unknown;
196
+ }
197
+ export declare function defaultConfigPath(): string;
198
+ /** Best-effort read of the operator's stop-watcher cadence override
199
+ * (`stopWatcher.intervalMs`). Undefined (default applies) unless the config
200
+ * holds a finite positive number. Read at every watcher CONSTRUCTION — boot
201
+ * AND runtime reconnects — so a mode/credential swap can't silently revert
202
+ * the override to the default (same read-at-build-time pattern as
203
+ * loadBracketMode). */
204
+ export declare function loadStopWatcherIntervalMs(path?: string): number | undefined;
205
+ /** Read the config file. Returns `{}` if the file doesn't exist.
206
+ * Throws if the file exists but is unreadable or not valid JSON — callers
207
+ * should treat that as an abort signal, not silently overwrite. */
208
+ export declare function readPluginConfig(path?: string): PluginConfigFile;
209
+ /** Apply a patch on top of the existing file and write atomically.
210
+ * - Unknown top-level keys in the on-disk file are preserved.
211
+ * - Unknown sub-keys of `microLive` are preserved.
212
+ * - Passing `undefined` as a top-level patch value deletes that key.
213
+ * - A `null` for `exchange` clears credentials.
214
+ *
215
+ * Atomicity: we write to `<path>.tmp` then rename. If the process crashes
216
+ * mid-write, the original file is untouched. A stale `.tmp` is overwritten
217
+ * on the next successful write.
218
+ */
219
+ export declare function updatePluginConfig(patch: Partial<PluginConfigFile>, path?: string): PluginConfigFile;
220
+ /** Redact a credential for logging — keeps first 4 and last 2 chars.
221
+ * Never log the full key/secret. */
222
+ export declare function redactCredential(value: string | undefined | null): string;
@@ -0,0 +1,126 @@
1
+ // Atomic read/write for ~/.reefclaw/plugin-config.json.
2
+ //
3
+ // Historically the plugin only READ this file at startup. As of PR1 of the
4
+ // dashboard onboarding feature, the plugin also WRITES it when the operator
5
+ // sets credentials or switches trading mode from the webapp. Writes must be
6
+ // crash-safe (no half-written JSON) and must preserve keys we don't understand
7
+ // (forwards compatibility — other tools may add fields we don't know about).
8
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
9
+ import { homedir } from 'node:os';
10
+ import { dirname, join } from 'node:path';
11
+ /** The connection the AGENT saves during onboarding lives in OpenClaw's own
12
+ * config (`skills.entries.reefclaw.config` in ~/.openclaw/openclaw.json) —
13
+ * the connector reads it there, and since the chat-install flow never writes
14
+ * ~/.reefclaw/plugin-config.json, the PLUGIN must fall back to it too or
15
+ * every fresh install has working dashboards but token-starved intel tools,
16
+ * journaling ingest, and config polling (hit live on the first real user,
17
+ * 2026-07-06). Nested `.config.*` is the schema-valid shape; legacy flat
18
+ * fields are read as a fallback. Fail-soft: {} on any problem. */
19
+ export function readOpenClawConnection() {
20
+ try {
21
+ const path = process.env.OPENCLAW_CONFIG_PATH ?? join(homedir(), '.openclaw', 'openclaw.json');
22
+ if (!existsSync(path))
23
+ return {};
24
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
25
+ const entry = parsed?.skills?.entries?.reefclaw;
26
+ if (!entry)
27
+ return {};
28
+ return {
29
+ token: entry.config?.token ?? entry.token,
30
+ userId: entry.config?.userId ?? entry.userId,
31
+ relayUrl: entry.config?.relayUrl ?? entry.relayUrl,
32
+ };
33
+ }
34
+ catch {
35
+ return {};
36
+ }
37
+ }
38
+ export function defaultConfigPath() {
39
+ return join(homedir(), '.reefclaw', 'plugin-config.json');
40
+ }
41
+ /** Best-effort read of the operator's stop-watcher cadence override
42
+ * (`stopWatcher.intervalMs`). Undefined (default applies) unless the config
43
+ * holds a finite positive number. Read at every watcher CONSTRUCTION — boot
44
+ * AND runtime reconnects — so a mode/credential swap can't silently revert
45
+ * the override to the default (same read-at-build-time pattern as
46
+ * loadBracketMode). */
47
+ export function loadStopWatcherIntervalMs(path) {
48
+ try {
49
+ const swMs = readPluginConfig(path).stopWatcher?.intervalMs;
50
+ if (typeof swMs === 'number' && Number.isFinite(swMs) && swMs > 0)
51
+ return swMs;
52
+ }
53
+ catch { /* best-effort — default applies */ }
54
+ return undefined;
55
+ }
56
+ /** Read the config file. Returns `{}` if the file doesn't exist.
57
+ * Throws if the file exists but is unreadable or not valid JSON — callers
58
+ * should treat that as an abort signal, not silently overwrite. */
59
+ export function readPluginConfig(path = defaultConfigPath()) {
60
+ if (!existsSync(path))
61
+ return {};
62
+ const raw = readFileSync(path, 'utf-8');
63
+ const parsed = JSON.parse(raw);
64
+ if (parsed == null || typeof parsed !== 'object' || Array.isArray(parsed)) {
65
+ throw new Error(`plugin-config.json root is not an object`);
66
+ }
67
+ return parsed;
68
+ }
69
+ /** Apply a patch on top of the existing file and write atomically.
70
+ * - Unknown top-level keys in the on-disk file are preserved.
71
+ * - Unknown sub-keys of `microLive` are preserved.
72
+ * - Passing `undefined` as a top-level patch value deletes that key.
73
+ * - A `null` for `exchange` clears credentials.
74
+ *
75
+ * Atomicity: we write to `<path>.tmp` then rename. If the process crashes
76
+ * mid-write, the original file is untouched. A stale `.tmp` is overwritten
77
+ * on the next successful write.
78
+ */
79
+ export function updatePluginConfig(patch, path = defaultConfigPath()) {
80
+ const dir = dirname(path);
81
+ if (!existsSync(dir)) {
82
+ mkdirSync(dir, { recursive: true });
83
+ }
84
+ const current = readPluginConfig(path);
85
+ const merged = { ...current };
86
+ for (const [key, value] of Object.entries(patch)) {
87
+ if (value === undefined) {
88
+ delete merged[key];
89
+ }
90
+ else if (key === 'microLive' && value && typeof value === 'object') {
91
+ merged.microLive = { ...(current.microLive ?? {}), ...value };
92
+ }
93
+ else if (key === 'brackets' && value && typeof value === 'object') {
94
+ merged.brackets = { ...(current.brackets ?? {}), ...value };
95
+ }
96
+ else if (key === 'userDataStream' && value && typeof value === 'object') {
97
+ merged.userDataStream = { ...(current.userDataStream ?? {}), ...value };
98
+ }
99
+ else if (key === 'positionReview' && value && typeof value === 'object') {
100
+ merged.positionReview = { ...(current.positionReview ?? {}), ...value };
101
+ }
102
+ else if (key === 'microstructure' && value && typeof value === 'object') {
103
+ merged.microstructure = { ...(current.microstructure ?? {}), ...value };
104
+ }
105
+ else if (key === 'approval' && value && typeof value === 'object') {
106
+ merged.approval = { ...(current.approval ?? {}), ...value };
107
+ }
108
+ else {
109
+ merged[key] = value;
110
+ }
111
+ }
112
+ const tmpPath = `${path}.tmp`;
113
+ const body = JSON.stringify(merged, null, 2) + '\n';
114
+ writeFileSync(tmpPath, body, { encoding: 'utf-8', mode: 0o600 });
115
+ renameSync(tmpPath, path);
116
+ return merged;
117
+ }
118
+ /** Redact a credential for logging — keeps first 4 and last 2 chars.
119
+ * Never log the full key/secret. */
120
+ export function redactCredential(value) {
121
+ if (!value)
122
+ return '(empty)';
123
+ if (value.length <= 8)
124
+ return '***';
125
+ return `${value.slice(0, 4)}…${value.slice(-2)}`;
126
+ }
@@ -0,0 +1,35 @@
1
+ import { type PluginConfigFile } from './plugin-config-io.js';
2
+ export type PositionReviewMode = 'off' | 'shadow' | 'observe' | 'enforce';
3
+ export declare function getPositionReviewMode(config?: PluginConfigFile): PositionReviewMode;
4
+ /** Resolve the position-review mode with the central-config precedence
5
+ * (TOOL_DISTRIBUTION_ARCHITECTURE.md §11 step 3, slice 3):
6
+ *
7
+ * central (agent_config.gates via gate-store) → plugin-config.json → 'off'
8
+ *
9
+ * The central value is already enum-validated (agent-config-client
10
+ * validateGates) and hot-applies on the next poll. `record_position_reviews`
11
+ * reads this per call (index.ts), so a dashboard/API flip needs NO restart —
12
+ * same mechanics as loadExitGateMode. Kill-switch RC_CENTRAL_GATES=off makes
13
+ * the store report null → the file rules again. (The startup log read at
14
+ * boot may still show the file value until the first poll applies central;
15
+ * it is cosmetic — the behavioural read is per-call.) */
16
+ export declare function loadPositionReviewMode(): PositionReviewMode;
17
+ export type ExitGateMode = 'off' | 'shadow' | 'observe' | 'enforce';
18
+ export declare function getExitGateMode(config?: PluginConfigFile): ExitGateMode;
19
+ /** Resolve the exit-gate mode with the central-config precedence
20
+ * (TOOL_DISTRIBUTION_ARCHITECTURE.md §11 step 3, slice 2):
21
+ *
22
+ * central (agent_config.gates via gate-store) → plugin-config.json → 'off'
23
+ *
24
+ * The central value is already enum-validated (agent-config-client
25
+ * validateGates) and hot-applies on the next poll — close-position.ts reads
26
+ * this per call, so a dashboard/API flip needs NO restart. `deps.exitGateMode`
27
+ * at the call site (tests) stays above all of this. Kill-switch
28
+ * RC_CENTRAL_GATES=off makes the store report null → the file rules again. */
29
+ export declare function loadExitGateMode(): ExitGateMode;
30
+ /** Stale threshold in ms. Default = 60 minutes (2 × 30-min heartbeat). */
31
+ export declare function getPositionReviewStaleAfterMs(config?: PluginConfigFile): number;
32
+ export declare function loadPositionReviewStaleAfterMs(): number;
33
+ export type MicrostructureHeartbeatPush = 'off' | 'on';
34
+ export declare function getMicrostructureHeartbeatPush(config?: PluginConfigFile): MicrostructureHeartbeatPush;
35
+ export declare function loadMicrostructureHeartbeatPush(): MicrostructureHeartbeatPush;
@@ -0,0 +1,105 @@
1
+ // Feature-flag readers for the Position Decision Journal.
2
+ //
3
+ // Two flags, both default 'off' so the system ships dead-code:
4
+ // - positionReview.mode drives the heartbeat-mandate + stale-gate
5
+ // - microstructure.heartbeatPush drives orderbook auto-attach to per-position tools
6
+ //
7
+ // See docs/POSITION_DECISION_JOURNAL_PLAN.md.
8
+ import { readPluginConfig } from './plugin-config-io.js';
9
+ import { gateStore } from './gate-store.js';
10
+ const VALID_REVIEW_MODES = new Set([
11
+ 'off',
12
+ 'shadow',
13
+ 'observe',
14
+ 'enforce',
15
+ ]);
16
+ export function getPositionReviewMode(config) {
17
+ const raw = config?.positionReview?.mode;
18
+ if (typeof raw === 'string' && VALID_REVIEW_MODES.has(raw)) {
19
+ return raw;
20
+ }
21
+ return 'off';
22
+ }
23
+ /** Resolve the position-review mode with the central-config precedence
24
+ * (TOOL_DISTRIBUTION_ARCHITECTURE.md §11 step 3, slice 3):
25
+ *
26
+ * central (agent_config.gates via gate-store) → plugin-config.json → 'off'
27
+ *
28
+ * The central value is already enum-validated (agent-config-client
29
+ * validateGates) and hot-applies on the next poll. `record_position_reviews`
30
+ * reads this per call (index.ts), so a dashboard/API flip needs NO restart —
31
+ * same mechanics as loadExitGateMode. Kill-switch RC_CENTRAL_GATES=off makes
32
+ * the store report null → the file rules again. (The startup log read at
33
+ * boot may still show the file value until the first poll applies central;
34
+ * it is cosmetic — the behavioural read is per-call.) */
35
+ export function loadPositionReviewMode() {
36
+ const central = gateStore.getPositionReviewMode();
37
+ if (central)
38
+ return central;
39
+ try {
40
+ return getPositionReviewMode(readPluginConfig());
41
+ }
42
+ catch {
43
+ return 'off';
44
+ }
45
+ }
46
+ const VALID_EXIT_GATE_MODES = new Set([
47
+ 'off',
48
+ 'shadow',
49
+ 'observe',
50
+ 'enforce',
51
+ ]);
52
+ export function getExitGateMode(config) {
53
+ const raw = config?.positionReview?.exitGate;
54
+ if (typeof raw === 'string' && VALID_EXIT_GATE_MODES.has(raw)) {
55
+ return raw;
56
+ }
57
+ return 'off';
58
+ }
59
+ /** Resolve the exit-gate mode with the central-config precedence
60
+ * (TOOL_DISTRIBUTION_ARCHITECTURE.md §11 step 3, slice 2):
61
+ *
62
+ * central (agent_config.gates via gate-store) → plugin-config.json → 'off'
63
+ *
64
+ * The central value is already enum-validated (agent-config-client
65
+ * validateGates) and hot-applies on the next poll — close-position.ts reads
66
+ * this per call, so a dashboard/API flip needs NO restart. `deps.exitGateMode`
67
+ * at the call site (tests) stays above all of this. Kill-switch
68
+ * RC_CENTRAL_GATES=off makes the store report null → the file rules again. */
69
+ export function loadExitGateMode() {
70
+ const central = gateStore.getExitGate();
71
+ if (central)
72
+ return central;
73
+ try {
74
+ return getExitGateMode(readPluginConfig());
75
+ }
76
+ catch {
77
+ return 'off';
78
+ }
79
+ }
80
+ /** Stale threshold in ms. Default = 60 minutes (2 × 30-min heartbeat). */
81
+ export function getPositionReviewStaleAfterMs(config) {
82
+ const raw = config?.positionReview?.staleAfterMs;
83
+ if (typeof raw === 'number' && Number.isFinite(raw) && raw > 0)
84
+ return raw;
85
+ return 60 * 60 * 1000;
86
+ }
87
+ export function loadPositionReviewStaleAfterMs() {
88
+ try {
89
+ return getPositionReviewStaleAfterMs(readPluginConfig());
90
+ }
91
+ catch {
92
+ return 60 * 60 * 1000;
93
+ }
94
+ }
95
+ export function getMicrostructureHeartbeatPush(config) {
96
+ return config?.microstructure?.heartbeatPush === 'on' ? 'on' : 'off';
97
+ }
98
+ export function loadMicrostructureHeartbeatPush() {
99
+ try {
100
+ return getMicrostructureHeartbeatPush(readPluginConfig());
101
+ }
102
+ catch {
103
+ return 'off';
104
+ }
105
+ }
@@ -0,0 +1,53 @@
1
+ /** Safety-floor (core) tools + operator-control tools. Never governable. */
2
+ export declare const UNGOVERNABLE_TOOLS: ReadonlySet<string>;
3
+ export type ToolGateMode = 'enforce' | 'shadow' | 'off';
4
+ /** RC_TOOL_GATE: 'off' = kill-switch (gate never blocks), 'shadow' = log
5
+ * would-be blocks but execute anyway, anything else/default = 'enforce'.
6
+ * Kill-switch convention per the plugin's other RC_* flags: a systemd env
7
+ * override flips it instantly on restart, no redeploy. */
8
+ export declare function resolveToolGateMode(): ToolGateMode;
9
+ /** The structured, agent-visible result for a blocked call. Worded so the
10
+ * agent adapts instead of retrying. */
11
+ export declare function disabledToolResult(name: string): {
12
+ ok: false;
13
+ error: 'tool_disabled_by_operator';
14
+ tool: string;
15
+ message: string;
16
+ };
17
+ /** Minimal structural view of a registered plugin tool. `execute` is variadic
18
+ * (toolCallId, params, signal?) and typed loosely to match the plugin-boundary
19
+ * PluginTool interface in index.ts, which itself uses `any` for params. The
20
+ * generic in wrapTool preserves the concrete tool shape (label, description,
21
+ * parameters, …). */
22
+ export interface GateablePluginTool {
23
+ name: string;
24
+ execute: (...args: any[]) => any;
25
+ }
26
+ export declare class ToolGate {
27
+ private readonly mode;
28
+ private disabled;
29
+ private version;
30
+ /** Names already shadow-logged for the current version — avoids log spam. */
31
+ private shadowLogged;
32
+ constructor(mode?: ToolGateMode);
33
+ getMode(): ToolGateMode;
34
+ getVersion(): number;
35
+ getDisabled(): string[];
36
+ /** Apply a validated config. Strips ungovernable names (third enforcement
37
+ * layer — the webapp write route and internal read route already did), and
38
+ * logs only when the effective set actually changed. */
39
+ apply(config: {
40
+ version: number;
41
+ tools: {
42
+ disabled: string[];
43
+ };
44
+ }): void;
45
+ /** Should this call be blocked? Ungovernable names short-circuit FIRST —
46
+ * the safety floor wins over any disabled set, in any mode. */
47
+ isBlocked(name: string): boolean;
48
+ /** Wrap a tool's execute with the gate check. The returned tool is
49
+ * identical except `execute` consults the gate's live state per call —
50
+ * which is what makes a config change hot-apply without re-registration.
51
+ * All original args (toolCallId, params, abort signal) pass through. */
52
+ wrapTool<T extends GateablePluginTool>(tool: T, jsonResult: (data: unknown) => unknown): T;
53
+ }
@@ -0,0 +1,128 @@
1
+ // ToolGate — the plugin-side enforcement point for the Tools-tab OFF-list
2
+ // (docs/TOOL_DISTRIBUTION_ARCHITECTURE.md §5f). Every registered tool's
3
+ // `execute` is wrapped once at registration; the wrapper consults the gate's
4
+ // LIVE state on every invocation, so a config change applies on the next call
5
+ // with no re-registration and no restart (§5e hot-reload).
6
+ //
7
+ // ★ §5d SAFETY FLOOR — UNGOVERNABLE_TOOLS is hardcoded here and checked
8
+ // BEFORE the disabled set. Even if a compromised config server, a hand-edited
9
+ // DB row, or a poisoned cache ships `close_position` in the OFF-list, the
10
+ // gate never blocks it. This set is pinned by a test on this side AND a
11
+ // mirror pin in the webapp catalog (tools-catalog.test.ts) — change both
12
+ // deliberately or not at all.
13
+ import { logger } from '../logger.js';
14
+ const TAG = 'tool-gate';
15
+ /** Safety-floor (core) tools + operator-control tools. Never governable. */
16
+ export const UNGOVERNABLE_TOOLS = new Set([
17
+ // Core safety floor — protecting/exiting positions and the review capture.
18
+ 'create_order',
19
+ 'close_position',
20
+ // Reversal capabilities for existing Wave 9 positions come only from this
21
+ // status path, so central tool preferences must never disable it.
22
+ 'get_wave9_status',
23
+ 'modify_stop',
24
+ 'attach_brackets',
25
+ 'audit_bracket_protection',
26
+ 'record_position_reviews',
27
+ // Operator-control channel — disabling these would lock the operator out.
28
+ 'set_exchange_credentials',
29
+ 'test_exchange_credentials',
30
+ 'clear_exchange_credentials',
31
+ 'set_trading_mode',
32
+ 'get_bracket_config',
33
+ 'set_bracket_requirement',
34
+ ]);
35
+ /** RC_TOOL_GATE: 'off' = kill-switch (gate never blocks), 'shadow' = log
36
+ * would-be blocks but execute anyway, anything else/default = 'enforce'.
37
+ * Kill-switch convention per the plugin's other RC_* flags: a systemd env
38
+ * override flips it instantly on restart, no redeploy. */
39
+ export function resolveToolGateMode() {
40
+ const raw = (process.env.RC_TOOL_GATE ?? '').toLowerCase();
41
+ if (raw === 'off')
42
+ return 'off';
43
+ if (raw === 'shadow')
44
+ return 'shadow';
45
+ return 'enforce';
46
+ }
47
+ /** The structured, agent-visible result for a blocked call. Worded so the
48
+ * agent adapts instead of retrying. */
49
+ export function disabledToolResult(name) {
50
+ return {
51
+ ok: false,
52
+ error: 'tool_disabled_by_operator',
53
+ tool: name,
54
+ message: `The ${name} tool has been disabled by your operator in the ReefClaw dashboard Tools tab. ` +
55
+ `Do not retry this call — adapt your plan without it, and mention to your operator that ` +
56
+ `re-enabling it in the dashboard would help if you believe it is needed.`,
57
+ };
58
+ }
59
+ export class ToolGate {
60
+ mode;
61
+ disabled = new Set();
62
+ version = 0;
63
+ /** Names already shadow-logged for the current version — avoids log spam. */
64
+ shadowLogged = new Set();
65
+ constructor(mode = resolveToolGateMode()) {
66
+ this.mode = mode;
67
+ if (mode !== 'enforce')
68
+ logger.info(TAG, `mode=${mode}`);
69
+ }
70
+ getMode() {
71
+ return this.mode;
72
+ }
73
+ getVersion() {
74
+ return this.version;
75
+ }
76
+ getDisabled() {
77
+ return [...this.disabled].sort();
78
+ }
79
+ /** Apply a validated config. Strips ungovernable names (third enforcement
80
+ * layer — the webapp write route and internal read route already did), and
81
+ * logs only when the effective set actually changed. */
82
+ apply(config) {
83
+ const next = new Set(config.tools.disabled.filter((n) => !UNGOVERNABLE_TOOLS.has(n)));
84
+ const changed = next.size !== this.disabled.size || [...next].some((n) => !this.disabled.has(n));
85
+ this.version = config.version;
86
+ if (!changed)
87
+ return;
88
+ this.disabled = next;
89
+ this.shadowLogged.clear();
90
+ logger.info(TAG, `applied config v${config.version}: ${next.size} tool(s) disabled${next.size > 0 ? ` (${[...next].sort().join(', ')})` : ''}`);
91
+ }
92
+ /** Should this call be blocked? Ungovernable names short-circuit FIRST —
93
+ * the safety floor wins over any disabled set, in any mode. */
94
+ isBlocked(name) {
95
+ if (this.mode === 'off')
96
+ return false;
97
+ if (UNGOVERNABLE_TOOLS.has(name))
98
+ return false;
99
+ if (!this.disabled.has(name))
100
+ return false;
101
+ if (this.mode === 'shadow') {
102
+ if (!this.shadowLogged.has(name)) {
103
+ this.shadowLogged.add(name);
104
+ logger.info(TAG, `SHADOW: would block ${name} (config v${this.version})`);
105
+ }
106
+ return false;
107
+ }
108
+ return true;
109
+ }
110
+ /** Wrap a tool's execute with the gate check. The returned tool is
111
+ * identical except `execute` consults the gate's live state per call —
112
+ * which is what makes a config change hot-apply without re-registration.
113
+ * All original args (toolCallId, params, abort signal) pass through. */
114
+ wrapTool(tool, jsonResult) {
115
+ const originalExecute = tool.execute.bind(tool);
116
+ return {
117
+ ...tool,
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ execute: (...args) => {
120
+ if (this.isBlocked(tool.name)) {
121
+ logger.info(TAG, `blocked ${tool.name} (disabled by operator, config v${this.version})`);
122
+ return Promise.resolve(jsonResult(disabledToolResult(tool.name)));
123
+ }
124
+ return originalExecute(...args);
125
+ },
126
+ };
127
+ }
128
+ }