@reefclaw/openclaw-plugin 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 (371) hide show
  1. package/.gitignore +8 -0
  2. package/audit/mode-transition-audit.d.ts +11 -0
  3. package/audit/mode-transition-audit.js +29 -0
  4. package/balance-utils.d.ts +36 -0
  5. package/balance-utils.js +98 -0
  6. package/bridge/bridge.d.ts +109 -0
  7. package/bridge/bridge.js +1036 -0
  8. package/bridge/config.d.ts +43 -0
  9. package/bridge/config.js +176 -0
  10. package/bridge/connector.d.ts +52 -0
  11. package/bridge/connector.js +293 -0
  12. package/bridge/event-replay-buffer.d.ts +43 -0
  13. package/bridge/event-replay-buffer.js +109 -0
  14. package/bridge/gateway/event-parser.d.ts +209 -0
  15. package/bridge/gateway/event-parser.js +793 -0
  16. package/bridge/gateway/gateway-config.d.ts +39 -0
  17. package/bridge/gateway/gateway-config.js +86 -0
  18. package/bridge/gateway/gateway-http-client.d.ts +50 -0
  19. package/bridge/gateway/gateway-http-client.js +165 -0
  20. package/bridge/gateway/gateway-ws-client.d.ts +116 -0
  21. package/bridge/gateway/gateway-ws-client.js +417 -0
  22. package/bridge/gateway/poller.d.ts +146 -0
  23. package/bridge/gateway/poller.js +505 -0
  24. package/bridge/gateway/tool-discovery.d.ts +25 -0
  25. package/bridge/gateway/tool-discovery.js +198 -0
  26. package/bridge/index.d.ts +2 -0
  27. package/bridge/index.js +253 -0
  28. package/bridge/logger.d.ts +2 -0
  29. package/bridge/logger.js +2 -0
  30. package/bridge/provider.d.ts +156 -0
  31. package/bridge/provider.js +2 -0
  32. package/bridge/providers/emergency-commands.d.ts +54 -0
  33. package/bridge/providers/emergency-commands.js +235 -0
  34. package/bridge/providers/gateway.d.ts +322 -0
  35. package/bridge/providers/gateway.js +2302 -0
  36. package/bridge/providers/mock.d.ts +37 -0
  37. package/bridge/providers/mock.js +385 -0
  38. package/bridge/providers/onboarding-commands.d.ts +83 -0
  39. package/bridge/providers/onboarding-commands.js +213 -0
  40. package/bridge/providers/risk-calculator.d.ts +96 -0
  41. package/bridge/providers/risk-calculator.js +369 -0
  42. package/bridge/setup.d.ts +32 -0
  43. package/bridge/setup.js +226 -0
  44. package/bridge/types.d.ts +584 -0
  45. package/bridge/types.js +50 -0
  46. package/bridge/utils/reconnect.d.ts +6 -0
  47. package/bridge/utils/reconnect.js +6 -0
  48. package/bridge/utils/skill-signing.d.ts +51 -0
  49. package/bridge/utils/skill-signing.js +138 -0
  50. package/bridge/utils/skill-version.d.ts +17 -0
  51. package/bridge/utils/skill-version.js +74 -0
  52. package/ccxt/binance-ban-gate.d.ts +47 -0
  53. package/ccxt/binance-ban-gate.js +409 -0
  54. package/ccxt/binance-private.d.ts +325 -0
  55. package/ccxt/binance-private.js +1415 -0
  56. package/ccxt/binance-public.d.ts +18 -0
  57. package/ccxt/binance-public.js +147 -0
  58. package/config/agent-config-client.d.ts +55 -0
  59. package/config/agent-config-client.js +145 -0
  60. package/config/agent-config-poller.d.ts +25 -0
  61. package/config/agent-config-poller.js +100 -0
  62. package/config/brackets-config.d.ts +22 -0
  63. package/config/brackets-config.js +58 -0
  64. package/config/gate-store.d.ts +18 -0
  65. package/config/gate-store.js +61 -0
  66. package/config/plugin-config-io.d.ts +181 -0
  67. package/config/plugin-config-io.js +84 -0
  68. package/config/position-review-config.d.ts +35 -0
  69. package/config/position-review-config.js +105 -0
  70. package/config/tool-gate.d.ts +53 -0
  71. package/config/tool-gate.js +125 -0
  72. package/config/user-data-stream-config.d.ts +85 -0
  73. package/config/user-data-stream-config.js +224 -0
  74. package/connector-supervisor.d.ts +36 -0
  75. package/connector-supervisor.js +149 -0
  76. package/exchange-adapter.d.ts +49 -0
  77. package/exchange-adapter.js +4 -0
  78. package/index.d.ts +30 -0
  79. package/index.js +2030 -0
  80. package/ingest/pending-entry-metadata.d.ts +52 -0
  81. package/ingest/pending-entry-metadata.js +182 -0
  82. package/ingest/position-auto-capture.d.ts +98 -0
  83. package/ingest/position-auto-capture.js +394 -0
  84. package/ingest/position-decisions-client.d.ts +318 -0
  85. package/ingest/position-decisions-client.js +296 -0
  86. package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
  87. package/ingest/reconcile-db-vs-exchange.js +114 -0
  88. package/ingest/reconciler-cleanup.d.ts +37 -0
  89. package/ingest/reconciler-cleanup.js +147 -0
  90. package/ingest/rest-gap-filler.d.ts +191 -0
  91. package/ingest/rest-gap-filler.js +565 -0
  92. package/ingest/touched-symbols-store.d.ts +25 -0
  93. package/ingest/touched-symbols-store.js +96 -0
  94. package/ingest/trade-store-client.d.ts +40 -0
  95. package/ingest/trade-store-client.js +125 -0
  96. package/ingest/ws-ingest.d.ts +43 -0
  97. package/ingest/ws-ingest.js +126 -0
  98. package/learning/setup-family.d.ts +21 -0
  99. package/learning/setup-family.js +103 -0
  100. package/lifecycle/install-signal-handlers.d.ts +33 -0
  101. package/lifecycle/install-signal-handlers.js +112 -0
  102. package/lifecycle/shutdown-coordinator.d.ts +43 -0
  103. package/lifecycle/shutdown-coordinator.js +131 -0
  104. package/live/bracket-id.d.ts +18 -0
  105. package/live/bracket-id.js +81 -0
  106. package/live/bracket-ledger.d.ts +54 -0
  107. package/live/bracket-ledger.js +267 -0
  108. package/live/bracket-manager.d.ts +82 -0
  109. package/live/bracket-manager.js +478 -0
  110. package/live/bracket-params.d.ts +22 -0
  111. package/live/bracket-params.js +124 -0
  112. package/live/bracket-reconciler.d.ts +95 -0
  113. package/live/bracket-reconciler.js +573 -0
  114. package/live/bracket-types.d.ts +102 -0
  115. package/live/bracket-types.js +8 -0
  116. package/live/deposit-tracker.d.ts +62 -0
  117. package/live/deposit-tracker.js +97 -0
  118. package/live/emergency-controls.d.ts +32 -0
  119. package/live/emergency-controls.js +226 -0
  120. package/live/exchange-errors.d.ts +12 -0
  121. package/live/exchange-errors.js +130 -0
  122. package/live/exchange-info-cache.d.ts +35 -0
  123. package/live/exchange-info-cache.js +119 -0
  124. package/live/fact-subscriber.d.ts +78 -0
  125. package/live/fact-subscriber.js +182 -0
  126. package/live/intent-journal.d.ts +42 -0
  127. package/live/intent-journal.js +122 -0
  128. package/live/listen-key-manager.d.ts +70 -0
  129. package/live/listen-key-manager.js +169 -0
  130. package/live/live-adapter.d.ts +264 -0
  131. package/live/live-adapter.js +1665 -0
  132. package/live/live-balance-enricher.d.ts +32 -0
  133. package/live/live-balance-enricher.js +104 -0
  134. package/live/live-bracket-api.d.ts +13 -0
  135. package/live/live-bracket-api.js +20 -0
  136. package/live/live-state-store.d.ts +194 -0
  137. package/live/live-state-store.js +450 -0
  138. package/live/local-signal-service.d.ts +57 -0
  139. package/live/local-signal-service.js +146 -0
  140. package/live/local-strategy-evaluator.d.ts +62 -0
  141. package/live/local-strategy-evaluator.js +127 -0
  142. package/live/microstructure-assembler.d.ts +54 -0
  143. package/live/microstructure-assembler.js +148 -0
  144. package/live/order-poller.d.ts +29 -0
  145. package/live/order-poller.js +125 -0
  146. package/live/position-state-store.d.ts +83 -0
  147. package/live/position-state-store.js +237 -0
  148. package/live/proposal-decision-listener.d.ts +64 -0
  149. package/live/proposal-decision-listener.js +288 -0
  150. package/live/proposal-manager.d.ts +76 -0
  151. package/live/proposal-manager.js +140 -0
  152. package/live/rate-limiter.d.ts +47 -0
  153. package/live/rate-limiter.js +159 -0
  154. package/live/reconciler.d.ts +39 -0
  155. package/live/reconciler.js +175 -0
  156. package/live/setup-buckets.d.ts +7 -0
  157. package/live/setup-buckets.js +33 -0
  158. package/live/slippage-tracker.d.ts +45 -0
  159. package/live/slippage-tracker.js +78 -0
  160. package/live/stop-watcher.d.ts +34 -0
  161. package/live/stop-watcher.js +158 -0
  162. package/live/user-data-active-probe.d.ts +54 -0
  163. package/live/user-data-active-probe.js +180 -0
  164. package/live/user-data-stream-controller.d.ts +200 -0
  165. package/live/user-data-stream-controller.js +579 -0
  166. package/live/user-data-stream-ws.d.ts +22 -0
  167. package/live/user-data-stream-ws.js +63 -0
  168. package/live/user-data-stream.d.ts +243 -0
  169. package/live/user-data-stream.js +704 -0
  170. package/logger.d.ts +2 -0
  171. package/logger.js +2 -0
  172. package/mfe.d.ts +21 -0
  173. package/mfe.js +68 -0
  174. package/onboarding/mode-ladder.d.ts +1 -0
  175. package/onboarding/mode-ladder.js +3 -0
  176. package/onboarding/runtime.d.ts +71 -0
  177. package/onboarding/runtime.js +153 -0
  178. package/openclaw.plugin.json +94 -0
  179. package/package.json +27 -0
  180. package/paper-adapter.d.ts +24 -0
  181. package/paper-adapter.js +91 -0
  182. package/persistence/state-manager.d.ts +42 -0
  183. package/persistence/state-manager.js +164 -0
  184. package/pinned-plan.d.ts +9 -0
  185. package/pinned-plan.js +23 -0
  186. package/risk/pre-trade-check.d.ts +38 -0
  187. package/risk/pre-trade-check.js +345 -0
  188. package/risk/pre-trade-types.d.ts +60 -0
  189. package/risk/pre-trade-types.js +3 -0
  190. package/scripts/assemble.mjs +114 -0
  191. package/shadow/shadow-tracker.d.ts +36 -0
  192. package/shadow/shadow-tracker.js +151 -0
  193. package/shadow/types.d.ts +42 -0
  194. package/shadow/types.js +20 -0
  195. package/shared/indicators-extended.d.ts +52 -0
  196. package/shared/indicators-extended.js +291 -0
  197. package/shared/indicators.d.ts +15 -0
  198. package/shared/indicators.js +114 -0
  199. package/signals/conditions/registry.d.ts +16 -0
  200. package/signals/conditions/registry.js +1274 -0
  201. package/signals/conditions/types.d.ts +1 -0
  202. package/signals/conditions/types.js +4 -0
  203. package/signals/direction-rules.d.ts +3 -0
  204. package/signals/direction-rules.js +24 -0
  205. package/signals/entry-rules.d.ts +6 -0
  206. package/signals/entry-rules.js +33 -0
  207. package/signals/serialize-context.d.ts +4 -0
  208. package/signals/serialize-context.js +39 -0
  209. package/signals/stop-rules.d.ts +3 -0
  210. package/signals/stop-rules.js +48 -0
  211. package/signals/strategy-adapter.d.ts +14 -0
  212. package/signals/strategy-adapter.js +122 -0
  213. package/signals/types.d.ts +1 -0
  214. package/signals/types.js +8 -0
  215. package/simulator/exchange-simulator.d.ts +93 -0
  216. package/simulator/exchange-simulator.js +684 -0
  217. package/simulator/fill-engine.d.ts +53 -0
  218. package/simulator/fill-engine.js +276 -0
  219. package/simulator/paper-market-feed.d.ts +26 -0
  220. package/simulator/paper-market-feed.js +104 -0
  221. package/simulator/realistic-fills.d.ts +59 -0
  222. package/simulator/realistic-fills.js +175 -0
  223. package/simulator/types.d.ts +219 -0
  224. package/simulator/types.js +43 -0
  225. package/skills/reefclaw/SKILL.md +97 -0
  226. package/strategy/builtin-strategies.d.ts +2 -0
  227. package/strategy/builtin-strategies.js +109 -0
  228. package/strategy/condition-registry.d.ts +3 -0
  229. package/strategy/condition-registry.js +153 -0
  230. package/strategy/evaluator.d.ts +67 -0
  231. package/strategy/evaluator.js +93 -0
  232. package/tools/assessment-validation.d.ts +118 -0
  233. package/tools/assessment-validation.js +415 -0
  234. package/tools/attach-brackets.d.ts +34 -0
  235. package/tools/attach-brackets.js +363 -0
  236. package/tools/audit-bracket-protection.d.ts +49 -0
  237. package/tools/audit-bracket-protection.js +527 -0
  238. package/tools/cancel-all-orders.d.ts +7 -0
  239. package/tools/cancel-all-orders.js +5 -0
  240. package/tools/cancel-order.d.ts +10 -0
  241. package/tools/cancel-order.js +14 -0
  242. package/tools/check-position-health.d.ts +46 -0
  243. package/tools/check-position-health.js +194 -0
  244. package/tools/clear-exchange-credentials.d.ts +24 -0
  245. package/tools/clear-exchange-credentials.js +70 -0
  246. package/tools/close-position.d.ts +22 -0
  247. package/tools/close-position.js +449 -0
  248. package/tools/create-order.d.ts +54 -0
  249. package/tools/create-order.js +338 -0
  250. package/tools/exit-gate.d.ts +58 -0
  251. package/tools/exit-gate.js +162 -0
  252. package/tools/fetch-balance.d.ts +5 -0
  253. package/tools/fetch-balance.js +4 -0
  254. package/tools/fetch-ohlcv.d.ts +11 -0
  255. package/tools/fetch-ohlcv.js +8 -0
  256. package/tools/fetch-open-orders.d.ts +7 -0
  257. package/tools/fetch-open-orders.js +4 -0
  258. package/tools/fetch-positions.d.ts +7 -0
  259. package/tools/fetch-positions.js +4 -0
  260. package/tools/fetch-ticker.d.ts +11 -0
  261. package/tools/fetch-ticker.js +5 -0
  262. package/tools/get-agent-profile.d.ts +4 -0
  263. package/tools/get-agent-profile.js +6 -0
  264. package/tools/get-analytics.d.ts +6 -0
  265. package/tools/get-analytics.js +7 -0
  266. package/tools/get-backtest.d.ts +12 -0
  267. package/tools/get-backtest.js +91 -0
  268. package/tools/get-basis.d.ts +7 -0
  269. package/tools/get-basis.js +7 -0
  270. package/tools/get-bracket-config.d.ts +11 -0
  271. package/tools/get-bracket-config.js +24 -0
  272. package/tools/get-cascade-risk.d.ts +7 -0
  273. package/tools/get-cascade-risk.js +8 -0
  274. package/tools/get-crypto-metrics.d.ts +18 -0
  275. package/tools/get-crypto-metrics.js +45 -0
  276. package/tools/get-cvd.d.ts +6 -0
  277. package/tools/get-cvd.js +6 -0
  278. package/tools/get-divergences.d.ts +6 -0
  279. package/tools/get-divergences.js +6 -0
  280. package/tools/get-funding-context.d.ts +6 -0
  281. package/tools/get-funding-context.js +16 -0
  282. package/tools/get-liquidation-levels.d.ts +7 -0
  283. package/tools/get-liquidation-levels.js +7 -0
  284. package/tools/get-liquidation-pulse.d.ts +9 -0
  285. package/tools/get-liquidation-pulse.js +22 -0
  286. package/tools/get-market-breadth.d.ts +6 -0
  287. package/tools/get-market-breadth.js +8 -0
  288. package/tools/get-market-intel.d.ts +19 -0
  289. package/tools/get-market-intel.js +116 -0
  290. package/tools/get-market-structure.d.ts +47 -0
  291. package/tools/get-market-structure.js +198 -0
  292. package/tools/get-my-mined-patterns.d.ts +20 -0
  293. package/tools/get-my-mined-patterns.js +61 -0
  294. package/tools/get-my-proposed-learnings.d.ts +20 -0
  295. package/tools/get-my-proposed-learnings.js +55 -0
  296. package/tools/get-my-recent-reviews.d.ts +22 -0
  297. package/tools/get-my-recent-reviews.js +66 -0
  298. package/tools/get-orderbook.d.ts +21 -0
  299. package/tools/get-orderbook.js +32 -0
  300. package/tools/get-pattern-scan.d.ts +7 -0
  301. package/tools/get-pattern-scan.js +8 -0
  302. package/tools/get-regime.d.ts +6 -0
  303. package/tools/get-regime.js +7 -0
  304. package/tools/get-relevant-learnings.d.ts +21 -0
  305. package/tools/get-relevant-learnings.js +65 -0
  306. package/tools/get-resting-liquidity.d.ts +6 -0
  307. package/tools/get-resting-liquidity.js +11 -0
  308. package/tools/get-risk-scenario.d.ts +29 -0
  309. package/tools/get-risk-scenario.js +47 -0
  310. package/tools/get-risk-summary.d.ts +51 -0
  311. package/tools/get-risk-summary.js +118 -0
  312. package/tools/get-sentiment.d.ts +4 -0
  313. package/tools/get-sentiment.js +6 -0
  314. package/tools/get-session-review.d.ts +7 -0
  315. package/tools/get-session-review.js +8 -0
  316. package/tools/get-setup-detail.d.ts +7 -0
  317. package/tools/get-setup-detail.js +303 -0
  318. package/tools/get-signals.d.ts +15 -0
  319. package/tools/get-signals.js +54 -0
  320. package/tools/get-sizing.d.ts +6 -0
  321. package/tools/get-sizing.js +6 -0
  322. package/tools/get-trade-feedback.d.ts +7 -0
  323. package/tools/get-trade-feedback.js +8 -0
  324. package/tools/get-trade-flow.d.ts +7 -0
  325. package/tools/get-trade-flow.js +7 -0
  326. package/tools/get-volume-analysis.d.ts +21 -0
  327. package/tools/get-volume-analysis.js +74 -0
  328. package/tools/get-volume-profile.d.ts +7 -0
  329. package/tools/get-volume-profile.js +7 -0
  330. package/tools/helpers.d.ts +25 -0
  331. package/tools/helpers.js +38 -0
  332. package/tools/intel-api.d.ts +14 -0
  333. package/tools/intel-api.js +52 -0
  334. package/tools/intel-cache.d.ts +25 -0
  335. package/tools/intel-cache.js +133 -0
  336. package/tools/list-strategies.d.ts +7 -0
  337. package/tools/list-strategies.js +6 -0
  338. package/tools/modify-stop.d.ts +17 -0
  339. package/tools/modify-stop.js +81 -0
  340. package/tools/modify-target.d.ts +17 -0
  341. package/tools/modify-target.js +71 -0
  342. package/tools/propose-learning.d.ts +22 -0
  343. package/tools/propose-learning.js +65 -0
  344. package/tools/query-review-outcomes.d.ts +30 -0
  345. package/tools/query-review-outcomes.js +64 -0
  346. package/tools/query-trades.d.ts +21 -0
  347. package/tools/query-trades.js +37 -0
  348. package/tools/record-position-reviews.d.ts +38 -0
  349. package/tools/record-position-reviews.js +147 -0
  350. package/tools/save-strategy.d.ts +16 -0
  351. package/tools/save-strategy.js +46 -0
  352. package/tools/scan-pairs.d.ts +18 -0
  353. package/tools/scan-pairs.js +220 -0
  354. package/tools/score-setup.d.ts +31 -0
  355. package/tools/score-setup.js +268 -0
  356. package/tools/set-bracket-requirement.d.ts +18 -0
  357. package/tools/set-bracket-requirement.js +81 -0
  358. package/tools/set-exchange-credentials.d.ts +25 -0
  359. package/tools/set-exchange-credentials.js +80 -0
  360. package/tools/set-trading-mode.d.ts +26 -0
  361. package/tools/set-trading-mode.js +135 -0
  362. package/tools/test-exchange-credentials.d.ts +16 -0
  363. package/tools/test-exchange-credentials.js +100 -0
  364. package/tools/toggle-strategy.d.ts +8 -0
  365. package/tools/toggle-strategy.js +8 -0
  366. package/trading-params-cache.d.ts +26 -0
  367. package/trading-params-cache.js +52 -0
  368. package/types.d.ts +110 -0
  369. package/types.js +7 -0
  370. package/util/plugin-paths.d.ts +3 -0
  371. package/util/plugin-paths.js +15 -0
@@ -0,0 +1,198 @@
1
+ // Tool auto-discovery for the OpenClaw gateway.
2
+ // Probes for available CCXT trading tools since OpenClaw has no GET /tools endpoint.
3
+ // Builds a ToolMap mapping logical tool names to discovered actual tool names.
4
+ import { logger } from '../logger.js';
5
+ import { GatewayHttpError } from './gateway-http-client.js';
6
+ const TAG = 'tool-discovery';
7
+ const REQUIRED_TOOLS = ['fetch_ticker', 'fetch_balance'];
8
+ const OPTIONAL_TOOLS = [
9
+ 'fetch_ohlcv',
10
+ 'fetch_positions',
11
+ 'fetch_open_orders',
12
+ 'cancel_all_orders',
13
+ 'cancel_order',
14
+ 'close_position',
15
+ 'create_order',
16
+ 'get_market_structure',
17
+ 'get_crypto_metrics',
18
+ 'get_market_intel',
19
+ 'set_trading_mode',
20
+ 'set_exchange_credentials',
21
+ 'test_exchange_credentials',
22
+ 'clear_exchange_credentials',
23
+ 'get_bracket_config',
24
+ 'set_bracket_requirement',
25
+ ];
26
+ /**
27
+ * Candidate actual tool names to probe for each logical tool.
28
+ * Ordered by likelihood — first match wins.
29
+ */
30
+ const CANDIDATES = {
31
+ fetch_ticker: ['fetch_ticker', 'ccxt_fetch_ticker', 'binance_fetch_ticker', 'get_ticker'],
32
+ fetch_balance: ['fetch_balance', 'ccxt_fetch_balance', 'binance_fetch_balance', 'get_balance'],
33
+ fetch_ohlcv: ['fetch_ohlcv', 'ccxt_fetch_ohlcv'],
34
+ fetch_positions: ['fetch_positions', 'fetch_open_positions', 'ccxt_fetch_positions'],
35
+ fetch_open_orders: ['fetch_open_orders', 'ccxt_fetch_open_orders'],
36
+ cancel_all_orders: ['cancel_all_orders', 'ccxt_cancel_all_orders'],
37
+ cancel_order: ['cancel_order', 'ccxt_cancel_order'],
38
+ close_position: ['close_position', 'close_all_positions', 'ccxt_close_position'],
39
+ create_order: ['create_order', 'ccxt_create_order'],
40
+ get_market_structure: ['get_market_structure'],
41
+ get_crypto_metrics: ['get_crypto_metrics'],
42
+ get_market_intel: ['get_market_intel'],
43
+ set_trading_mode: ['set_trading_mode'],
44
+ set_exchange_credentials: ['set_exchange_credentials'],
45
+ test_exchange_credentials: ['test_exchange_credentials'],
46
+ clear_exchange_credentials: ['clear_exchange_credentials'],
47
+ get_bracket_config: ['get_bracket_config'],
48
+ set_bracket_requirement: ['set_bracket_requirement'],
49
+ };
50
+ /**
51
+ * Test args used when probing each logical tool.
52
+ * Read tools (ticker, balance, etc.) use real args that return data.
53
+ * Write tools (create_order, cancel, close) use args that will be
54
+ * rejected by exchange validation (amount:0, etc.) — we only need
55
+ * to distinguish 400 (tool exists, bad args) from 404 (tool not found).
56
+ */
57
+ const PROBE_ARGS = {
58
+ fetch_ticker: { symbol: 'BTC/USDT' },
59
+ fetch_balance: {},
60
+ fetch_ohlcv: { symbol: 'BTC/USDT', timeframe: '1h', limit: 1 },
61
+ fetch_positions: { symbol: 'BTC/USDT' },
62
+ fetch_open_orders: { symbol: 'BTC/USDT' },
63
+ // For write tools: probe with minimal args. We expect 400 (bad args) = tool exists.
64
+ cancel_all_orders: { symbol: 'BTC/USDT' },
65
+ cancel_order: { id: 'probe-0', symbol: 'BTC/USDT' },
66
+ close_position: { symbol: 'BTC/USDT' },
67
+ create_order: { symbol: 'BTC/USDT', type: 'limit', side: 'buy', amount: 0, price: 0 },
68
+ get_market_structure: { symbol: 'BTC/USDT' },
69
+ get_crypto_metrics: { symbol: 'BTC/USDT' },
70
+ get_market_intel: { category: 'sentiment' },
71
+ // Safe probe args — plugin tools early-return on invalid input without
72
+ // touching disk. `mode: '__probe__'` fails the VALID_MODES check; empty
73
+ // strings fail the length-8 validator in set_exchange_credentials. Both
74
+ // return HTTP 200 with ok:false, which the probe treats as "tool exists".
75
+ set_trading_mode: { mode: '__probe__' },
76
+ set_exchange_credentials: { apiKey: '', secret: '' },
77
+ // test_exchange_credentials: empty strings fail the length check and
78
+ // early-return without hitting Binance.
79
+ test_exchange_credentials: { apiKey: '', secret: '' },
80
+ // clear_exchange_credentials: tool requires confirm:true. Probing without
81
+ // it triggers the safety gate early-return — tool exists, nothing wiped.
82
+ clear_exchange_credentials: {},
83
+ // Bracket-config probes: no-arg read; set with an invalid flag triggers early-return.
84
+ get_bracket_config: {},
85
+ set_bracket_requirement: { flag: '__probe__', value: false },
86
+ };
87
+ // ---- Discovery logic ----
88
+ /**
89
+ * Probe a single candidate tool name. Returns true if the tool exists.
90
+ *
91
+ * Strategy:
92
+ * - 200: tool exists and invocation succeeded
93
+ * - 400: tool exists but args were bad (still counts as found)
94
+ * - 404: tool does not exist
95
+ * - 401: auth error — rethrow (don't mask)
96
+ * - Other: treat as not found
97
+ */
98
+ async function probeCandidate(http, candidateName, args) {
99
+ try {
100
+ await http.invoke(candidateName, args, { timeoutMs: 8_000 });
101
+ return true; // 200 — tool exists and works
102
+ }
103
+ catch (err) {
104
+ if (err instanceof GatewayHttpError) {
105
+ if (err.status === 400)
106
+ return true; // Tool exists, bad args
107
+ if (err.status === 404)
108
+ return false; // Tool not found
109
+ if (err.status === 401)
110
+ throw err; // Auth error — fatal
111
+ }
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * Discover the actual tool name for a logical tool by probing candidates in order.
117
+ * Returns the first candidate that exists, or null if none found.
118
+ */
119
+ async function discoverTool(http, logical) {
120
+ const candidates = CANDIDATES[logical];
121
+ const args = PROBE_ARGS[logical];
122
+ for (const candidate of candidates) {
123
+ logger.debug(TAG, `Probing ${candidate} for ${logical}...`);
124
+ const exists = await probeCandidate(http, candidate, args);
125
+ if (exists) {
126
+ logger.debug(TAG, `Found: ${logical} → ${candidate}`);
127
+ return candidate;
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ /**
133
+ * Discover all available trading tools on the gateway.
134
+ *
135
+ * Probes required tools first, then optional tools in parallel.
136
+ * Fails fast if no required tools are found.
137
+ */
138
+ export async function discoverTools(http) {
139
+ logger.info(TAG, 'Starting tool auto-discovery...');
140
+ const toolMap = {};
141
+ const found = [];
142
+ const missingRequired = [];
143
+ const missingOptional = [];
144
+ // Discover required tools first (sequentially to fail fast on auth errors)
145
+ for (const logical of REQUIRED_TOOLS) {
146
+ const actual = await discoverTool(http, logical);
147
+ if (actual) {
148
+ toolMap[logical] = actual;
149
+ found.push(logical);
150
+ }
151
+ else {
152
+ missingRequired.push(logical);
153
+ }
154
+ }
155
+ // If all required tools are missing, log diagnostic and return (caller decides what to do)
156
+ if (found.length === 0) {
157
+ const tried = REQUIRED_TOOLS
158
+ .map(t => `${t}: [${CANDIDATES[t].join(', ')}]`)
159
+ .join('; ');
160
+ logger.warn(TAG, `No trading tools found. Is a CCXT trading plugin installed? Tried: ${tried}`);
161
+ logger.info(TAG, 'Hint: install a trading plugin with: openclaw skills install reefclaw-paper-trading');
162
+ // Still discover optional tools — some might exist even without required ones
163
+ }
164
+ // Log missing required tools
165
+ for (const logical of missingRequired) {
166
+ logger.error(TAG, `Required tool not found: ${logical} (tried: ${CANDIDATES[logical].join(', ')})`);
167
+ }
168
+ // Discover optional tools in parallel
169
+ const optionalResults = await Promise.allSettled(OPTIONAL_TOOLS.map(async (logical) => {
170
+ const actual = await discoverTool(http, logical);
171
+ return { logical, actual };
172
+ }));
173
+ for (const result of optionalResults) {
174
+ if (result.status === 'fulfilled') {
175
+ const { logical, actual } = result.value;
176
+ if (actual) {
177
+ toolMap[logical] = actual;
178
+ found.push(logical);
179
+ }
180
+ else {
181
+ missingOptional.push(logical);
182
+ }
183
+ }
184
+ else {
185
+ // Promise rejected (shouldn't happen unless auth error propagates)
186
+ logger.warn(TAG, `Discovery failed for optional tool: ${result.reason}`);
187
+ }
188
+ }
189
+ // Log summary
190
+ logger.info(TAG, `Tool discovery complete: ${found.length} found, ${missingRequired.length} required missing, ${missingOptional.length} optional missing`);
191
+ for (const [logical, actual] of Object.entries(toolMap)) {
192
+ logger.info(TAG, ` ${logical} → ${actual}`);
193
+ }
194
+ for (const logical of missingOptional) {
195
+ logger.warn(TAG, `Optional tool not found: ${logical}`);
196
+ }
197
+ return { toolMap, found, missingRequired, missingOptional };
198
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+ // ReefClaw Skill — CLI entry point
3
+ // Usage:
4
+ // tsx src/index.ts --provider mock (standalone testing)
5
+ // tsx src/index.ts --provider gateway (real OpenClaw — not yet implemented)
6
+ // tsx src/index.ts --setup rc_TOKEN --user-id ID (save token to config)
7
+ //
8
+ // Config precedence: CLI args > env vars > OpenClaw config > fallback env > defaults
9
+ // See config.ts for full resolution logic.
10
+ import { readFileSync } from 'fs';
11
+ import { resolve, dirname } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { logger, setLogLevel } from './logger.js';
14
+ import { Bridge } from './bridge.js';
15
+ import { MockProvider } from './providers/mock.js';
16
+ import { GatewayProvider } from './providers/gateway.js';
17
+ import { resolveConfig, ensureGatewayScopeConfigOnStartup } from './config.js';
18
+ import { resolveGatewayConfig, validateGatewayConfig } from './gateway/gateway-config.js';
19
+ import { runSetup } from './setup.js';
20
+ const TAG = 'main';
21
+ // ---- Load .env file (skill/.env only) ----
22
+ function loadEnvFile() {
23
+ const __dirname = dirname(fileURLToPath(import.meta.url));
24
+ const envPath = resolve(__dirname, '..', '.env');
25
+ try {
26
+ const content = readFileSync(envPath, 'utf-8');
27
+ for (const line of content.split('\n')) {
28
+ const trimmed = line.trim();
29
+ if (!trimmed || trimmed.startsWith('#'))
30
+ continue;
31
+ const eqIdx = trimmed.indexOf('=');
32
+ if (eqIdx === -1)
33
+ continue;
34
+ const key = trimmed.slice(0, eqIdx).trim();
35
+ const value = trimmed.slice(eqIdx + 1).trim();
36
+ if (!process.env[key])
37
+ process.env[key] = value;
38
+ }
39
+ logger.debug(TAG, `Loaded env from ${envPath}`);
40
+ }
41
+ catch {
42
+ // File not found — not an error
43
+ }
44
+ }
45
+ function parseArgs() {
46
+ const args = process.argv.slice(2);
47
+ const cli = { provider: 'mock' };
48
+ const gateway = {};
49
+ for (let i = 0; i < args.length; i++) {
50
+ const arg = args[i];
51
+ const next = args[i + 1];
52
+ switch (arg) {
53
+ case '--provider':
54
+ case '-p':
55
+ if (next === 'mock' || next === 'gateway') {
56
+ cli.provider = next;
57
+ i++;
58
+ }
59
+ else {
60
+ console.error(`Invalid provider: ${next}. Use "mock" or "gateway".`);
61
+ process.exit(1);
62
+ }
63
+ break;
64
+ case '--token':
65
+ case '-t':
66
+ cli.token = next;
67
+ i++;
68
+ break;
69
+ case '--user-id':
70
+ case '-u':
71
+ cli.userId = next;
72
+ i++;
73
+ break;
74
+ case '--relay-url':
75
+ case '-r':
76
+ cli.relayUrl = next;
77
+ i++;
78
+ break;
79
+ case '--gateway-url':
80
+ gateway.gatewayUrl = next;
81
+ i++;
82
+ break;
83
+ case '--gateway-token':
84
+ gateway.gatewayToken = next;
85
+ i++;
86
+ break;
87
+ case '--symbol':
88
+ gateway.symbol = next;
89
+ i++;
90
+ break;
91
+ case '--log-level':
92
+ case '-l':
93
+ if (['debug', 'info', 'warn', 'error'].includes(next)) {
94
+ cli.logLevel = next;
95
+ i++;
96
+ }
97
+ break;
98
+ case '--setup':
99
+ case '-s':
100
+ // --setup with optional token as next arg
101
+ if (next && !next.startsWith('-')) {
102
+ cli.setup = next;
103
+ i++;
104
+ }
105
+ else {
106
+ cli.setup = true;
107
+ }
108
+ break;
109
+ case '--help':
110
+ case '-h':
111
+ printUsage();
112
+ process.exit(0);
113
+ }
114
+ }
115
+ return { cli, gateway };
116
+ }
117
+ function printUsage() {
118
+ console.log(`
119
+ ReefClaw Skill — Bridge between OpenClaw and ReefClaw relay
120
+
121
+ Usage:
122
+ tsx src/index.ts [options]
123
+
124
+ Options:
125
+ --provider, -p <mock|gateway> Provider type (default: mock)
126
+ --token, -t <token> Connection token (or REEFCLAW_TOKEN env)
127
+ --user-id, -u <id> User ID (or REEFCLAW_USER_ID env)
128
+ --relay-url, -r <url> Relay URL (default: wss://reefclaw.radunlupsa.partykit.dev)
129
+ --gateway-url <url> OpenClaw gateway URL (or OPENCLAW_GATEWAY_URL env)
130
+ --gateway-token <token> OpenClaw gateway token (or OPENCLAW_GATEWAY_TOKEN env)
131
+ --symbol <symbol> Trading symbol (default: BTC/USDT, or REEFCLAW_SYMBOL env)
132
+ --log-level, -l <level> Log level: debug, info, warn, error (default: info)
133
+ --setup, -s [token] Run setup flow (validate token, test connection, save to config)
134
+ --help, -h Show this help
135
+
136
+ Relay config resolution (highest priority first):
137
+ 1. CLI arguments (--token, --user-id, --relay-url)
138
+ 2. Environment variables (REEFCLAW_TOKEN, REEFCLAW_USER_ID, REEFCLAW_RELAY_URL)
139
+ 3. OpenClaw config file (~/.openclaw/openclaw.json → skills.entries.reefclaw)
140
+ 4. Fallback env vars (MOCK_TOKEN, USER_ID)
141
+ 5. Defaults (relay URL → wss://reefclaw.radunlupsa.partykit.dev)
142
+
143
+ Gateway config resolution (for --provider gateway):
144
+ 1. CLI arguments (--gateway-url, --gateway-token, --symbol)
145
+ 2. Environment variables (OPENCLAW_GATEWAY_URL, OPENCLAW_GATEWAY_TOKEN, REEFCLAW_SYMBOL)
146
+ 3. OpenClaw config file (~/.openclaw/openclaw.json → gateway.auth.token, gateway.port)
147
+ 4. Defaults (http://localhost:18789, BTC/USDT)
148
+ `);
149
+ }
150
+ // ---- Main ----
151
+ async function main() {
152
+ loadEnvFile();
153
+ ensureGatewayScopeConfigOnStartup();
154
+ const { cli: args, gateway: gatewayArgs } = parseArgs();
155
+ if (args.logLevel) {
156
+ setLogLevel(args.logLevel);
157
+ }
158
+ // Handle --setup flow
159
+ if (args.setup !== undefined) {
160
+ const setupToken = typeof args.setup === 'string' ? args.setup : undefined;
161
+ await runSetup(setupToken, args.userId);
162
+ process.exit(0);
163
+ }
164
+ // Resolve config
165
+ const { token, userId, relayUrl } = resolveConfig(args);
166
+ if (!token || !userId) {
167
+ console.error('');
168
+ console.error(' ReefClaw: Missing configuration');
169
+ console.error(' ================================');
170
+ console.error('');
171
+ if (!token) {
172
+ console.error(' No connection token found.');
173
+ }
174
+ if (!userId) {
175
+ console.error(' No user ID found.');
176
+ }
177
+ console.error('');
178
+ console.error(' Quick setup:');
179
+ console.error(' node dist/index.js --setup rc_YOUR_TOKEN --user-id YOUR_USER_ID');
180
+ console.error('');
181
+ console.error(' Or set environment variables:');
182
+ console.error(' REEFCLAW_TOKEN=rc_xxx REEFCLAW_USER_ID=xxx node dist/index.js');
183
+ console.error('');
184
+ console.error(' Or paste the connect message from the onboarding page to your agent:');
185
+ console.error(' "Connect my agent to ReefClaw. Save these to my reefclaw skill config:');
186
+ console.error(' token: rc_... userId: <uuid> relayUrl: wss://..."');
187
+ console.error(' (A token alone is NOT enough — the userId is required to reach the relay.)');
188
+ console.error('');
189
+ console.error(' Get the full connect message at https://reefclaw.com/onboarding');
190
+ console.error('');
191
+ process.exit(1);
192
+ }
193
+ // Create provider
194
+ let provider;
195
+ if (args.provider === 'mock') {
196
+ logger.info(TAG, 'Using MockProvider');
197
+ provider = new MockProvider();
198
+ }
199
+ else {
200
+ // Resolve and validate gateway config for real OpenClaw connection
201
+ const gwResolved = resolveGatewayConfig(gatewayArgs);
202
+ const gwConfig = validateGatewayConfig(gwResolved);
203
+ if (!gwConfig) {
204
+ console.error('');
205
+ console.error(' ReefClaw: Missing gateway token');
206
+ console.error(' ================================');
207
+ console.error('');
208
+ console.error(' No OpenClaw gateway token found. The token is read from:');
209
+ console.error(' 1. --gateway-token CLI arg');
210
+ console.error(' 2. OPENCLAW_GATEWAY_TOKEN env var');
211
+ console.error(' 3. ~/.openclaw/openclaw.json → gateway.auth.token');
212
+ console.error('');
213
+ console.error(' Make sure OpenClaw is configured and running.');
214
+ console.error('');
215
+ process.exit(1);
216
+ }
217
+ // Pass connection token so GatewayProvider can authenticate with intelligence service
218
+ gwConfig.connectionToken = token;
219
+ logger.info(TAG, `Using GatewayProvider (url=${gwConfig.gatewayUrl}, symbol=${gwConfig.symbol})`);
220
+ provider = new GatewayProvider(gwConfig);
221
+ }
222
+ // Create bridge
223
+ const connectorConfig = {
224
+ relayUrl,
225
+ userId,
226
+ token,
227
+ };
228
+ const bridge = new Bridge(provider, connectorConfig);
229
+ // Handle graceful shutdown
230
+ let shuttingDown = false;
231
+ async function shutdown(signal) {
232
+ if (shuttingDown)
233
+ return;
234
+ shuttingDown = true;
235
+ logger.info(TAG, `Received ${signal}, shutting down...`);
236
+ // Drain in-flight trade reports before stopping (prevents data loss during kill/flatten)
237
+ if ('drainReports' in provider && typeof provider.drainReports === 'function') {
238
+ try {
239
+ await provider.drainReports();
240
+ }
241
+ catch { /* best-effort */ }
242
+ }
243
+ bridge.stop();
244
+ // Allow 1s for final cleanup before force exit
245
+ setTimeout(() => process.exit(0), 1000);
246
+ }
247
+ process.on('SIGINT', () => void shutdown('SIGINT').catch(() => process.exit(1)));
248
+ process.on('SIGTERM', () => void shutdown('SIGTERM').catch(() => process.exit(1)));
249
+ // Start
250
+ logger.info(TAG, `Starting ReefClaw skill (provider=${args.provider}, relay=${relayUrl})`);
251
+ bridge.start();
252
+ }
253
+ main();
@@ -0,0 +1,2 @@
1
+ export type { LogLevel } from '@reefclaw/shared';
2
+ export { logger, setLogLevel, formatError } from '@reefclaw/shared';
@@ -0,0 +1,2 @@
1
+ // Re-export from @reefclaw/shared (canonical source of truth).
2
+ export { logger, setLogLevel, formatError } from '@reefclaw/shared';
@@ -0,0 +1,156 @@
1
+ import type { EmergencyAction, ReconciliationSnapshot, TickerData, CandleData, OrderUpdatePayload, AgentStateData, RiskUpdatePayload, ChatMessage, MarketStructureData, CryptoMetricsData, VolumeAnalysisData, TradeJournalEntry, RegimeData, SignalData, MissionData, AnalyticsData, ShadowComparisonData, TradingModeData, DecisionTraceData } from './types.js';
2
+ import type { TradingMode } from '@reefclaw/shared';
3
+ /** Fill error data emitted when a limit fill fails */
4
+ export interface FillErrorData {
5
+ orderId: string;
6
+ symbol: string;
7
+ error: string;
8
+ timestamp: string;
9
+ }
10
+ /** Events emitted by the provider to be forwarded to the relay */
11
+ export interface ProviderEvents {
12
+ ticker: (data: TickerData) => void;
13
+ candle: (data: CandleData) => void;
14
+ orderUpdate: (data: OrderUpdatePayload) => void;
15
+ agentState: (data: AgentStateData) => void;
16
+ riskUpdate: (data: RiskUpdatePayload) => void;
17
+ chatMessage: (data: {
18
+ message: ChatMessage;
19
+ }) => void;
20
+ /** Streaming chat: first chunk — creates the in-progress message */
21
+ chatMessageStart: (data: {
22
+ id: string;
23
+ runId: string;
24
+ timestamp: string;
25
+ }) => void;
26
+ /** Streaming chat: incremental text delta */
27
+ chatMessageChunk: (data: {
28
+ id: string;
29
+ delta: string;
30
+ }) => void;
31
+ /** Streaming chat: generation complete — final content for DB persistence */
32
+ chatMessageEnd: (data: {
33
+ id: string;
34
+ content: string;
35
+ }) => void;
36
+ /** Streaming chat: keep-alive during tool execution — prevents webapp timeout */
37
+ chatStreamingKeepAlive: (data: {
38
+ id: string;
39
+ toolName: string;
40
+ }) => void;
41
+ marketStructure: (data: MarketStructureData) => void;
42
+ cryptoMetrics: (data: CryptoMetricsData) => void;
43
+ volumeAnalysis: (data: VolumeAnalysisData) => void;
44
+ tradeJournal: (data: TradeJournalEntry) => void;
45
+ /** Regime classification from intelligence service */
46
+ regimeUpdate: (data: RegimeData) => void;
47
+ /** Signal engine updates from intelligence service */
48
+ signalUpdate: (data: SignalData) => void;
49
+ /** Trade mission updates from intelligence service */
50
+ missionUpdate: (data: MissionData) => void;
51
+ /** Edge analytics updates from intelligence service */
52
+ analyticsUpdate: (data: AnalyticsData) => void;
53
+ /** Background fill error (e.g., limit order fill failed due to insufficient balance) */
54
+ fillError: (data: FillErrorData) => void;
55
+ /** Shadow comparison event — paper vs live fill estimate (Phase 9b) */
56
+ shadowComparison: (data: ShadowComparisonData) => void;
57
+ /** Trading mode update (Phase 9b) */
58
+ tradingModeUpdate: (data: TradingModeData) => void;
59
+ /** Decision trace update (Phase 9c) */
60
+ decisionTraceUpdate: (data: DecisionTraceData) => void;
61
+ }
62
+ export type ProviderEventName = keyof ProviderEvents;
63
+ /**
64
+ * Adapter interface between OpenClaw (or mock) and the ReefClaw relay.
65
+ * Implementations emit events via the on/off listener pattern.
66
+ */
67
+ export interface OpenClawProvider {
68
+ /** Start the provider (begin emitting events) */
69
+ start(): void;
70
+ /** Stop the provider (clean up timers, connections) */
71
+ stop(): void;
72
+ /** Execute an emergency command */
73
+ executeEmergency(action: EmergencyAction): Promise<{
74
+ action: string;
75
+ executed: boolean;
76
+ timestamp: string;
77
+ }>;
78
+ /** Handle an incoming chat message from the operator */
79
+ handleChat(content: string): Promise<{
80
+ received: boolean;
81
+ error?: string;
82
+ }>;
83
+ /** Close a specific position by symbol (non-emergency, single-symbol close) */
84
+ closePosition(symbol: string): Promise<{
85
+ closed: boolean;
86
+ symbol: string;
87
+ error?: string;
88
+ }>;
89
+ /** Operator-only: set the trading mode. Plugin enforces the ladder. */
90
+ setTradingMode?(mode: TradingMode, acknowledged?: boolean): Promise<{
91
+ ok: boolean;
92
+ message: string;
93
+ previousMode: TradingMode;
94
+ mode: TradingMode;
95
+ readiness: string;
96
+ reason?: string;
97
+ }>;
98
+ /** Operator-only: set Binance API credentials. The raw secret is written
99
+ * to the plugin-local config file and never retained by the skill. */
100
+ setExchangeCredentials?(apiKey: string, secret: string, testnet?: boolean): Promise<{
101
+ ok: boolean;
102
+ message: string;
103
+ fingerprint: string;
104
+ reconnected: boolean;
105
+ mode: TradingMode;
106
+ readiness: string;
107
+ }>;
108
+ /** Operator-only: verify Binance API credentials with a transient
109
+ * read-only call. Nothing is persisted. */
110
+ testExchangeCredentials?(apiKey: string, secret: string, testnet?: boolean): Promise<{
111
+ ok: boolean;
112
+ message: string;
113
+ fingerprint: string;
114
+ canReadBalance: boolean;
115
+ canReadPositions: boolean;
116
+ balanceUSDT: number | null;
117
+ testnet: boolean;
118
+ errors: string[];
119
+ }>;
120
+ /** Operator-only: remove stored credentials from the plugin config and
121
+ * de-escalate to PAPER mode if currently running in a live mode. */
122
+ clearExchangeCredentials?(): Promise<{
123
+ ok: boolean;
124
+ message: string;
125
+ modeBefore: TradingMode;
126
+ mode: TradingMode;
127
+ rolledBackToPaper: boolean;
128
+ readiness: string;
129
+ }>;
130
+ /** Operator-only: read current bracket-orders config (mode + require flags). */
131
+ getBracketConfig?(): Promise<{
132
+ ok: boolean;
133
+ message?: string;
134
+ mode: 'off' | 'observe' | 'enforce';
135
+ requireStopLoss: boolean;
136
+ requireTakeProfit: boolean;
137
+ }>;
138
+ /** Operator-only: flip requireStopLoss or requireTakeProfit. Returns a
139
+ * warning string when a flag goes off so the dashboard can render the
140
+ * confirmation banner without hardcoding copy. */
141
+ setBracketRequirement?(flag: 'requireStopLoss' | 'requireTakeProfit', value: boolean): Promise<{
142
+ ok: boolean;
143
+ flag: 'requireStopLoss' | 'requireTakeProfit';
144
+ previousValue: boolean;
145
+ value: boolean;
146
+ warning?: string;
147
+ error?: string;
148
+ message?: string;
149
+ }>;
150
+ /** Get a full reconciliation snapshot */
151
+ getSnapshot(): Promise<ReconciliationSnapshot>;
152
+ /** Register an event listener */
153
+ on<E extends ProviderEventName>(event: E, listener: ProviderEvents[E]): void;
154
+ /** Remove an event listener */
155
+ off<E extends ProviderEventName>(event: E, listener: ProviderEvents[E]): void;
156
+ }
@@ -0,0 +1,2 @@
1
+ // OpenClawProvider interface — adapter pattern for mock vs real gateway
2
+ export {};
@@ -0,0 +1,54 @@
1
+ import type { GatewayHttpClient } from '../gateway/gateway-http-client.js';
2
+ import type { ToolMap } from '../gateway/tool-discovery.js';
3
+ import type { OrderData } from '../types.js';
4
+ import type { CcxtPosition } from '../gateway/poller.js';
5
+ export interface EmergencyResult {
6
+ action: string;
7
+ executed: boolean;
8
+ timestamp: string;
9
+ details?: string;
10
+ }
11
+ export type AgentMode = 'ACTIVE' | 'PAUSED' | 'STOPPED' | 'ERROR';
12
+ export interface EmergencyContext {
13
+ http: GatewayHttpClient | null;
14
+ toolMap: ToolMap;
15
+ symbol: string;
16
+ }
17
+ /**
18
+ * Kill: stop the agent and cancel WORKING orders, while PRESERVING protective
19
+ * brackets. A protective order (exchange-side STOP_MARKET / TAKE_PROFIT_MARKET)
20
+ * is the only thing guarding an open position once the agent is halted (nothing
21
+ * will re-attach a stop). Kill cancels only the agent's working orders (pending
22
+ * entries / adds), PORTFOLIO-WIDE, and keeps every protective leg in place. To
23
+ * actually exit a position, use Flatten.
24
+ *
25
+ * Bracket preservation is defence-in-depth: the plugin's `cancelAllOrders`
26
+ * already skips ReefClaw-cid brackets, so the old per-symbol kill never stripped
27
+ * a ReefClaw bracket — this skill-side `protective` filter is BROADER (it also
28
+ * preserves externally-placed / non-ReefClaw-cid stops) and portfolio-wide.
29
+ *
30
+ * Caller must set agentMode = 'STOPPED' after this returns, and should pass a
31
+ * FRESH all-symbols order snapshot (see the gateway wrapper).
32
+ */
33
+ export declare function executeKill(ctx: EmergencyContext, openOrders: OrderData[]): Promise<EmergencyResult>;
34
+ /**
35
+ * Flatten: close all open positions at market.
36
+ * Caller must set agentMode = 'STOPPED' after this returns.
37
+ */
38
+ export declare function executeFlatten(ctx: EmergencyContext, cachedPositions: CcxtPosition[]): Promise<EmergencyResult>;
39
+ /**
40
+ * Pause: prevent new entries, keep existing positions.
41
+ * Returns the new agent mode if the transition is valid.
42
+ */
43
+ export declare function executePause(currentMode: AgentMode): {
44
+ result: EmergencyResult;
45
+ newMode: AgentMode;
46
+ };
47
+ /**
48
+ * Resume: re-enable entries.
49
+ * Returns the new agent mode if the transition is valid.
50
+ */
51
+ export declare function executeResume(currentMode: AgentMode): {
52
+ result: EmergencyResult;
53
+ newMode: AgentMode;
54
+ };