@senpi/runtime 1.0.95-dev.feat-dsl-backend-int.20260416023008 → 1.0.95-dev.runtime-phase-2.20260416194608
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/README.md +72 -0
- package/dist/actions/action-runtime-module.d.ts +55 -0
- package/dist/actions/action-runtime-module.d.ts.map +1 -0
- package/dist/actions/action-runtime-module.js +444 -0
- package/dist/actions/action-runtime-module.js.map +1 -0
- package/dist/actions/close-position/close-position.action.d.ts +1 -0
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
- package/dist/actions/close-position/close-position.action.js +55 -20
- package/dist/actions/close-position/close-position.action.js.map +1 -1
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +5 -0
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/llm-decision/shared.d.ts +1 -1
- package/dist/actions/llm-decision/shared.d.ts.map +1 -1
- package/dist/actions/llm-decision/shared.js +1 -1
- package/dist/actions/llm-decision/shared.js.map +1 -1
- package/dist/actions/notifications/formatter.d.ts +39 -0
- package/dist/actions/notifications/formatter.d.ts.map +1 -0
- package/dist/actions/notifications/formatter.js +68 -0
- package/dist/actions/notifications/formatter.js.map +1 -0
- package/dist/actions/notifications/index.d.ts +37 -0
- package/dist/actions/notifications/index.d.ts.map +1 -0
- package/dist/actions/notifications/index.js +89 -0
- package/dist/actions/notifications/index.js.map +1 -0
- package/dist/actions/open-position/open-position.action.d.ts +1 -0
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +132 -27
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/open-position/resolve-margin.d.ts +22 -0
- package/dist/actions/open-position/resolve-margin.d.ts.map +1 -0
- package/dist/actions/open-position/resolve-margin.js +30 -0
- package/dist/actions/open-position/resolve-margin.js.map +1 -0
- package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.js +4 -1
- package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
- package/dist/actions/store/action-store.d.ts +45 -0
- package/dist/actions/store/action-store.d.ts.map +1 -0
- package/dist/actions/store/action-store.js +127 -0
- package/dist/actions/store/action-store.js.map +1 -0
- package/dist/actions/store/index.d.ts +11 -0
- package/dist/actions/store/index.d.ts.map +1 -0
- package/dist/actions/store/index.js +9 -0
- package/dist/actions/store/index.js.map +1 -0
- package/dist/actions/store/paths.d.ts +15 -0
- package/dist/actions/store/paths.d.ts.map +1 -0
- package/dist/actions/store/paths.js +29 -0
- package/dist/actions/store/paths.js.map +1 -0
- package/dist/actions/store/types.d.ts +114 -0
- package/dist/actions/store/types.d.ts.map +1 -0
- package/dist/actions/store/types.js +48 -0
- package/dist/actions/store/types.js.map +1 -0
- package/dist/actions/tracking-helpers.d.ts +13 -0
- package/dist/actions/tracking-helpers.d.ts.map +1 -0
- package/dist/actions/tracking-helpers.js +47 -0
- package/dist/actions/tracking-helpers.js.map +1 -0
- package/dist/actions/types.d.ts +8 -0
- package/dist/actions/types.d.ts.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +105 -3
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +428 -1
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/order-types.d.ts +7 -0
- package/dist/constants/order-types.d.ts.map +1 -0
- package/dist/constants/order-types.js +6 -0
- package/dist/constants/order-types.js.map +1 -0
- package/dist/context/interpolate.d.ts +6 -2
- package/dist/context/interpolate.d.ts.map +1 -1
- package/dist/context/interpolate.js +6 -2
- package/dist/context/interpolate.js.map +1 -1
- package/dist/context/types.d.ts +8 -1
- package/dist/context/types.d.ts.map +1 -1
- package/dist/context/types.js +8 -1
- package/dist/context/types.js.map +1 -1
- package/dist/dsl/config/exit-block.d.ts +7 -0
- package/dist/dsl/config/exit-block.d.ts.map +1 -1
- package/dist/dsl/config/parse-plugin-config.d.ts.map +1 -1
- package/dist/dsl/config/parse-plugin-config.js +27 -1
- package/dist/dsl/config/parse-plugin-config.js.map +1 -1
- package/dist/dsl/config/unknown-keys.d.ts.map +1 -1
- package/dist/dsl/config/unknown-keys.js +3 -1
- package/dist/dsl/config/unknown-keys.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +4 -0
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +8 -5
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts +4 -0
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +8 -2
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +3 -1
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/health/index.d.ts +5 -2
- package/dist/health/index.d.ts.map +1 -1
- package/dist/health/index.js +106 -6
- package/dist/health/index.js.map +1 -1
- package/dist/health/types.d.ts +102 -0
- package/dist/health/types.d.ts.map +1 -1
- package/dist/health/types.js +7 -1
- package/dist/health/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -1
- package/dist/index.js.map +1 -1
- package/dist/risk/guardrail.types.d.ts +53 -0
- package/dist/risk/guardrail.types.d.ts.map +1 -0
- package/dist/risk/guardrail.types.js +5 -0
- package/dist/risk/guardrail.types.js.map +1 -0
- package/dist/risk/index.d.ts +2 -4
- package/dist/risk/index.d.ts.map +1 -1
- package/dist/risk/index.js +2 -6
- package/dist/risk/index.js.map +1 -1
- package/dist/risk/risk-audit-log.d.ts +25 -0
- package/dist/risk/risk-audit-log.d.ts.map +1 -0
- package/dist/risk/risk-audit-log.js +30 -0
- package/dist/risk/risk-audit-log.js.map +1 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts +162 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.d.ts.map +1 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js +285 -0
- package/dist/runtime/__tests__/helpers/runtime-gateway-harness.js.map +1 -0
- package/dist/runtime/create-actions.d.ts +6 -2
- package/dist/runtime/create-actions.d.ts.map +1 -1
- package/dist/runtime/create-actions.js +18 -7
- package/dist/runtime/create-actions.js.map +1 -1
- package/dist/runtime/create-scanner-module.d.ts +5 -0
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +12 -1
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/load-runtime-config.d.ts +1 -1
- package/dist/runtime/load-runtime-config.d.ts.map +1 -1
- package/dist/runtime/load-runtime-config.js +37 -1
- package/dist/runtime/load-runtime-config.js.map +1 -1
- package/dist/runtime/map-strategies.d.ts +1 -1
- package/dist/runtime/map-strategies.d.ts.map +1 -1
- package/dist/runtime/map-strategies.js +38 -1
- package/dist/runtime/map-strategies.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts +23 -2
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +441 -5
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/run.d.ts +7 -0
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +3 -0
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +1169 -24
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +105 -2
- package/dist/runtime/runtime-schema.js.map +1 -1
- package/dist/runtime/runtime.d.ts +26 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +192 -6
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scanner-composition.d.ts +10 -0
- package/dist/runtime/scanner-composition.d.ts.map +1 -1
- package/dist/runtime/scanner-composition.js +10 -0
- package/dist/runtime/scanner-composition.js.map +1 -1
- package/dist/runtime/scanner-registry.d.ts +39 -1
- package/dist/runtime/scanner-registry.d.ts.map +1 -1
- package/dist/runtime/scanner-registry.js +105 -2
- package/dist/runtime/scanner-registry.js.map +1 -1
- package/dist/runtime/state-layout.d.ts +2 -0
- package/dist/runtime/state-layout.d.ts.map +1 -1
- package/dist/runtime/state-layout.js +1 -0
- package/dist/runtime/state-layout.js.map +1 -1
- package/dist/runtime/validate-action-prompts.d.ts +30 -0
- package/dist/runtime/validate-action-prompts.d.ts.map +1 -0
- package/dist/runtime/validate-action-prompts.js +110 -0
- package/dist/runtime/validate-action-prompts.js.map +1 -0
- package/dist/scanners/__tests__/test-helpers.d.ts +10 -0
- package/dist/scanners/__tests__/test-helpers.d.ts.map +1 -1
- package/dist/scanners/__tests__/test-helpers.js +52 -0
- package/dist/scanners/__tests__/test-helpers.js.map +1 -1
- package/dist/scanners/engine/engine.d.ts +37 -0
- package/dist/scanners/engine/engine.d.ts.map +1 -1
- package/dist/scanners/engine/engine.js +132 -14
- package/dist/scanners/engine/engine.js.map +1 -1
- package/dist/scanners/engine/result-builder.d.ts +16 -0
- package/dist/scanners/engine/result-builder.d.ts.map +1 -1
- package/dist/scanners/engine/result-builder.js +22 -0
- package/dist/scanners/engine/result-builder.js.map +1 -1
- package/dist/scanners/engine/strategy-registry.d.ts +2 -0
- package/dist/scanners/engine/strategy-registry.d.ts.map +1 -1
- package/dist/scanners/engine/strategy-registry.js +5 -1
- package/dist/scanners/engine/strategy-registry.js.map +1 -1
- package/dist/scanners/external-scanner-receiver.d.ts +118 -0
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -0
- package/dist/scanners/external-scanner-receiver.js +266 -0
- package/dist/scanners/external-scanner-receiver.js.map +1 -0
- package/dist/scanners/implementations/external-scanner.d.ts +17 -0
- package/dist/scanners/implementations/external-scanner.d.ts.map +1 -0
- package/dist/scanners/implementations/external-scanner.js +51 -0
- package/dist/scanners/implementations/external-scanner.js.map +1 -0
- package/dist/scanners/implementations/index.d.ts +1 -0
- package/dist/scanners/implementations/index.d.ts.map +1 -1
- package/dist/scanners/implementations/index.js +1 -0
- package/dist/scanners/implementations/index.js.map +1 -1
- package/dist/scanners/implementations/position-tracker.d.ts.map +1 -1
- package/dist/scanners/implementations/position-tracker.js +3 -1
- package/dist/scanners/implementations/position-tracker.js.map +1 -1
- package/dist/scanners/index.d.ts +4 -1
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +2 -0
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/protocol/scanner.d.ts +3 -1
- package/dist/scanners/protocol/scanner.d.ts.map +1 -1
- package/dist/scanners/providers/client.d.ts.map +1 -1
- package/dist/scanners/providers/client.js +0 -8
- package/dist/scanners/providers/client.js.map +1 -1
- package/dist/scanners/runtime-module.d.ts +10 -0
- package/dist/scanners/runtime-module.d.ts.map +1 -1
- package/dist/scanners/runtime-module.js +19 -3
- package/dist/scanners/runtime-module.js.map +1 -1
- package/dist/scanners/scanner-definition.d.ts +12 -1
- package/dist/scanners/scanner-definition.d.ts.map +1 -1
- package/dist/scanners/types.d.ts +3 -0
- package/dist/scanners/types.d.ts.map +1 -1
- package/dist/scanners/types.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-live.js +1 -1
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-mock.js +1 -1
- package/dist/scripts/run-dsl-standalone-mock.js.map +1 -1
- package/dist/senpi/client.d.ts +27 -2
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +74 -1
- package/dist/senpi/client.js.map +1 -1
- package/dist/senpi/index.d.ts +1 -1
- package/dist/senpi/index.d.ts.map +1 -1
- package/dist/senpi/types.d.ts +68 -0
- package/dist/senpi/types.d.ts.map +1 -1
- package/dist/strategy/strategy-state.d.ts +4 -1
- package/dist/strategy/strategy-state.d.ts.map +1 -1
- package/dist/strategy/strategy-state.js +7 -2
- package/dist/strategy/strategy-state.js.map +1 -1
- package/dist/tracking/constants.d.ts +24 -0
- package/dist/tracking/constants.d.ts.map +1 -0
- package/dist/tracking/constants.js +46 -0
- package/dist/tracking/constants.js.map +1 -0
- package/dist/tracking/index.d.ts +12 -0
- package/dist/tracking/index.d.ts.map +1 -0
- package/dist/tracking/index.js +8 -0
- package/dist/tracking/index.js.map +1 -0
- package/dist/tracking/tracker.d.ts +22 -0
- package/dist/tracking/tracker.d.ts.map +1 -0
- package/dist/tracking/tracker.js +44 -0
- package/dist/tracking/tracker.js.map +1 -0
- package/dist/tracking/tracking-handler.d.ts +12 -0
- package/dist/tracking/tracking-handler.d.ts.map +1 -0
- package/dist/tracking/tracking-handler.js +148 -0
- package/dist/tracking/tracking-handler.js.map +1 -0
- package/dist/tracking/transport.d.ts +35 -0
- package/dist/tracking/transport.d.ts.map +1 -0
- package/dist/tracking/transport.js +117 -0
- package/dist/tracking/transport.js.map +1 -0
- package/dist/tracking/types.d.ts +21 -0
- package/dist/tracking/types.d.ts.map +1 -0
- package/dist/tracking/types.js +6 -0
- package/dist/tracking/types.js.map +1 -0
- package/dist/types/action.d.ts +13 -2
- package/dist/types/action.d.ts.map +1 -1
- package/dist/types/dsl/index.d.ts +3 -0
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/strategy.d.ts +9 -3
- package/dist/types/strategy.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +19 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/resolve-order-type.d.ts +5 -0
- package/dist/utils/resolve-order-type.d.ts.map +1 -0
- package/dist/utils/resolve-order-type.js +29 -0
- package/dist/utils/resolve-order-type.js.map +1 -0
- package/examples/strategies/dsl-showcase.yaml +7 -2
- package/examples/strategies/dsl.yaml +5 -1
- package/examples/strategies/fox-minimal-loosened.yaml +18 -3
- package/examples/strategies/fox-minimal.yaml +25 -3
- package/examples/strategies/minimal.yaml +4 -2
- package/examples/strategies/momentum/how-it-works.md +47 -0
- package/examples/strategies/momentum/momentum-guarded.yaml +161 -0
- package/examples/strategies/risk-showcase.yaml +93 -0
- package/examples/strategies/viper.yaml +11 -3
- package/examples/strategies/wolf.yaml +11 -3
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +12 -4
- package/package.json +4 -4
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { expect, vi } from "vitest";
|
|
5
|
+
import { SharedArtifactStore } from "../../../scanners/store/shared-artifact-store.js";
|
|
6
|
+
import { loadRuntimeConfig } from "../../load-runtime-config.js";
|
|
7
|
+
import { Runtime } from "../../runtime.js";
|
|
8
|
+
/**
|
|
9
|
+
* Default MCP transport used by runtime integration tests that do not care
|
|
10
|
+
* about real tool behavior.
|
|
11
|
+
*
|
|
12
|
+
* The runtime expects `list_open_positions` to resolve cleanly even when no
|
|
13
|
+
* positions exist, so the helper returns an empty list there and a generic
|
|
14
|
+
* success envelope elsewhere.
|
|
15
|
+
*/
|
|
16
|
+
export async function noopTransport(method, _params) {
|
|
17
|
+
if (method === "list_open_positions") {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return { success: true, results: [] };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a dedicated temporary runtime state directory for one test.
|
|
24
|
+
*
|
|
25
|
+
* The caller supplies the prefix so failures remain easy to attribute from temp
|
|
26
|
+
* paths and filesystem inspection.
|
|
27
|
+
*/
|
|
28
|
+
export function createRuntimeStateDir(prefix) {
|
|
29
|
+
return mkdtempSync(join(tmpdir(), prefix));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Captures OpenClaw gateway requests while returning a deterministic no-op
|
|
33
|
+
* decision response.
|
|
34
|
+
*
|
|
35
|
+
* This helper keeps the real action layer, prompt interpolation, and context
|
|
36
|
+
* building in play without making network calls or depending on gateway
|
|
37
|
+
* availability.
|
|
38
|
+
*/
|
|
39
|
+
export class GatewayCapture {
|
|
40
|
+
calls = [];
|
|
41
|
+
originalGatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
|
42
|
+
reasoning;
|
|
43
|
+
actionType;
|
|
44
|
+
fetchMock;
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
this.reasoning = options.reasoning ?? "test-harness";
|
|
47
|
+
this.actionType = options.actionType ?? "OPEN_POSITION";
|
|
48
|
+
this.fetchMock = vi.fn(async (_url, init) => {
|
|
49
|
+
const request = parseGatewayInvokeRequest(init?.body);
|
|
50
|
+
this.calls.push(request);
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
status: 200,
|
|
54
|
+
json: async () => ({
|
|
55
|
+
ok: true,
|
|
56
|
+
result: {
|
|
57
|
+
json: {
|
|
58
|
+
execute: false,
|
|
59
|
+
confidence: 4,
|
|
60
|
+
reasoning: this.reasoning,
|
|
61
|
+
actionType: this.actionType,
|
|
62
|
+
payload: {},
|
|
63
|
+
},
|
|
64
|
+
usage: {
|
|
65
|
+
inputTokens: 0,
|
|
66
|
+
outputTokens: 0,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
text: async () => JSON.stringify({ ok: true }),
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Installs the fetch stub and a deterministic gateway token expected by the
|
|
76
|
+
* real action-layer client.
|
|
77
|
+
*/
|
|
78
|
+
install() {
|
|
79
|
+
process.env.OPENCLAW_GATEWAY_TOKEN = "test-token";
|
|
80
|
+
vi.stubGlobal("fetch", this.fetchMock);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Restores the original fetch global and gateway token after a test.
|
|
84
|
+
*
|
|
85
|
+
* Restoring the env var matters because some runtime tests explicitly verify
|
|
86
|
+
* behavior when the token is absent.
|
|
87
|
+
*/
|
|
88
|
+
restore() {
|
|
89
|
+
vi.unstubAllGlobals();
|
|
90
|
+
if (this.originalGatewayToken !== undefined) {
|
|
91
|
+
process.env.OPENCLAW_GATEWAY_TOKEN = this.originalGatewayToken;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Waits until the expected number of gateway calls has been captured.
|
|
98
|
+
*
|
|
99
|
+
* The runtime routes actions through an async serial consumer, so tests must
|
|
100
|
+
* poll briefly instead of assuming the request exists immediately after a
|
|
101
|
+
* scanner run or ingest call resolves.
|
|
102
|
+
*/
|
|
103
|
+
async waitForCallCount(expectedCount) {
|
|
104
|
+
const deadline = Date.now() + 1_000;
|
|
105
|
+
while (Date.now() < deadline) {
|
|
106
|
+
if (this.calls.length >= expectedCount) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await sleep(10);
|
|
110
|
+
}
|
|
111
|
+
throw new Error(`Timed out waiting for ${expectedCount} gateway call(s); saw ${this.calls.length}.`);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Asserts that no gateway requests were emitted after a short stabilization
|
|
115
|
+
* window.
|
|
116
|
+
*
|
|
117
|
+
* This guards tests that expect dependency failures or skips to prevent any
|
|
118
|
+
* downstream LLM routing.
|
|
119
|
+
*/
|
|
120
|
+
async expectNoCalls() {
|
|
121
|
+
await sleep(100);
|
|
122
|
+
expect(this.calls).toHaveLength(0);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Shared integration harness for runtime tests that need real scanner-module
|
|
127
|
+
* behavior plus captured action-layer gateway requests.
|
|
128
|
+
*
|
|
129
|
+
* The harness centralizes the repetitive bootstrap/teardown logic so scenario
|
|
130
|
+
* tests can stay focused on their domain-specific setup and assertions.
|
|
131
|
+
*/
|
|
132
|
+
export class RuntimeGatewayHarness {
|
|
133
|
+
options;
|
|
134
|
+
runtime = null;
|
|
135
|
+
address = null;
|
|
136
|
+
gateway;
|
|
137
|
+
mcpTransport;
|
|
138
|
+
constructor(options) {
|
|
139
|
+
this.options = options;
|
|
140
|
+
this.gateway = new GatewayCapture({
|
|
141
|
+
reasoning: options.gatewayReasoning,
|
|
142
|
+
actionType: options.gatewayActionType,
|
|
143
|
+
});
|
|
144
|
+
this.mcpTransport = options.mcpTransport ?? noopTransport;
|
|
145
|
+
}
|
|
146
|
+
/** Installs the gateway capture so the real action path can run offline. */
|
|
147
|
+
installGatewayCapture() {
|
|
148
|
+
this.gateway.install();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Starts the runtime from an inline YAML recipe string and resolves the
|
|
152
|
+
* strategy address once boot completes.
|
|
153
|
+
*/
|
|
154
|
+
async start(recipeYaml) {
|
|
155
|
+
const config = await loadRuntimeConfig(recipeYaml, { fromPath: false });
|
|
156
|
+
this.runtime = new Runtime(config, {
|
|
157
|
+
stateDir: this.options.stateDir,
|
|
158
|
+
mcpTransport: this.mcpTransport,
|
|
159
|
+
});
|
|
160
|
+
await this.runtime.start();
|
|
161
|
+
this.address = resolveStrategyAddress(this.runtime);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Stops the runtime, restores gateway globals, and removes the temporary
|
|
165
|
+
* state directory.
|
|
166
|
+
*/
|
|
167
|
+
async dispose() {
|
|
168
|
+
if (this.runtime) {
|
|
169
|
+
await this.runtime.stop();
|
|
170
|
+
this.runtime = null;
|
|
171
|
+
}
|
|
172
|
+
this.address = null;
|
|
173
|
+
this.gateway.restore();
|
|
174
|
+
vi.restoreAllMocks();
|
|
175
|
+
try {
|
|
176
|
+
rmSync(this.options.stateDir, { recursive: true, force: true });
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// ignore temp-dir cleanup failures so test assertions surface first
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Runs one configured scanner through the real scanner module. */
|
|
183
|
+
async runScanner(scannerId) {
|
|
184
|
+
return this.scannerModule.runOnce(this.requireAddress(), scannerId);
|
|
185
|
+
}
|
|
186
|
+
/** Runs one scanner plus its dependency chain through the real scanner module. */
|
|
187
|
+
async runScannerChain(scannerId) {
|
|
188
|
+
return this.scannerModule.runChain(this.requireAddress(), scannerId);
|
|
189
|
+
}
|
|
190
|
+
/** Reads retained scanner context for the active runtime strategy. */
|
|
191
|
+
async readScannerContext(scannerId) {
|
|
192
|
+
return this.scannerModule.getScannerContext(this.requireAddress(), scannerId);
|
|
193
|
+
}
|
|
194
|
+
/** Queries persisted latest signals for the active runtime strategy. */
|
|
195
|
+
async querySignals(scannerId) {
|
|
196
|
+
return this.scannerModule.querySignals({
|
|
197
|
+
address: this.requireAddress(),
|
|
198
|
+
scannerId,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/** Forwards one external ingest request through the real runtime surface. */
|
|
202
|
+
async ingestExternalScannerData(request) {
|
|
203
|
+
return this.requireRuntime().ingestExternalScannerData(request);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Returns the most recent captured gateway request after waiting for the
|
|
207
|
+
* action queue to emit it.
|
|
208
|
+
*/
|
|
209
|
+
async waitForGatewayRequest() {
|
|
210
|
+
await this.gateway.waitForCallCount(1);
|
|
211
|
+
const request = this.gateway.calls.at(-1);
|
|
212
|
+
if (!request) {
|
|
213
|
+
throw new Error("Expected a captured gateway request, but none was recorded.");
|
|
214
|
+
}
|
|
215
|
+
return request;
|
|
216
|
+
}
|
|
217
|
+
/** Asserts that the runtime did not emit any gateway requests. */
|
|
218
|
+
async expectNoGatewayRequests() {
|
|
219
|
+
await this.gateway.expectNoCalls();
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Seeds one retained-context envelope directly into the shared-artifact store.
|
|
223
|
+
*
|
|
224
|
+
* This is intentionally test-only: it lets dependency-focused scenarios start
|
|
225
|
+
* from an already-published context snapshot without forcing an upstream
|
|
226
|
+
* scanner run first.
|
|
227
|
+
*/
|
|
228
|
+
async seedRetainedContext(options) {
|
|
229
|
+
const store = new SharedArtifactStore(this.options.stateDir);
|
|
230
|
+
await store.saveEnvelopeByScanner(options.address, options.scannerId, {
|
|
231
|
+
updatedAt: options.updatedAt,
|
|
232
|
+
data: options.value,
|
|
233
|
+
}, {
|
|
234
|
+
contract: options.contract,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
/** Returns the active strategy address once the runtime has started. */
|
|
238
|
+
getAddress() {
|
|
239
|
+
return this.requireAddress();
|
|
240
|
+
}
|
|
241
|
+
get scannerModule() {
|
|
242
|
+
const runtime = this.requireRuntime();
|
|
243
|
+
return runtime.scannerModule;
|
|
244
|
+
}
|
|
245
|
+
requireRuntime() {
|
|
246
|
+
if (!this.runtime) {
|
|
247
|
+
throw new Error("Runtime has not been started for this test harness.");
|
|
248
|
+
}
|
|
249
|
+
return this.runtime;
|
|
250
|
+
}
|
|
251
|
+
requireAddress() {
|
|
252
|
+
if (!this.address) {
|
|
253
|
+
throw new Error("Runtime strategy address is not available before start().");
|
|
254
|
+
}
|
|
255
|
+
return this.address;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Reads the strategy wallet address from the real runtime internals after
|
|
260
|
+
* start-up validation has finished.
|
|
261
|
+
*/
|
|
262
|
+
function resolveStrategyAddress(runtime) {
|
|
263
|
+
const address = runtime.strategyConfig.address;
|
|
264
|
+
if (typeof address !== "string" || address.length === 0) {
|
|
265
|
+
throw new Error("Expected runtime to expose a non-empty strategy address.");
|
|
266
|
+
}
|
|
267
|
+
return address;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Parses the JSON request body sent by the OpenClaw client.
|
|
271
|
+
*
|
|
272
|
+
* Failing fast on non-string bodies protects the helper against silent drift in
|
|
273
|
+
* the gateway client contract.
|
|
274
|
+
*/
|
|
275
|
+
function parseGatewayInvokeRequest(body) {
|
|
276
|
+
if (typeof body !== "string") {
|
|
277
|
+
throw new Error("Expected OpenClaw fetch body to be a JSON string.");
|
|
278
|
+
}
|
|
279
|
+
return JSON.parse(body);
|
|
280
|
+
}
|
|
281
|
+
/** Small async sleep helper used by polling assertions. */
|
|
282
|
+
function sleep(ms) {
|
|
283
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=runtime-gateway-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-gateway-harness.js","sourceRoot":"","sources":["../../../../src/runtime/__tests__/helpers/runtime-gateway-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Instantiate actions from skills config and expose runActionsForSignal for serial processing.
|
|
3
3
|
*/
|
|
4
|
-
import type { Action, HookEvent } from "../actions/types.js";
|
|
4
|
+
import type { Action, ActionConfig, HookEvent } from "../actions/types.js";
|
|
5
|
+
import type { ActionRuntimeModule } from "../actions/action-runtime-module.js";
|
|
5
6
|
import type { SenpiEventBus } from "../types/event-bus.js";
|
|
6
7
|
import type { RuntimeContext } from "../types/runtime.js";
|
|
7
8
|
import type { RuntimeConfig } from "./runtime-config.js";
|
|
@@ -10,11 +11,14 @@ export interface CreateActionsOptions extends Omit<CreateActionContextDeps, "str
|
|
|
10
11
|
bus: SenpiEventBus;
|
|
11
12
|
/** When provided, this context is reused for all actions (built once per trading recipe by the runtime). */
|
|
12
13
|
runtimeContext?: RuntimeContext;
|
|
14
|
+
/** When set, wraps each action invocation with telemetry and persistence. */
|
|
15
|
+
actionModule?: ActionRuntimeModule;
|
|
13
16
|
}
|
|
14
17
|
export interface ActionWithMeta {
|
|
15
18
|
action: Action;
|
|
16
19
|
name: string;
|
|
17
20
|
eventsConsumed: string[];
|
|
21
|
+
config: ActionConfig;
|
|
18
22
|
}
|
|
19
23
|
export interface CreateActionsResult {
|
|
20
24
|
actions: ActionWithMeta[];
|
|
@@ -26,5 +30,5 @@ export interface CreateActionsResult {
|
|
|
26
30
|
* and runActionsForSignal so the runtime can process signals serially (one at a time) to avoid slot races.
|
|
27
31
|
* When options.runtimeContext is provided (e.g. by Runtime), it is reused for all action factories.
|
|
28
32
|
*/
|
|
29
|
-
export declare function createActions(config: RuntimeConfig, options: CreateActionsOptions): CreateActionsResult
|
|
33
|
+
export declare function createActions(config: RuntimeConfig, options: CreateActionsOptions): Promise<CreateActionsResult>;
|
|
30
34
|
//# sourceMappingURL=create-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-actions.d.ts","sourceRoot":"","sources":["../../src/runtime/create-actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"create-actions.d.ts","sourceRoot":"","sources":["../../src/runtime/create-actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAc,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAK1E,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,GAAG,UAAU,CAAC;IAClG,GAAG,EAAE,aAAa,CAAC;IACnB,4GAA4G;IAC5G,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,mBAAmB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAmEtH"}
|
|
@@ -12,7 +12,7 @@ import { MaxLeverageCache } from "../leverage/max-leverage-cache.js";
|
|
|
12
12
|
* and runActionsForSignal so the runtime can process signals serially (one at a time) to avoid slot races.
|
|
13
13
|
* When options.runtimeContext is provided (e.g. by Runtime), it is reused for all action factories.
|
|
14
14
|
*/
|
|
15
|
-
export function createActions(config, options) {
|
|
15
|
+
export async function createActions(config, options) {
|
|
16
16
|
const context = options.runtimeContext ??
|
|
17
17
|
createRuntimeContext(resolveStrategyConfig(config), {
|
|
18
18
|
senpi: options.senpi,
|
|
@@ -25,12 +25,14 @@ export function createActions(config, options) {
|
|
|
25
25
|
});
|
|
26
26
|
const actions = [];
|
|
27
27
|
const actionList = config.actions ?? [];
|
|
28
|
+
const strategyAddress = resolveStrategyConfig(config).address;
|
|
29
|
+
const actionModule = options.actionModule;
|
|
28
30
|
for (const entry of actionList) {
|
|
29
31
|
const factory = ActionRegistry.get(entry.action_type);
|
|
30
32
|
if (!factory) {
|
|
31
33
|
throw new Error(`Unknown action_type: ${entry.action_type}`);
|
|
32
34
|
}
|
|
33
|
-
const
|
|
35
|
+
const actionConfig = {
|
|
34
36
|
name: entry.name,
|
|
35
37
|
action_type: entry.action_type,
|
|
36
38
|
decision_mode: entry.decision_mode ?? "none",
|
|
@@ -41,27 +43,36 @@ export function createActions(config, options) {
|
|
|
41
43
|
decision_prompt: entry.decision_prompt,
|
|
42
44
|
params: entry.params,
|
|
43
45
|
};
|
|
44
|
-
const action = factory(
|
|
46
|
+
const action = factory(actionConfig, context);
|
|
47
|
+
if (actionModule) {
|
|
48
|
+
await actionModule.registerAction(strategyAddress, entry.name, actionConfig);
|
|
49
|
+
}
|
|
45
50
|
const actionWithManifest = action;
|
|
46
51
|
const manifest = actionWithManifest?.manifest?.eventsConsumed ?? [HOOK_EVENT.ON_SIGNAL_DETECTED];
|
|
47
52
|
actions.push({
|
|
48
53
|
action,
|
|
49
54
|
name: entry.name,
|
|
50
55
|
eventsConsumed: manifest,
|
|
56
|
+
config: actionConfig,
|
|
51
57
|
});
|
|
52
58
|
}
|
|
53
59
|
function runActionsForSignal(event) {
|
|
54
60
|
const scanPayload = event?.data;
|
|
55
61
|
const scannerId = scanPayload?.scanResult?.scannerId;
|
|
62
|
+
const address = event.address;
|
|
56
63
|
const promises = [];
|
|
57
|
-
for (const { action } of actions) {
|
|
58
|
-
const
|
|
59
|
-
const scanners = cfg?.scanners;
|
|
64
|
+
for (const { action, config: cfg } of actions) {
|
|
65
|
+
const scanners = cfg.scanners;
|
|
60
66
|
if (Array.isArray(scanners) && scanners.length > 0) {
|
|
61
67
|
if (scannerId == null || !scanners.includes(scannerId))
|
|
62
68
|
continue;
|
|
63
69
|
}
|
|
64
|
-
|
|
70
|
+
if (actionModule) {
|
|
71
|
+
promises.push(actionModule.wrapHandle(address, action, cfg, event));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
promises.push(Promise.resolve(action.handle(event)));
|
|
75
|
+
}
|
|
65
76
|
}
|
|
66
77
|
return Promise.all(promises).then(() => undefined);
|
|
67
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-actions.js","sourceRoot":"","sources":["../../src/runtime/create-actions.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"create-actions.js","sourceRoot":"","sources":["../../src/runtime/create-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,11 @@ import type { RuntimeConfig } from "./runtime-config.js";
|
|
|
9
9
|
* Builds the standalone scanner runtime module from parsed trading recipe config.
|
|
10
10
|
* Scanner registrations are normalized into factories so YAML-level ids and
|
|
11
11
|
* optional config overrides become strategy-scoped scanner instances.
|
|
12
|
+
*
|
|
13
|
+
* External scanners feed the same composition builder as built-in scanners.
|
|
14
|
+
* Their declared `outputs` metadata and synthesized retained-context contract
|
|
15
|
+
* are what make external context producers available to `depends_on` and
|
|
16
|
+
* action-context validation.
|
|
12
17
|
*/
|
|
13
18
|
export declare function createScannerModuleFromRuntimeConfig(config: RuntimeConfig, stateDir: string, providers?: ScannerDataProviders, logger?: ScannerLogger): ReturnType<typeof createScannerRuntimeModule>;
|
|
14
19
|
//# sourceMappingURL=create-scanner-module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-scanner-module.d.ts","sourceRoot":"","sources":["../../src/runtime/create-scanner-module.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAG3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD
|
|
1
|
+
{"version":3,"file":"create-scanner-module.d.ts","sourceRoot":"","sources":["../../src/runtime/create-scanner-module.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAG3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD;;;;;;;;;GASG;AACH,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,oBAAoB,EAChC,MAAM,CAAC,EAAE,aAAa,GACrB,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAkC/C"}
|
|
@@ -10,12 +10,23 @@ import { buildScannerComposition } from "./scanner-composition.js";
|
|
|
10
10
|
* Builds the standalone scanner runtime module from parsed trading recipe config.
|
|
11
11
|
* Scanner registrations are normalized into factories so YAML-level ids and
|
|
12
12
|
* optional config overrides become strategy-scoped scanner instances.
|
|
13
|
+
*
|
|
14
|
+
* External scanners feed the same composition builder as built-in scanners.
|
|
15
|
+
* Their declared `outputs` metadata and synthesized retained-context contract
|
|
16
|
+
* are what make external context producers available to `depends_on` and
|
|
17
|
+
* action-context validation.
|
|
13
18
|
*/
|
|
14
19
|
export function createScannerModuleFromRuntimeConfig(config, stateDir, providers, logger) {
|
|
15
20
|
const strategy = resolveStrategyRegistration(config);
|
|
16
21
|
const scanners = [];
|
|
17
22
|
for (const sc of config.scanners ?? []) {
|
|
18
|
-
scanners.push(ScannerRegistry.createScanner(sc.type, sc.name, sc.config, sc.depends_on
|
|
23
|
+
scanners.push(ScannerRegistry.createScanner(sc.type, sc.name, sc.config, sc.depends_on, sc.type === "external_scanner"
|
|
24
|
+
? {
|
|
25
|
+
outputs: sc.outputs,
|
|
26
|
+
retention: sc.retention,
|
|
27
|
+
retentionMaxRuns: sc.retention_max_runs,
|
|
28
|
+
}
|
|
29
|
+
: undefined));
|
|
19
30
|
}
|
|
20
31
|
const preparedScanners = prepareScannerInputs(scanners);
|
|
21
32
|
const composition = buildScannerComposition(config, preparedScanners.map((scanner) => scanner.definition), logger);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-scanner-module.js","sourceRoot":"","sources":["../../src/runtime/create-scanner-module.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE
|
|
1
|
+
{"version":3,"file":"create-scanner-module.js","sourceRoot":"","sources":["../../src/runtime/create-scanner-module.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE;;;;;;;;;GASG;AACH,MAAM,UAAU,oCAAoC,CAClD,MAAqB,EACrB,QAAgB,EAChB,SAAgC,EAChC,MAAsB;IAEtB,MAAM,QAAQ,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CACX,eAAe,CAAC,aAAa,CAC3B,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,MAAM,EACT,EAAE,CAAC,UAAU,EACb,EAAE,CAAC,IAAI,KAAK,kBAAkB;YAC5B,CAAC,CAAC;gBACE,OAAO,EAAE,EAAE,CAAC,OAAO;gBACnB,SAAS,EAAE,EAAE,CAAC,SAAS;gBACvB,gBAAgB,EAAE,EAAE,CAAC,kBAAkB;aACxC;YACH,CAAC,CAAC,SAAS,CACd,CACF,CAAC;IACJ,CAAC;IACD,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,WAAW,GAAG,uBAAuB,CACzC,MAAM,EACN,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,EACrD,MAAM,CACP,CAAC;IACF,OAAO,0BAA0B,CAAC;QAChC,QAAQ;QACR,QAAQ;QACR,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;QAC5D,WAAW;QACX,SAAS;QACT,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -11,7 +11,7 @@ export interface LoadRuntimeConfigOptions {
|
|
|
11
11
|
* Minimal valid YAML structure shown in validation errors so users can fix their file.
|
|
12
12
|
* Keep this in sync with runtimeConfigSchema (name + strategy with wallet).
|
|
13
13
|
*/
|
|
14
|
-
export declare const MINIMAL_RECIPE_YAML_SAMPLE = "# Required: name and a strategy with a wallet\nname: my-recipe\n# version: 1 # optional; defaults to current (1). Supports integer or semver string.\nstrategy:\n wallet: \"your-wallet-address\"\n # optional:
|
|
14
|
+
export declare const MINIMAL_RECIPE_YAML_SAMPLE = "# Required: name and a strategy with a wallet\nname: my-recipe\n# version: 1 # optional; defaults to current (1). Supports integer or semver string.\nstrategy:\n wallet: \"your-wallet-address\"\n # optional: slots, margin_pct, margin_per_slot, enabled, etc.\n\n# Optional: scanners, actions, exit. Run: openclaw senpi guide examples\n";
|
|
15
15
|
/**
|
|
16
16
|
* Load trading recipe from a file path or YAML string.
|
|
17
17
|
* - If fromPath is true, pathOrContent is a file path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-runtime-config.d.ts","sourceRoot":"","sources":["../../src/runtime/load-runtime-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"load-runtime-config.d.ts","sourceRoot":"","sources":["../../src/runtime/load-runtime-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAM9E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,sVAQtC,CAAC;AA8HF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,aAAa,CAAC,CA8ExB"}
|
|
@@ -11,6 +11,7 @@ import { runtimeConfigSchema } from "./runtime-schema.js";
|
|
|
11
11
|
import { resolveEnvInObject } from "./env-resolve.js";
|
|
12
12
|
import { mapRuntimeExitToDslConfig } from "./map-exit-config.js";
|
|
13
13
|
import { CURRENT_RUNTIME_VERSION, SUPPORTED_RUNTIME_VERSIONS, extractMajorVersion } from "./runtime-version.js";
|
|
14
|
+
import { assertActionPromptPlaceholdersResolvable } from "./validate-action-prompts.js";
|
|
14
15
|
/**
|
|
15
16
|
* Minimal valid YAML structure shown in validation errors so users can fix their file.
|
|
16
17
|
* Keep this in sync with runtimeConfigSchema (name + strategy with wallet).
|
|
@@ -20,7 +21,7 @@ name: my-recipe
|
|
|
20
21
|
# version: 1 # optional; defaults to current (1). Supports integer or semver string.
|
|
21
22
|
strategy:
|
|
22
23
|
wallet: "your-wallet-address"
|
|
23
|
-
# optional:
|
|
24
|
+
# optional: slots, margin_pct, margin_per_slot, enabled, etc.
|
|
24
25
|
|
|
25
26
|
# Optional: scanners, actions, exit. Run: openclaw senpi guide examples
|
|
26
27
|
`;
|
|
@@ -102,6 +103,39 @@ function formatZodError(message, issues) {
|
|
|
102
103
|
const pathTip = "Tip: Paths use dot notation; a number is the 0-based index (e.g. strategy.wallet = wallet address, actions.0 = first action).";
|
|
103
104
|
return `${message}\n${lines.join("\n")}\n\n${pathTip}\n\nExample of required structure:\n${MINIMAL_RECIPE_YAML_SAMPLE}`;
|
|
104
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Rejects configs where two or more scanner entries share the same `name`.
|
|
108
|
+
*
|
|
109
|
+
* Scanner names are used as artifact keys for context-producing scanners and as
|
|
110
|
+
* identifiers throughout the composition graph, so uniqueness is a hard
|
|
111
|
+
* runtime invariant. The error message includes every offending index
|
|
112
|
+
* (`scanners.<i>`) so operators can locate both occurrences in YAML rather
|
|
113
|
+
* than only the second one encountered.
|
|
114
|
+
*/
|
|
115
|
+
function assertUniqueScannerNames(config) {
|
|
116
|
+
const scanners = config.scanners ?? [];
|
|
117
|
+
const firstSeen = new Map();
|
|
118
|
+
const duplicates = new Map();
|
|
119
|
+
scanners.forEach((scanner, index) => {
|
|
120
|
+
const prior = firstSeen.get(scanner.name);
|
|
121
|
+
if (prior === undefined) {
|
|
122
|
+
firstSeen.set(scanner.name, index);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const list = duplicates.get(scanner.name) ?? [prior];
|
|
126
|
+
list.push(index);
|
|
127
|
+
duplicates.set(scanner.name, list);
|
|
128
|
+
});
|
|
129
|
+
if (duplicates.size === 0)
|
|
130
|
+
return;
|
|
131
|
+
const details = Array.from(duplicates.entries())
|
|
132
|
+
.map(([name, indices]) => {
|
|
133
|
+
const paths = indices.map((i) => `scanners.${i}`).join(", ");
|
|
134
|
+
return ` • '${name}' at ${paths}`;
|
|
135
|
+
})
|
|
136
|
+
.join("\n");
|
|
137
|
+
throw new Error(`Duplicate scanner name(s). Scanner names must be unique within one runtime:\n${details}`);
|
|
138
|
+
}
|
|
105
139
|
/**
|
|
106
140
|
* Load trading recipe from a file path or YAML string.
|
|
107
141
|
* - If fromPath is true, pathOrContent is a file path.
|
|
@@ -139,6 +173,8 @@ export async function loadRuntimeConfig(pathOrContent, options) {
|
|
|
139
173
|
const result = runtimeConfigSchema.safeParse(resolved);
|
|
140
174
|
if (result.success) {
|
|
141
175
|
const cfg = result.data;
|
|
176
|
+
assertUniqueScannerNames(cfg);
|
|
177
|
+
assertActionPromptPlaceholdersResolvable(cfg);
|
|
142
178
|
const major = extractMajorVersion(cfg.version);
|
|
143
179
|
if (!SUPPORTED_RUNTIME_VERSIONS.includes(major)) {
|
|
144
180
|
throw new Error(`Unsupported version: ${cfg.version ?? "(none)"} (major: ${major}). Supported major versions: ${SUPPORTED_RUNTIME_VERSIONS.join(", ")}.\n` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-runtime-config.js","sourceRoot":"","sources":["../../src/runtime/load-runtime-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAiB,MAAM,KAAK,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"load-runtime-config.js","sourceRoot":"","sources":["../../src/runtime/load-runtime-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve recipe `strategy` to a single StrategyConfig.
|
|
3
|
-
* Address = wallet (env-resolved). Coerces
|
|
3
|
+
* Address = wallet (env-resolved). Coerces numeric fields from strings.
|
|
4
4
|
*/
|
|
5
5
|
import type { StrategyConfig } from "../types/strategy.js";
|
|
6
6
|
import type { RuntimeConfig } from "./runtime-schema.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-strategies.d.ts","sourceRoot":"","sources":["../../src/runtime/map-strategies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"map-strategies.d.ts","sourceRoot":"","sources":["../../src/runtime/map-strategies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAgBzD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,aAAa,GAAG,cAAc,CAiFjF;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAG9F"}
|