@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.
- package/.gitignore +8 -0
- package/audit/mode-transition-audit.d.ts +11 -0
- package/audit/mode-transition-audit.js +29 -0
- package/balance-utils.d.ts +36 -0
- package/balance-utils.js +98 -0
- package/bridge/bridge.d.ts +109 -0
- package/bridge/bridge.js +1036 -0
- package/bridge/config.d.ts +43 -0
- package/bridge/config.js +176 -0
- package/bridge/connector.d.ts +52 -0
- package/bridge/connector.js +293 -0
- package/bridge/event-replay-buffer.d.ts +43 -0
- package/bridge/event-replay-buffer.js +109 -0
- package/bridge/gateway/event-parser.d.ts +209 -0
- package/bridge/gateway/event-parser.js +793 -0
- package/bridge/gateway/gateway-config.d.ts +39 -0
- package/bridge/gateway/gateway-config.js +86 -0
- package/bridge/gateway/gateway-http-client.d.ts +50 -0
- package/bridge/gateway/gateway-http-client.js +165 -0
- package/bridge/gateway/gateway-ws-client.d.ts +116 -0
- package/bridge/gateway/gateway-ws-client.js +417 -0
- package/bridge/gateway/poller.d.ts +146 -0
- package/bridge/gateway/poller.js +505 -0
- package/bridge/gateway/tool-discovery.d.ts +25 -0
- package/bridge/gateway/tool-discovery.js +198 -0
- package/bridge/index.d.ts +2 -0
- package/bridge/index.js +253 -0
- package/bridge/logger.d.ts +2 -0
- package/bridge/logger.js +2 -0
- package/bridge/provider.d.ts +156 -0
- package/bridge/provider.js +2 -0
- package/bridge/providers/emergency-commands.d.ts +54 -0
- package/bridge/providers/emergency-commands.js +235 -0
- package/bridge/providers/gateway.d.ts +322 -0
- package/bridge/providers/gateway.js +2302 -0
- package/bridge/providers/mock.d.ts +37 -0
- package/bridge/providers/mock.js +385 -0
- package/bridge/providers/onboarding-commands.d.ts +83 -0
- package/bridge/providers/onboarding-commands.js +213 -0
- package/bridge/providers/risk-calculator.d.ts +96 -0
- package/bridge/providers/risk-calculator.js +369 -0
- package/bridge/setup.d.ts +32 -0
- package/bridge/setup.js +226 -0
- package/bridge/types.d.ts +584 -0
- package/bridge/types.js +50 -0
- package/bridge/utils/reconnect.d.ts +6 -0
- package/bridge/utils/reconnect.js +6 -0
- package/bridge/utils/skill-signing.d.ts +51 -0
- package/bridge/utils/skill-signing.js +138 -0
- package/bridge/utils/skill-version.d.ts +17 -0
- package/bridge/utils/skill-version.js +74 -0
- package/ccxt/binance-ban-gate.d.ts +47 -0
- package/ccxt/binance-ban-gate.js +409 -0
- package/ccxt/binance-private.d.ts +325 -0
- package/ccxt/binance-private.js +1415 -0
- package/ccxt/binance-public.d.ts +18 -0
- package/ccxt/binance-public.js +147 -0
- package/config/agent-config-client.d.ts +55 -0
- package/config/agent-config-client.js +145 -0
- package/config/agent-config-poller.d.ts +25 -0
- package/config/agent-config-poller.js +100 -0
- package/config/brackets-config.d.ts +22 -0
- package/config/brackets-config.js +58 -0
- package/config/gate-store.d.ts +18 -0
- package/config/gate-store.js +61 -0
- package/config/plugin-config-io.d.ts +181 -0
- package/config/plugin-config-io.js +84 -0
- package/config/position-review-config.d.ts +35 -0
- package/config/position-review-config.js +105 -0
- package/config/tool-gate.d.ts +53 -0
- package/config/tool-gate.js +125 -0
- package/config/user-data-stream-config.d.ts +85 -0
- package/config/user-data-stream-config.js +224 -0
- package/connector-supervisor.d.ts +36 -0
- package/connector-supervisor.js +149 -0
- package/exchange-adapter.d.ts +49 -0
- package/exchange-adapter.js +4 -0
- package/index.d.ts +30 -0
- package/index.js +2030 -0
- package/ingest/pending-entry-metadata.d.ts +52 -0
- package/ingest/pending-entry-metadata.js +182 -0
- package/ingest/position-auto-capture.d.ts +98 -0
- package/ingest/position-auto-capture.js +394 -0
- package/ingest/position-decisions-client.d.ts +318 -0
- package/ingest/position-decisions-client.js +296 -0
- package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
- package/ingest/reconcile-db-vs-exchange.js +114 -0
- package/ingest/reconciler-cleanup.d.ts +37 -0
- package/ingest/reconciler-cleanup.js +147 -0
- package/ingest/rest-gap-filler.d.ts +191 -0
- package/ingest/rest-gap-filler.js +565 -0
- package/ingest/touched-symbols-store.d.ts +25 -0
- package/ingest/touched-symbols-store.js +96 -0
- package/ingest/trade-store-client.d.ts +40 -0
- package/ingest/trade-store-client.js +125 -0
- package/ingest/ws-ingest.d.ts +43 -0
- package/ingest/ws-ingest.js +126 -0
- package/learning/setup-family.d.ts +21 -0
- package/learning/setup-family.js +103 -0
- package/lifecycle/install-signal-handlers.d.ts +33 -0
- package/lifecycle/install-signal-handlers.js +112 -0
- package/lifecycle/shutdown-coordinator.d.ts +43 -0
- package/lifecycle/shutdown-coordinator.js +131 -0
- package/live/bracket-id.d.ts +18 -0
- package/live/bracket-id.js +81 -0
- package/live/bracket-ledger.d.ts +54 -0
- package/live/bracket-ledger.js +267 -0
- package/live/bracket-manager.d.ts +82 -0
- package/live/bracket-manager.js +478 -0
- package/live/bracket-params.d.ts +22 -0
- package/live/bracket-params.js +124 -0
- package/live/bracket-reconciler.d.ts +95 -0
- package/live/bracket-reconciler.js +573 -0
- package/live/bracket-types.d.ts +102 -0
- package/live/bracket-types.js +8 -0
- package/live/deposit-tracker.d.ts +62 -0
- package/live/deposit-tracker.js +97 -0
- package/live/emergency-controls.d.ts +32 -0
- package/live/emergency-controls.js +226 -0
- package/live/exchange-errors.d.ts +12 -0
- package/live/exchange-errors.js +130 -0
- package/live/exchange-info-cache.d.ts +35 -0
- package/live/exchange-info-cache.js +119 -0
- package/live/fact-subscriber.d.ts +78 -0
- package/live/fact-subscriber.js +182 -0
- package/live/intent-journal.d.ts +42 -0
- package/live/intent-journal.js +122 -0
- package/live/listen-key-manager.d.ts +70 -0
- package/live/listen-key-manager.js +169 -0
- package/live/live-adapter.d.ts +264 -0
- package/live/live-adapter.js +1665 -0
- package/live/live-balance-enricher.d.ts +32 -0
- package/live/live-balance-enricher.js +104 -0
- package/live/live-bracket-api.d.ts +13 -0
- package/live/live-bracket-api.js +20 -0
- package/live/live-state-store.d.ts +194 -0
- package/live/live-state-store.js +450 -0
- package/live/local-signal-service.d.ts +57 -0
- package/live/local-signal-service.js +146 -0
- package/live/local-strategy-evaluator.d.ts +62 -0
- package/live/local-strategy-evaluator.js +127 -0
- package/live/microstructure-assembler.d.ts +54 -0
- package/live/microstructure-assembler.js +148 -0
- package/live/order-poller.d.ts +29 -0
- package/live/order-poller.js +125 -0
- package/live/position-state-store.d.ts +83 -0
- package/live/position-state-store.js +237 -0
- package/live/proposal-decision-listener.d.ts +64 -0
- package/live/proposal-decision-listener.js +288 -0
- package/live/proposal-manager.d.ts +76 -0
- package/live/proposal-manager.js +140 -0
- package/live/rate-limiter.d.ts +47 -0
- package/live/rate-limiter.js +159 -0
- package/live/reconciler.d.ts +39 -0
- package/live/reconciler.js +175 -0
- package/live/setup-buckets.d.ts +7 -0
- package/live/setup-buckets.js +33 -0
- package/live/slippage-tracker.d.ts +45 -0
- package/live/slippage-tracker.js +78 -0
- package/live/stop-watcher.d.ts +34 -0
- package/live/stop-watcher.js +158 -0
- package/live/user-data-active-probe.d.ts +54 -0
- package/live/user-data-active-probe.js +180 -0
- package/live/user-data-stream-controller.d.ts +200 -0
- package/live/user-data-stream-controller.js +579 -0
- package/live/user-data-stream-ws.d.ts +22 -0
- package/live/user-data-stream-ws.js +63 -0
- package/live/user-data-stream.d.ts +243 -0
- package/live/user-data-stream.js +704 -0
- package/logger.d.ts +2 -0
- package/logger.js +2 -0
- package/mfe.d.ts +21 -0
- package/mfe.js +68 -0
- package/onboarding/mode-ladder.d.ts +1 -0
- package/onboarding/mode-ladder.js +3 -0
- package/onboarding/runtime.d.ts +71 -0
- package/onboarding/runtime.js +153 -0
- package/openclaw.plugin.json +94 -0
- package/package.json +27 -0
- package/paper-adapter.d.ts +24 -0
- package/paper-adapter.js +91 -0
- package/persistence/state-manager.d.ts +42 -0
- package/persistence/state-manager.js +164 -0
- package/pinned-plan.d.ts +9 -0
- package/pinned-plan.js +23 -0
- package/risk/pre-trade-check.d.ts +38 -0
- package/risk/pre-trade-check.js +345 -0
- package/risk/pre-trade-types.d.ts +60 -0
- package/risk/pre-trade-types.js +3 -0
- package/scripts/assemble.mjs +114 -0
- package/shadow/shadow-tracker.d.ts +36 -0
- package/shadow/shadow-tracker.js +151 -0
- package/shadow/types.d.ts +42 -0
- package/shadow/types.js +20 -0
- package/shared/indicators-extended.d.ts +52 -0
- package/shared/indicators-extended.js +291 -0
- package/shared/indicators.d.ts +15 -0
- package/shared/indicators.js +114 -0
- package/signals/conditions/registry.d.ts +16 -0
- package/signals/conditions/registry.js +1274 -0
- package/signals/conditions/types.d.ts +1 -0
- package/signals/conditions/types.js +4 -0
- package/signals/direction-rules.d.ts +3 -0
- package/signals/direction-rules.js +24 -0
- package/signals/entry-rules.d.ts +6 -0
- package/signals/entry-rules.js +33 -0
- package/signals/serialize-context.d.ts +4 -0
- package/signals/serialize-context.js +39 -0
- package/signals/stop-rules.d.ts +3 -0
- package/signals/stop-rules.js +48 -0
- package/signals/strategy-adapter.d.ts +14 -0
- package/signals/strategy-adapter.js +122 -0
- package/signals/types.d.ts +1 -0
- package/signals/types.js +8 -0
- package/simulator/exchange-simulator.d.ts +93 -0
- package/simulator/exchange-simulator.js +684 -0
- package/simulator/fill-engine.d.ts +53 -0
- package/simulator/fill-engine.js +276 -0
- package/simulator/paper-market-feed.d.ts +26 -0
- package/simulator/paper-market-feed.js +104 -0
- package/simulator/realistic-fills.d.ts +59 -0
- package/simulator/realistic-fills.js +175 -0
- package/simulator/types.d.ts +219 -0
- package/simulator/types.js +43 -0
- package/skills/reefclaw/SKILL.md +97 -0
- package/strategy/builtin-strategies.d.ts +2 -0
- package/strategy/builtin-strategies.js +109 -0
- package/strategy/condition-registry.d.ts +3 -0
- package/strategy/condition-registry.js +153 -0
- package/strategy/evaluator.d.ts +67 -0
- package/strategy/evaluator.js +93 -0
- package/tools/assessment-validation.d.ts +118 -0
- package/tools/assessment-validation.js +415 -0
- package/tools/attach-brackets.d.ts +34 -0
- package/tools/attach-brackets.js +363 -0
- package/tools/audit-bracket-protection.d.ts +49 -0
- package/tools/audit-bracket-protection.js +527 -0
- package/tools/cancel-all-orders.d.ts +7 -0
- package/tools/cancel-all-orders.js +5 -0
- package/tools/cancel-order.d.ts +10 -0
- package/tools/cancel-order.js +14 -0
- package/tools/check-position-health.d.ts +46 -0
- package/tools/check-position-health.js +194 -0
- package/tools/clear-exchange-credentials.d.ts +24 -0
- package/tools/clear-exchange-credentials.js +70 -0
- package/tools/close-position.d.ts +22 -0
- package/tools/close-position.js +449 -0
- package/tools/create-order.d.ts +54 -0
- package/tools/create-order.js +338 -0
- package/tools/exit-gate.d.ts +58 -0
- package/tools/exit-gate.js +162 -0
- package/tools/fetch-balance.d.ts +5 -0
- package/tools/fetch-balance.js +4 -0
- package/tools/fetch-ohlcv.d.ts +11 -0
- package/tools/fetch-ohlcv.js +8 -0
- package/tools/fetch-open-orders.d.ts +7 -0
- package/tools/fetch-open-orders.js +4 -0
- package/tools/fetch-positions.d.ts +7 -0
- package/tools/fetch-positions.js +4 -0
- package/tools/fetch-ticker.d.ts +11 -0
- package/tools/fetch-ticker.js +5 -0
- package/tools/get-agent-profile.d.ts +4 -0
- package/tools/get-agent-profile.js +6 -0
- package/tools/get-analytics.d.ts +6 -0
- package/tools/get-analytics.js +7 -0
- package/tools/get-backtest.d.ts +12 -0
- package/tools/get-backtest.js +91 -0
- package/tools/get-basis.d.ts +7 -0
- package/tools/get-basis.js +7 -0
- package/tools/get-bracket-config.d.ts +11 -0
- package/tools/get-bracket-config.js +24 -0
- package/tools/get-cascade-risk.d.ts +7 -0
- package/tools/get-cascade-risk.js +8 -0
- package/tools/get-crypto-metrics.d.ts +18 -0
- package/tools/get-crypto-metrics.js +45 -0
- package/tools/get-cvd.d.ts +6 -0
- package/tools/get-cvd.js +6 -0
- package/tools/get-divergences.d.ts +6 -0
- package/tools/get-divergences.js +6 -0
- package/tools/get-funding-context.d.ts +6 -0
- package/tools/get-funding-context.js +16 -0
- package/tools/get-liquidation-levels.d.ts +7 -0
- package/tools/get-liquidation-levels.js +7 -0
- package/tools/get-liquidation-pulse.d.ts +9 -0
- package/tools/get-liquidation-pulse.js +22 -0
- package/tools/get-market-breadth.d.ts +6 -0
- package/tools/get-market-breadth.js +8 -0
- package/tools/get-market-intel.d.ts +19 -0
- package/tools/get-market-intel.js +116 -0
- package/tools/get-market-structure.d.ts +47 -0
- package/tools/get-market-structure.js +198 -0
- package/tools/get-my-mined-patterns.d.ts +20 -0
- package/tools/get-my-mined-patterns.js +61 -0
- package/tools/get-my-proposed-learnings.d.ts +20 -0
- package/tools/get-my-proposed-learnings.js +55 -0
- package/tools/get-my-recent-reviews.d.ts +22 -0
- package/tools/get-my-recent-reviews.js +66 -0
- package/tools/get-orderbook.d.ts +21 -0
- package/tools/get-orderbook.js +32 -0
- package/tools/get-pattern-scan.d.ts +7 -0
- package/tools/get-pattern-scan.js +8 -0
- package/tools/get-regime.d.ts +6 -0
- package/tools/get-regime.js +7 -0
- package/tools/get-relevant-learnings.d.ts +21 -0
- package/tools/get-relevant-learnings.js +65 -0
- package/tools/get-resting-liquidity.d.ts +6 -0
- package/tools/get-resting-liquidity.js +11 -0
- package/tools/get-risk-scenario.d.ts +29 -0
- package/tools/get-risk-scenario.js +47 -0
- package/tools/get-risk-summary.d.ts +51 -0
- package/tools/get-risk-summary.js +118 -0
- package/tools/get-sentiment.d.ts +4 -0
- package/tools/get-sentiment.js +6 -0
- package/tools/get-session-review.d.ts +7 -0
- package/tools/get-session-review.js +8 -0
- package/tools/get-setup-detail.d.ts +7 -0
- package/tools/get-setup-detail.js +303 -0
- package/tools/get-signals.d.ts +15 -0
- package/tools/get-signals.js +54 -0
- package/tools/get-sizing.d.ts +6 -0
- package/tools/get-sizing.js +6 -0
- package/tools/get-trade-feedback.d.ts +7 -0
- package/tools/get-trade-feedback.js +8 -0
- package/tools/get-trade-flow.d.ts +7 -0
- package/tools/get-trade-flow.js +7 -0
- package/tools/get-volume-analysis.d.ts +21 -0
- package/tools/get-volume-analysis.js +74 -0
- package/tools/get-volume-profile.d.ts +7 -0
- package/tools/get-volume-profile.js +7 -0
- package/tools/helpers.d.ts +25 -0
- package/tools/helpers.js +38 -0
- package/tools/intel-api.d.ts +14 -0
- package/tools/intel-api.js +52 -0
- package/tools/intel-cache.d.ts +25 -0
- package/tools/intel-cache.js +133 -0
- package/tools/list-strategies.d.ts +7 -0
- package/tools/list-strategies.js +6 -0
- package/tools/modify-stop.d.ts +17 -0
- package/tools/modify-stop.js +81 -0
- package/tools/modify-target.d.ts +17 -0
- package/tools/modify-target.js +71 -0
- package/tools/propose-learning.d.ts +22 -0
- package/tools/propose-learning.js +65 -0
- package/tools/query-review-outcomes.d.ts +30 -0
- package/tools/query-review-outcomes.js +64 -0
- package/tools/query-trades.d.ts +21 -0
- package/tools/query-trades.js +37 -0
- package/tools/record-position-reviews.d.ts +38 -0
- package/tools/record-position-reviews.js +147 -0
- package/tools/save-strategy.d.ts +16 -0
- package/tools/save-strategy.js +46 -0
- package/tools/scan-pairs.d.ts +18 -0
- package/tools/scan-pairs.js +220 -0
- package/tools/score-setup.d.ts +31 -0
- package/tools/score-setup.js +268 -0
- package/tools/set-bracket-requirement.d.ts +18 -0
- package/tools/set-bracket-requirement.js +81 -0
- package/tools/set-exchange-credentials.d.ts +25 -0
- package/tools/set-exchange-credentials.js +80 -0
- package/tools/set-trading-mode.d.ts +26 -0
- package/tools/set-trading-mode.js +135 -0
- package/tools/test-exchange-credentials.d.ts +16 -0
- package/tools/test-exchange-credentials.js +100 -0
- package/tools/toggle-strategy.d.ts +8 -0
- package/tools/toggle-strategy.js +8 -0
- package/trading-params-cache.d.ts +26 -0
- package/trading-params-cache.js +52 -0
- package/types.d.ts +110 -0
- package/types.js +7 -0
- package/util/plugin-paths.d.ts +3 -0
- 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>;
|
package/bridge/setup.js
ADDED
|
@@ -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
|
+
}
|