@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,32 @@
1
+ export interface ConnectBundle {
2
+ token?: string;
3
+ userId?: string;
4
+ relayUrl?: string;
5
+ }
6
+ /**
7
+ * Extract token / userId / relayUrl from the onboarding "connect message"
8
+ * (or a bare token). Deterministic, order-independent, tolerant of any prose
9
+ * the agent/user wraps around it — so `--setup "<pasted message>"` works whether
10
+ * the user pasted just the token or the full three-line bundle. Mirrors the
11
+ * format produced by webapp onboarding (token/userId/relayUrl lines).
12
+ */
13
+ export declare function parseConnectBundle(text: string): ConnectBundle;
14
+ export declare function validateToken(token: string): {
15
+ valid: boolean;
16
+ error?: string;
17
+ };
18
+ /**
19
+ * Attempts a WebSocket connection to the relay to verify the token is valid.
20
+ * Connects, waits for auth ack, then disconnects.
21
+ * Returns { success, message }.
22
+ */
23
+ export declare function testConnection(token: string, userId: string, relayUrl?: string): Promise<{
24
+ success: boolean;
25
+ message: string;
26
+ }>;
27
+ /**
28
+ * Run the setup flow.
29
+ * - If token provided: validate, test, save to config
30
+ * - If no token: print instructions
31
+ */
32
+ export declare function runSetup(tokenOrBundle?: string, userId?: string, relayUrl?: string): Promise<void>;
@@ -0,0 +1,226 @@
1
+ // Interactive setup helper for the ReefClaw skill.
2
+ // Validates token format, tests relay connection, saves to OpenClaw config.
3
+ import WebSocket from 'ws';
4
+ import { execSync } from 'node:child_process';
5
+ import { writeOpenClawConfig } from './config.js';
6
+ import { logger } from './logger.js';
7
+ const TAG = 'setup';
8
+ const DEFAULT_RELAY_URL = 'wss://reefclaw.radunlupsa.partykit.dev';
9
+ const TOKEN_PREFIX = 'rc_';
10
+ const TOKEN_MIN_LENGTH = 10; // rc_ + at least 7 chars
11
+ const CONNECTION_TEST_TIMEOUT_MS = 10_000;
12
+ /**
13
+ * Extract token / userId / relayUrl from the onboarding "connect message"
14
+ * (or a bare token). Deterministic, order-independent, tolerant of any prose
15
+ * the agent/user wraps around it — so `--setup "<pasted message>"` works whether
16
+ * the user pasted just the token or the full three-line bundle. Mirrors the
17
+ * format produced by webapp onboarding (token/userId/relayUrl lines).
18
+ */
19
+ export function parseConnectBundle(text) {
20
+ const out = {};
21
+ if (!text)
22
+ return out;
23
+ const tokenMatch = text.match(/rc_[A-Za-z0-9_-]{7,}/);
24
+ if (tokenMatch)
25
+ out.token = tokenMatch[0];
26
+ const uuidMatch = text.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/);
27
+ if (uuidMatch)
28
+ out.userId = uuidMatch[0];
29
+ const relayMatch = text.match(/wss:\/\/[^\s'"]+/);
30
+ if (relayMatch)
31
+ out.relayUrl = relayMatch[0];
32
+ return out;
33
+ }
34
+ // ---- Token validation ----
35
+ export function validateToken(token) {
36
+ if (!token) {
37
+ return { valid: false, error: 'Token is empty' };
38
+ }
39
+ if (!token.startsWith(TOKEN_PREFIX)) {
40
+ return { valid: false, error: `Token must start with "${TOKEN_PREFIX}"` };
41
+ }
42
+ if (token.length < TOKEN_MIN_LENGTH) {
43
+ return { valid: false, error: `Token is too short (minimum ${TOKEN_MIN_LENGTH} characters)` };
44
+ }
45
+ return { valid: true };
46
+ }
47
+ // ---- Connection test ----
48
+ /**
49
+ * Attempts a WebSocket connection to the relay to verify the token is valid.
50
+ * Connects, waits for auth ack, then disconnects.
51
+ * Returns { success, message }.
52
+ */
53
+ export async function testConnection(token, userId, relayUrl = DEFAULT_RELAY_URL) {
54
+ return new Promise((resolve) => {
55
+ // Token is sent via Authorization header so it doesn't appear in edge/proxy/access logs
56
+ // that capture full request URIs. Same rationale as connector.ts buildUrl().
57
+ const url = `${relayUrl}/parties/reefclaw/${userId}`;
58
+ const timer = setTimeout(() => {
59
+ ws.close();
60
+ resolve({ success: false, message: 'Connection timed out — relay may be unreachable' });
61
+ }, CONNECTION_TEST_TIMEOUT_MS);
62
+ const ws = new WebSocket(url, {
63
+ headers: { Authorization: `Bearer ${token}` },
64
+ });
65
+ ws.on('open', () => {
66
+ logger.debug(TAG, 'Test connection open, awaiting auth ack');
67
+ });
68
+ ws.on('message', (data) => {
69
+ try {
70
+ const frame = JSON.parse(data.toString());
71
+ if (frame.type === 'res' && frame.id === '_connect') {
72
+ clearTimeout(timer);
73
+ ws.close(1000, 'Setup test complete');
74
+ if (frame.ok) {
75
+ resolve({ success: true, message: 'Token verified — connection to relay successful' });
76
+ }
77
+ else {
78
+ resolve({
79
+ success: false,
80
+ message: `Auth rejected: ${frame.error?.message ?? 'unknown error'}`,
81
+ });
82
+ }
83
+ }
84
+ }
85
+ catch {
86
+ // Ignore unparseable messages during test
87
+ }
88
+ });
89
+ ws.on('error', (err) => {
90
+ clearTimeout(timer);
91
+ resolve({ success: false, message: `Connection failed: ${err.message}` });
92
+ });
93
+ ws.on('close', (code) => {
94
+ clearTimeout(timer);
95
+ if (code === 4001 || code === 4002) {
96
+ resolve({ success: false, message: 'Authentication failed — check your token and user ID' });
97
+ }
98
+ // Normal close after successful test handled by message handler
99
+ });
100
+ });
101
+ }
102
+ // ---- Setup flow ----
103
+ /**
104
+ * Run the setup flow.
105
+ * - If token provided: validate, test, save to config
106
+ * - If no token: print instructions
107
+ */
108
+ export async function runSetup(tokenOrBundle, userId, relayUrl) {
109
+ console.log('');
110
+ console.log(' ReefClaw Skill Setup');
111
+ console.log(' ====================');
112
+ console.log('');
113
+ if (!tokenOrBundle) {
114
+ printSetupInstructions();
115
+ return;
116
+ }
117
+ // Accept either a bare token OR the full onboarding connect message (which
118
+ // also carries userId + relayUrl). Explicit args win over parsed values.
119
+ const parsed = parseConnectBundle(tokenOrBundle);
120
+ const token = parsed.token ?? tokenOrBundle.trim();
121
+ const resolvedUserId = userId ?? parsed.userId;
122
+ const resolvedRelayUrl = relayUrl ?? parsed.relayUrl;
123
+ // Validate token format
124
+ const validation = validateToken(token);
125
+ if (!validation.valid) {
126
+ console.error(` Error: ${validation.error}`);
127
+ console.error('');
128
+ console.error(' Your token should look like: rc_a1b2c3d4e5f6...');
129
+ console.error(' Get one at https://reefclaw.com/onboarding');
130
+ process.exit(1);
131
+ }
132
+ console.log(' Token format: OK');
133
+ // Test connection if userId is available
134
+ if (resolvedUserId) {
135
+ console.log(' Testing relay connection...');
136
+ const result = await testConnection(token, resolvedUserId, resolvedRelayUrl);
137
+ if (result.success) {
138
+ console.log(` Connection: ${result.message}`);
139
+ }
140
+ else {
141
+ console.warn(` Connection: ${result.message}`);
142
+ console.warn(' (Token will be saved anyway — you can retry later)');
143
+ }
144
+ }
145
+ else {
146
+ console.log(' No user ID found — the skill cannot reach the relay without it.');
147
+ console.log(' Paste the full connect message from https://reefclaw.com/onboarding');
148
+ console.log(' (it includes the userId line), or pass --user-id <id>.');
149
+ }
150
+ // Save to config
151
+ writeOpenClawConfig(token, resolvedUserId, resolvedRelayUrl);
152
+ // Create heartbeat cron job if none exists
153
+ ensureHeartbeatCron();
154
+ console.log('');
155
+ console.log(' Setup complete! Token saved to ~/.openclaw/config.json');
156
+ console.log('');
157
+ console.log(' Next steps:');
158
+ console.log(' 1. Start your OpenClaw agent');
159
+ console.log(' 2. Open https://reefclaw.com/dashboard');
160
+ console.log(' 3. The skill will connect automatically');
161
+ console.log(' 4. Your agent checks the market every 15 minutes (adjustable via chat)');
162
+ console.log('');
163
+ }
164
+ // ---- Heartbeat cron ----
165
+ /**
166
+ * Ensures a heartbeat cron job exists for ReefClaw.
167
+ * Checks `openclaw cron list` for an existing job with "reefclaw" in the name.
168
+ * If none found, creates one with 15m default interval.
169
+ * Non-fatal — if openclaw CLI isn't available or cron fails, setup still succeeds.
170
+ */
171
+ function ensureHeartbeatCron() {
172
+ try {
173
+ // Check if a reefclaw cron already exists
174
+ const listOutput = execSync('openclaw cron list --json 2>/dev/null', {
175
+ encoding: 'utf-8',
176
+ timeout: 15_000,
177
+ });
178
+ // Look for any job with "reefclaw" in the name
179
+ try {
180
+ const jobs = JSON.parse(listOutput);
181
+ const existing = (Array.isArray(jobs) ? jobs : []).find((j) => j.name?.toLowerCase().includes('reefclaw'));
182
+ if (existing) {
183
+ console.log(` Heartbeat cron: already exists (${existing.name})`);
184
+ return;
185
+ }
186
+ }
187
+ catch {
188
+ // JSON parse failed — maybe not JSON output, check raw text
189
+ if (listOutput.toLowerCase().includes('reefclaw')) {
190
+ console.log(' Heartbeat cron: already exists');
191
+ return;
192
+ }
193
+ }
194
+ // No existing job — create one
195
+ console.log(' Creating heartbeat cron (every 15m)...');
196
+ execSync('openclaw cron add --name reefclaw-heartbeat --every 15m --session isolated ' +
197
+ "--message 'Heartbeat. Run SESSION START mandatory checks, then the full Decision Loop (Steps 0-9) from SKILL.md. Check tradingMode from fetch_balance — it is your source of truth for paper vs live. Use tools in parallel where possible.' 2>&1", { encoding: 'utf-8', timeout: 15_000 });
198
+ console.log(' Heartbeat cron: created (every 15 minutes)');
199
+ console.log(' Tip: Ask your agent "change heartbeat to 10 minutes" to adjust');
200
+ }
201
+ catch (err) {
202
+ // Non-fatal — user can create cron manually or agent can create it on first session
203
+ const msg = err instanceof Error ? err.message : String(err);
204
+ if (msg.includes('not found') || msg.includes('ENOENT')) {
205
+ console.log(' Heartbeat cron: skipped (openclaw CLI not in PATH)');
206
+ }
207
+ else {
208
+ console.log(` Heartbeat cron: skipped (${msg.split('\n')[0]})`);
209
+ }
210
+ }
211
+ }
212
+ function printSetupInstructions() {
213
+ console.log(' To connect your OpenClaw agent to ReefClaw:');
214
+ console.log('');
215
+ console.log(' 1. Go to https://reefclaw.com and create an account');
216
+ console.log(' 2. Copy your connection token from the onboarding page');
217
+ console.log(' 3. Run this command with your token:');
218
+ console.log('');
219
+ console.log(' node dist/index.js --setup rc_YOUR_TOKEN_HERE --user-id YOUR_USER_ID');
220
+ console.log('');
221
+ console.log(' Or tell your OpenClaw agent:');
222
+ console.log(' "Here\'s my ReefClaw token: rc_YOUR_TOKEN_HERE"');
223
+ console.log('');
224
+ console.log(' The agent will save it automatically. No manual config editing needed.');
225
+ console.log('');
226
+ }