@reefclaw/connect 0.1.37 → 0.1.39
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/assets/bridge/gateway/gateway-ws-client.d.ts +2 -0
- package/assets/bridge/gateway/gateway-ws-client.js +6 -0
- package/assets/bridge/heartbeat-runs-state.d.ts +16 -0
- package/assets/bridge/heartbeat-runs-state.js +58 -0
- package/assets/bridge/heartbeat-runs.d.ts +99 -0
- package/assets/bridge/heartbeat-runs.js +300 -0
- package/assets/bridge/heartbeat-transcript.d.ts +209 -0
- package/assets/bridge/heartbeat-transcript.js +688 -0
- package/assets/bridge/index.js +14 -0
- package/assets/bridge/model-health.d.ts +37 -0
- package/assets/bridge/model-health.js +97 -0
- package/assets/bridge/provider.d.ts +5 -1
- package/assets/bridge/providers/gateway.d.ts +25 -1
- package/assets/bridge/providers/gateway.js +167 -2
- package/assets/bridge/providers/mock.js +1 -0
- package/assets/bridge/types.d.ts +41 -0
- package/assets/plugin/index.js +7 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +13 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.js +23 -2
- package/assets/plugin/openclaw.plugin.json +1 -1
- package/assets/plugin/paper-adapter.js +8 -0
- package/assets/plugin/signals/types.js +1 -1
- package/assets/plugin/simulator/exchange-simulator.d.ts +7 -0
- package/assets/plugin/simulator/exchange-simulator.js +30 -0
- package/assets/plugin/simulator/types.d.ts +1 -1
- package/assets/plugin/tools/create-order.js +1 -1
- package/assets/plugin/tools/reentry-cooldown.js +2 -2
- package/package.json +1 -1
|
@@ -25,17 +25,25 @@ export class PaperAdapter {
|
|
|
25
25
|
async closePosition(symbol, closeReason) {
|
|
26
26
|
return this.simulator.closePosition(symbol, closeReason);
|
|
27
27
|
}
|
|
28
|
+
// Reads pull a newer state.json first (ExchangeSimulator.refreshState —
|
|
29
|
+
// no-op without a hook). Out-of-tool readers (DB-vs-exchange sweep,
|
|
30
|
+
// stop-watcher) otherwise see a stale book in the process that did not
|
|
31
|
+
// execute the entry and post false synthetic closes / phantom stop fills.
|
|
28
32
|
async getBalance() {
|
|
33
|
+
this.simulator.refreshState();
|
|
29
34
|
return this.simulator.getBalance();
|
|
30
35
|
}
|
|
31
36
|
async getPositions(symbol) {
|
|
37
|
+
this.simulator.refreshState();
|
|
32
38
|
return this.simulator.getPositions(symbol);
|
|
33
39
|
}
|
|
34
40
|
/** Paper has no exchange fetch to fail — position state is always known. */
|
|
35
41
|
async getPositionsOrNull(symbol) {
|
|
42
|
+
this.simulator.refreshState();
|
|
36
43
|
return this.simulator.getPositions(symbol);
|
|
37
44
|
}
|
|
38
45
|
async getOpenOrders(symbol) {
|
|
46
|
+
this.simulator.refreshState();
|
|
39
47
|
return this.simulator.getOpenOrders(symbol);
|
|
40
48
|
}
|
|
41
49
|
async fetchOrder(orderId, _symbol) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Re-export shim for the plugin-side strategy evaluator (facts-out).
|
|
2
2
|
//
|
|
3
|
-
// The generated
|
|
3
|
+
// The generated evaluator-core copies (registry, strategy-adapter, direction/entry/
|
|
4
4
|
// stop-rules) import their types from `./types.js`. The canonical definitions
|
|
5
5
|
// live in @reefclaw/shared (type-only → erased at runtime), so this shim makes
|
|
6
6
|
// those relative imports resolve inside the plugin tree without pulling any
|
|
@@ -63,6 +63,13 @@ export declare class ExchangeSimulator extends EventEmitter {
|
|
|
63
63
|
* on open and is released on close, so we must add it back here. */
|
|
64
64
|
computeEquity(): number;
|
|
65
65
|
private getQuoteCurrency;
|
|
66
|
+
private stateRefresher;
|
|
67
|
+
/** Install the "reload state.json if it changed" hook (index.ts reloadState). */
|
|
68
|
+
setStateRefresher(fn: (() => void) | null): void;
|
|
69
|
+
/** Pull a newer on-disk snapshot before an out-of-tool read. No-op when no
|
|
70
|
+
* hook is installed (tests / single-process). Never throws — a failed
|
|
71
|
+
* reload leaves the current in-memory book in place. */
|
|
72
|
+
refreshState(): void;
|
|
66
73
|
getBalance(): CcxtBalance;
|
|
67
74
|
getPositions(symbol?: string): CcxtPosition[];
|
|
68
75
|
getOpenOrders(symbol?: string): CcxtOrder[];
|
|
@@ -153,6 +153,36 @@ export class ExchangeSimulator extends EventEmitter {
|
|
|
153
153
|
getQuoteCurrency() {
|
|
154
154
|
return this.state.config?.quoteCurrency ?? 'USDT';
|
|
155
155
|
}
|
|
156
|
+
// ---- Cross-process refresh (two-process architecture) ----
|
|
157
|
+
//
|
|
158
|
+
// The agent and gateway processes each hold their own ExchangeSimulator and
|
|
159
|
+
// share state through state.json. Every paper TOOL path calls index.ts
|
|
160
|
+
// reloadState() before reading, but out-of-tool readers (the periodic
|
|
161
|
+
// DB-vs-exchange sweep, the stop-watcher's 3s poll) read the adapter
|
|
162
|
+
// directly — and a process that did NOT execute the entry then sees a
|
|
163
|
+
// stale in-memory book. On 2026-09-14 that posted a synthetic
|
|
164
|
+
// `reconciler_observed_flat` close 5–100s after EVERY entry on a paying
|
|
165
|
+
// tenant's box while the engine kept the position alive for hours. The
|
|
166
|
+
// hook lives on the simulator (not the adapter) so every PaperAdapter ever
|
|
167
|
+
// built from it — boot or any reconnect path — inherits it.
|
|
168
|
+
stateRefresher = null;
|
|
169
|
+
/** Install the "reload state.json if it changed" hook (index.ts reloadState). */
|
|
170
|
+
setStateRefresher(fn) {
|
|
171
|
+
this.stateRefresher = fn;
|
|
172
|
+
}
|
|
173
|
+
/** Pull a newer on-disk snapshot before an out-of-tool read. No-op when no
|
|
174
|
+
* hook is installed (tests / single-process). Never throws — a failed
|
|
175
|
+
* reload leaves the current in-memory book in place. */
|
|
176
|
+
refreshState() {
|
|
177
|
+
if (!this.stateRefresher)
|
|
178
|
+
return;
|
|
179
|
+
try {
|
|
180
|
+
this.stateRefresher();
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
logger.warn(TAG, `state refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
156
186
|
// ---- Read operations (for tools) ----
|
|
157
187
|
getBalance() {
|
|
158
188
|
const free = {};
|
|
@@ -150,7 +150,7 @@ export interface PositionMetadata {
|
|
|
150
150
|
/** The agent's stated profit-realization plan, pinned at entry (indication,
|
|
151
151
|
* not an enforced mechanic). */
|
|
152
152
|
realizationRule?: RealizationRule;
|
|
153
|
-
/** Re-entry cooldown gate
|
|
153
|
+
/** Re-entry cooldown gate evaluation, present ONLY when the gate TRIGGERED on this
|
|
154
154
|
* entry (a same-symbol loss within the window) and the order fired anyway
|
|
155
155
|
* (shadow/observe). Journaled to position_entries.metadata.reentry_cooldown
|
|
156
156
|
* so the shadow soak can measure the would-block cohort's forward outcomes
|
|
@@ -1113,7 +1113,7 @@ export async function createOrderTool(args, deps) {
|
|
|
1113
1113
|
const n = num(v);
|
|
1114
1114
|
return n != null ? Math.max(min, Math.min(max, n)) : undefined;
|
|
1115
1115
|
};
|
|
1116
|
-
// Journal-tag a TRIGGERED cooldown
|
|
1116
|
+
// Journal-tag a TRIGGERED cooldown evaluation (shadow/observe fire-anyway cohort —
|
|
1117
1117
|
// the measurement rows the promote-to-enforce decision reads).
|
|
1118
1118
|
const reentryCooldownTag = reentryCooldownEval?.triggered
|
|
1119
1119
|
? {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
// Mode semantics mirror the exit gate (docs/CLAUDE/exit-gate.md):
|
|
23
23
|
// off — not evaluated; byte-identical to the pre-gate path.
|
|
24
24
|
// shadow — evaluated + logged + journal-tagged; never affects the order.
|
|
25
|
-
// observe — as shadow, but a triggered
|
|
26
|
-
// enforce — a triggered
|
|
25
|
+
// observe — as shadow, but a triggered evaluation logs at WARN (operator-visible).
|
|
26
|
+
// enforce — a triggered evaluation hard-rejects create_order with a recovery hint.
|
|
27
27
|
export function evaluateReentryCooldown(inputs) {
|
|
28
28
|
const base = {
|
|
29
29
|
mode: inputs.mode,
|