@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,39 @@
1
+ export interface GatewayConfig {
2
+ /** Full gateway URL, e.g. "http://localhost:18789" */
3
+ gatewayUrl: string;
4
+ /** Auth token for gateway API + WebSocket */
5
+ gatewayToken: string;
6
+ /** Trading symbol, e.g. "BTC/USDT" */
7
+ symbol: string;
8
+ /** Intelligence service URL (optional — regime classification) */
9
+ intelligenceUrl?: string;
10
+ /** Connection token for intelligence service auth */
11
+ connectionToken?: string;
12
+ }
13
+ /** CLI args specific to gateway provider */
14
+ export interface GatewayCliArgs {
15
+ gatewayUrl?: string;
16
+ gatewayToken?: string;
17
+ symbol?: string;
18
+ intelligenceUrl?: string;
19
+ }
20
+ /**
21
+ * Resolve gateway connection config with priority:
22
+ * 1. CLI args (--gateway-url, --gateway-token, --symbol)
23
+ * 2. Env vars (OPENCLAW_GATEWAY_URL, OPENCLAW_GATEWAY_TOKEN, REEFCLAW_SYMBOL)
24
+ * 3. OpenClaw config file (~/.openclaw/openclaw.json)
25
+ * 4. Defaults (localhost:18789, BTC/USDT)
26
+ *
27
+ * Returns null for gatewayToken if it can't be resolved (caller must handle).
28
+ */
29
+ export declare function resolveGatewayConfig(args: GatewayCliArgs): {
30
+ gatewayUrl: string;
31
+ gatewayToken: string | null;
32
+ symbol: string;
33
+ intelligenceUrl: string | null;
34
+ };
35
+ /**
36
+ * Validate that the resolved config has all required fields.
37
+ * Returns a fully typed GatewayConfig or null if token is missing.
38
+ */
39
+ export declare function validateGatewayConfig(resolved: ReturnType<typeof resolveGatewayConfig>): GatewayConfig | null;
@@ -0,0 +1,86 @@
1
+ // Gateway config auto-discovery for OpenClaw integration.
2
+ // Reads gateway connection details from ~/.openclaw/openclaw.json (JSON5).
3
+ // Config priority: CLI args > env vars > openclaw.json > defaults.
4
+ import { readFileSync } from 'fs';
5
+ import { join } from 'path';
6
+ import { homedir } from 'os';
7
+ import JSON5 from 'json5';
8
+ import { logger } from '../logger.js';
9
+ const TAG = 'gateway-config';
10
+ const DEFAULT_GATEWAY_PORT = 18789;
11
+ const DEFAULT_GATEWAY_HOST = 'localhost';
12
+ const DEFAULT_SYMBOL = 'BTC/USDT';
13
+ // ---- Read OpenClaw config file ----
14
+ function getConfigPath() {
15
+ return process.env.OPENCLAW_CONFIG_PATH
16
+ || join(homedir(), '.openclaw', 'openclaw.json');
17
+ }
18
+ function readOpenClawJson() {
19
+ const configPath = getConfigPath();
20
+ try {
21
+ const raw = readFileSync(configPath, 'utf-8');
22
+ const config = JSON5.parse(raw);
23
+ logger.debug(TAG, `Read OpenClaw config from ${configPath}`);
24
+ return config;
25
+ }
26
+ catch {
27
+ logger.debug(TAG, `Could not read OpenClaw config from ${configPath}`);
28
+ return null;
29
+ }
30
+ }
31
+ // ---- Resolve gateway config ----
32
+ /**
33
+ * Resolve gateway connection config with priority:
34
+ * 1. CLI args (--gateway-url, --gateway-token, --symbol)
35
+ * 2. Env vars (OPENCLAW_GATEWAY_URL, OPENCLAW_GATEWAY_TOKEN, REEFCLAW_SYMBOL)
36
+ * 3. OpenClaw config file (~/.openclaw/openclaw.json)
37
+ * 4. Defaults (localhost:18789, BTC/USDT)
38
+ *
39
+ * Returns null for gatewayToken if it can't be resolved (caller must handle).
40
+ */
41
+ export function resolveGatewayConfig(args) {
42
+ const ocConfig = readOpenClawJson();
43
+ // --- Gateway URL ---
44
+ // CLI > env > construct from openclaw.json port > default
45
+ const port = ocConfig?.gateway?.port ?? DEFAULT_GATEWAY_PORT;
46
+ const defaultUrl = `http://${DEFAULT_GATEWAY_HOST}:${port}`;
47
+ const gatewayUrl = args.gatewayUrl
48
+ || process.env.OPENCLAW_GATEWAY_URL
49
+ || defaultUrl;
50
+ // --- Gateway token ---
51
+ // CLI > env > openclaw.json gateway.auth.token
52
+ const fileToken = ocConfig?.gateway?.auth?.token ?? null;
53
+ const gatewayToken = args.gatewayToken
54
+ || process.env.OPENCLAW_GATEWAY_TOKEN
55
+ || fileToken;
56
+ if (fileToken && !args.gatewayToken && !process.env.OPENCLAW_GATEWAY_TOKEN) {
57
+ logger.info(TAG, 'Using gateway token from OpenClaw config');
58
+ }
59
+ // --- Symbol ---
60
+ // CLI > env > default
61
+ const symbol = args.symbol
62
+ || process.env.REEFCLAW_SYMBOL
63
+ || DEFAULT_SYMBOL;
64
+ if (!gatewayToken) {
65
+ logger.warn(TAG, 'Gateway token not found in CLI args, env vars, or OpenClaw config');
66
+ }
67
+ // --- Intelligence URL ---
68
+ // CLI > env > default
69
+ const intelligenceUrl = args.intelligenceUrl
70
+ || process.env.REEFCLAW_INTELLIGENCE_URL
71
+ || null;
72
+ if (intelligenceUrl) {
73
+ logger.info(TAG, `Intelligence service: ${intelligenceUrl}`);
74
+ }
75
+ logger.debug(TAG, `Resolved: url=${gatewayUrl}, token=${gatewayToken ? '***' : '(none)'}, symbol=${symbol}`);
76
+ return { gatewayUrl, gatewayToken, symbol, intelligenceUrl };
77
+ }
78
+ /**
79
+ * Validate that the resolved config has all required fields.
80
+ * Returns a fully typed GatewayConfig or null if token is missing.
81
+ */
82
+ export function validateGatewayConfig(resolved) {
83
+ if (!resolved.gatewayToken)
84
+ return null;
85
+ return resolved;
86
+ }
@@ -0,0 +1,50 @@
1
+ import type { GatewayConfig } from './gateway-config.js';
2
+ export declare class GatewayHttpError extends Error {
3
+ readonly status: number;
4
+ readonly body?: unknown | undefined;
5
+ constructor(message: string, status: number, body?: unknown | undefined);
6
+ }
7
+ /** Parsed result of a successful tool invocation */
8
+ export interface InvokeResult<T = unknown> {
9
+ data: T;
10
+ raw: string;
11
+ }
12
+ export interface HealthResponse {
13
+ ok: boolean;
14
+ [key: string]: unknown;
15
+ }
16
+ export declare class GatewayHttpClient {
17
+ private readonly baseUrl;
18
+ private token;
19
+ constructor(config: Pick<GatewayConfig, 'gatewayUrl' | 'gatewayToken'>);
20
+ /**
21
+ * Update the auth token — called after WS handshake obtains a device token.
22
+ * The gateway issues device tokens during the WS connect handshake.
23
+ * REST API calls must use this device token, not the raw gateway auth token.
24
+ */
25
+ setToken(token: string): void;
26
+ /**
27
+ * Invoke a tool on the OpenClaw gateway.
28
+ *
29
+ * Handles the nested response envelope:
30
+ * { ok, result: { content: [{ type: "text", text: "<JSON-string>" }] } }
31
+ *
32
+ * The actual tool result is JSON-stringified inside result.content[0].text,
33
+ * so we parse twice: once for the outer envelope, once for the inner text.
34
+ */
35
+ invoke<T = unknown>(tool: string, args: Record<string, unknown>, opts?: {
36
+ timeoutMs?: number;
37
+ sessionKey?: string;
38
+ action?: string;
39
+ }): Promise<InvokeResult<T>>;
40
+ /**
41
+ * Invoke a tool with emergency timeout (5s).
42
+ * Convenience wrapper for kill/flatten operations that bypass the agent.
43
+ */
44
+ invokeEmergency<T = unknown>(tool: string, args: Record<string, unknown>): Promise<InvokeResult<T>>;
45
+ /**
46
+ * Check gateway health via GET /health.
47
+ */
48
+ health(timeoutMs?: number): Promise<HealthResponse>;
49
+ private describeHttpError;
50
+ }
@@ -0,0 +1,165 @@
1
+ // HTTP client for the OpenClaw gateway REST API.
2
+ // Wraps POST /tools/invoke with double-envelope unwrapping and GET /health.
3
+ import { logger } from '../logger.js';
4
+ const TAG = 'gateway-http';
5
+ // ---- Timeout defaults ----
6
+ const DEFAULT_TIMEOUT_MS = 10_000;
7
+ const EMERGENCY_TIMEOUT_MS = 5_000;
8
+ // ---- Error types ----
9
+ export class GatewayHttpError extends Error {
10
+ status;
11
+ body;
12
+ constructor(message, status, body) {
13
+ super(message);
14
+ this.status = status;
15
+ this.body = body;
16
+ this.name = 'GatewayHttpError';
17
+ }
18
+ }
19
+ // ---- Client ----
20
+ export class GatewayHttpClient {
21
+ baseUrl;
22
+ token;
23
+ constructor(config) {
24
+ // Convert ws:// → http:// and wss:// → https:// for HTTP requests
25
+ const url = config.gatewayUrl
26
+ .replace(/^wss:\/\//, 'https://')
27
+ .replace(/^ws:\/\//, 'http://')
28
+ .replace(/\/$/, '');
29
+ this.baseUrl = url;
30
+ this.token = config.gatewayToken;
31
+ }
32
+ /**
33
+ * Update the auth token — called after WS handshake obtains a device token.
34
+ * The gateway issues device tokens during the WS connect handshake.
35
+ * REST API calls must use this device token, not the raw gateway auth token.
36
+ */
37
+ setToken(token) {
38
+ this.token = token;
39
+ logger.info(TAG, 'HTTP client token updated (device token from WS handshake)');
40
+ }
41
+ /**
42
+ * Invoke a tool on the OpenClaw gateway.
43
+ *
44
+ * Handles the nested response envelope:
45
+ * { ok, result: { content: [{ type: "text", text: "<JSON-string>" }] } }
46
+ *
47
+ * The actual tool result is JSON-stringified inside result.content[0].text,
48
+ * so we parse twice: once for the outer envelope, once for the inner text.
49
+ */
50
+ async invoke(tool, args, opts) {
51
+ const url = `${this.baseUrl}/tools/invoke`;
52
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
53
+ const body = { tool, args };
54
+ if (opts?.sessionKey)
55
+ body.sessionKey = opts.sessionKey;
56
+ if (opts?.action)
57
+ body.action = opts.action;
58
+ logger.debug(TAG, `POST ${url} tool=${tool} args_keys=[${Object.keys(args).join(',')}]`);
59
+ const controller = new AbortController();
60
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
61
+ let res;
62
+ try {
63
+ res = await fetch(url, {
64
+ method: 'POST',
65
+ headers: {
66
+ 'Content-Type': 'application/json',
67
+ 'Authorization': `Bearer ${this.token}`,
68
+ },
69
+ body: JSON.stringify(body),
70
+ signal: controller.signal,
71
+ });
72
+ }
73
+ catch (err) {
74
+ if (err instanceof Error && err.name === 'AbortError') {
75
+ throw new GatewayHttpError(`Request timed out after ${timeoutMs}ms`, 0);
76
+ }
77
+ throw new GatewayHttpError(`Network error: ${err instanceof Error ? err.message : String(err)}`, 0);
78
+ }
79
+ finally {
80
+ clearTimeout(timer);
81
+ }
82
+ // Handle HTTP error codes
83
+ if (!res.ok) {
84
+ let errorBody;
85
+ try {
86
+ errorBody = await res.json();
87
+ }
88
+ catch {
89
+ errorBody = await res.text().catch(() => null);
90
+ }
91
+ const msg = this.describeHttpError(res.status, tool, errorBody);
92
+ throw new GatewayHttpError(msg, res.status, errorBody);
93
+ }
94
+ // Parse outer envelope
95
+ const envelope = (await res.json());
96
+ if (!envelope.ok) {
97
+ throw new GatewayHttpError(`Tool invoke failed: ${envelope.error?.message ?? 'unknown error'}`, res.status, envelope);
98
+ }
99
+ // Unwrap nested envelope: result.content[0].text contains JSON string
100
+ const textContent = envelope.result?.content?.[0]?.text;
101
+ if (textContent === undefined) {
102
+ throw new GatewayHttpError('Unexpected response format: missing result.content[0].text', res.status, envelope);
103
+ }
104
+ // Parse the inner JSON string
105
+ let data;
106
+ try {
107
+ data = JSON.parse(textContent);
108
+ }
109
+ catch {
110
+ throw new GatewayHttpError('Failed to parse inner JSON from result.content[0].text', res.status, { raw: textContent });
111
+ }
112
+ logger.debug(TAG, `Tool ${tool} returned successfully`);
113
+ return { data, raw: textContent };
114
+ }
115
+ /**
116
+ * Invoke a tool with emergency timeout (5s).
117
+ * Convenience wrapper for kill/flatten operations that bypass the agent.
118
+ */
119
+ async invokeEmergency(tool, args) {
120
+ return this.invoke(tool, args, { timeoutMs: EMERGENCY_TIMEOUT_MS });
121
+ }
122
+ /**
123
+ * Check gateway health via GET /health.
124
+ */
125
+ async health(timeoutMs = DEFAULT_TIMEOUT_MS) {
126
+ const url = `${this.baseUrl}/health`;
127
+ logger.debug(TAG, `GET ${url}`);
128
+ const controller = new AbortController();
129
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
130
+ let res;
131
+ try {
132
+ res = await fetch(url, {
133
+ method: 'GET',
134
+ headers: { 'Authorization': `Bearer ${this.token}` },
135
+ signal: controller.signal,
136
+ });
137
+ }
138
+ catch (err) {
139
+ if (err instanceof Error && err.name === 'AbortError') {
140
+ throw new GatewayHttpError(`Health check timed out after ${timeoutMs}ms`, 0);
141
+ }
142
+ throw new GatewayHttpError(`Network error: ${err instanceof Error ? err.message : String(err)}`, 0);
143
+ }
144
+ finally {
145
+ clearTimeout(timer);
146
+ }
147
+ if (!res.ok) {
148
+ throw new GatewayHttpError(`Health check failed: HTTP ${res.status}`, res.status);
149
+ }
150
+ return (await res.json());
151
+ }
152
+ // ---- Private ----
153
+ describeHttpError(status, tool, body) {
154
+ const bodyMsg = body && typeof body === 'object' && 'error' in body
155
+ ? `: ${body.error?.message ?? ''}`
156
+ : '';
157
+ switch (status) {
158
+ case 400: return `Bad request for tool "${tool}"${bodyMsg}`;
159
+ case 401: return `Unauthorized — invalid or expired gateway token${bodyMsg}`;
160
+ case 404: return `Tool "${tool}" not found (not in allowlist or doesn't exist)${bodyMsg}`;
161
+ case 405: return `Method not allowed for tool "${tool}"${bodyMsg}`;
162
+ default: return `HTTP ${status} invoking tool "${tool}"${bodyMsg}`;
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,116 @@
1
+ import { type ReconnectConfig as BaseReconnectConfig } from '../utils/reconnect.js';
2
+ import type { GatewayConfig } from './gateway-config.js';
3
+ interface ReconnectConfig extends BaseReconnectConfig {
4
+ maxAttempts: number;
5
+ }
6
+ /** hello-ok response payload from gateway */
7
+ export interface HelloOkPayload {
8
+ type: 'hello-ok';
9
+ protocol: number;
10
+ policy: {
11
+ tickIntervalMs: number;
12
+ maxPayload: number;
13
+ };
14
+ snapshot: {
15
+ presence: Record<string, unknown>;
16
+ health: Record<string, unknown>;
17
+ stateVersion: number;
18
+ uptimeMs: number;
19
+ };
20
+ auth: {
21
+ deviceToken: string;
22
+ role: string;
23
+ scopes: string[];
24
+ };
25
+ }
26
+ export type GatewayWsEvent = 'connected' | 'disconnected' | 'reconnecting' | 'failed' | 'agent' | 'presence' | 'tick' | 'shutdown';
27
+ export type GatewayWsEventPayload = {
28
+ connected: HelloOkPayload;
29
+ disconnected: {
30
+ code: number;
31
+ reason: string;
32
+ };
33
+ reconnecting: {
34
+ attempt: number;
35
+ delayMs: number;
36
+ };
37
+ failed: {
38
+ reason: string;
39
+ };
40
+ agent: {
41
+ runId: string;
42
+ stream: string;
43
+ data: unknown;
44
+ seq?: number;
45
+ };
46
+ presence: {
47
+ payload: unknown;
48
+ seq?: number;
49
+ };
50
+ tick: void;
51
+ shutdown: void;
52
+ };
53
+ type EventListener<E extends GatewayWsEvent> = (payload: GatewayWsEventPayload[E]) => void;
54
+ export type GatewayWsState = 'disconnected' | 'connecting' | 'handshaking' | 'connected' | 'reconnecting' | 'failed';
55
+ export declare class GatewayWsClient {
56
+ private ws;
57
+ private state;
58
+ private attempt;
59
+ private reconnectTimer;
60
+ private staleWarnTimer;
61
+ private staleReconnectTimer;
62
+ private tickIntervalMs;
63
+ private pendingRpcs;
64
+ private readonly reconnectConfig;
65
+ private destroyed;
66
+ /** Stored device token from hello-ok for future connects */
67
+ private deviceToken;
68
+ /** Last hello-ok payload — contains initial snapshot */
69
+ private lastHelloOk;
70
+ /** Event listeners */
71
+ private listeners;
72
+ private readonly gatewayUrl;
73
+ private readonly gatewayToken;
74
+ constructor(config: Pick<GatewayConfig, 'gatewayUrl' | 'gatewayToken'>, reconnect?: Partial<ReconnectConfig>);
75
+ /** Start the WebSocket connection and handshake */
76
+ connect(): void;
77
+ /** Disconnect and clean up. Cannot reconnect after this. */
78
+ destroy(): void;
79
+ /**
80
+ * Send an RPC request and wait for the response.
81
+ * Used for: agent (chat), health, status
82
+ */
83
+ sendRpc(method: string, params?: Record<string, unknown>): Promise<unknown>;
84
+ /** Register an event listener */
85
+ on<E extends GatewayWsEvent>(event: E, listener: EventListener<E>): void;
86
+ /** Remove an event listener */
87
+ off<E extends GatewayWsEvent>(event: E, listener: EventListener<E>): void;
88
+ /** Get current connection state */
89
+ getState(): GatewayWsState;
90
+ /** Get the hello-ok snapshot from the last successful connection */
91
+ getHelloOk(): HelloOkPayload | null;
92
+ /** Get stored device token (for future connects) */
93
+ getDeviceToken(): string | null;
94
+ private handleMessage;
95
+ private handleResponse;
96
+ private handleEvent;
97
+ /**
98
+ * Step 1: Receive connect.challenge with {nonce, ts}.
99
+ * Step 2: Send connect request with auth token.
100
+ */
101
+ private handleChallenge;
102
+ /**
103
+ * Step 3: Process hello-ok response.
104
+ * Extracts policy, snapshot, and device token.
105
+ */
106
+ private handleHelloOk;
107
+ /** Reset the stale timers — called on any incoming event/tick */
108
+ private resetStaleTimer;
109
+ private clearStaleTimer;
110
+ private scheduleReconnect;
111
+ private clearReconnectTimer;
112
+ private setState;
113
+ private emit;
114
+ private rejectAllPending;
115
+ }
116
+ export {};