@senpi/runtime 3.0.0-dev.runtime-phase-2.20260623210537 → 3.0.0-dev.runtime-phase-2.20260625112547
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 +10 -9
- package/dist/actions/action-runtime-module.d.ts.map +1 -1
- package/dist/actions/action-runtime-module.js +1 -1
- package/dist/actions/action-runtime-module.js.map +1 -1
- package/dist/actions/decision-engine.d.ts.map +1 -1
- package/dist/actions/decision-engine.js +3 -0
- package/dist/actions/decision-engine.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +54 -14
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/types.d.ts +10 -2
- package/dist/actions/types.d.ts.map +1 -1
- package/dist/actions/types.js +8 -0
- package/dist/actions/types.js.map +1 -1
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +80 -74
- 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 +0 -108
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/dsl/index.d.ts +2 -0
- package/dist/constants/dsl/index.d.ts.map +1 -1
- package/dist/constants/dsl/index.js +2 -0
- package/dist/constants/dsl/index.js.map +1 -1
- package/dist/dsl/config/parse-tiers.d.ts.map +1 -1
- package/dist/dsl/config/parse-tiers.js +6 -2
- package/dist/dsl/config/parse-tiers.js.map +1 -1
- package/dist/dsl/engine-client/config-mapping.d.ts +7 -0
- package/dist/dsl/engine-client/config-mapping.d.ts.map +1 -1
- package/dist/dsl/engine-client/config-mapping.js +16 -2
- package/dist/dsl/engine-client/config-mapping.js.map +1 -1
- package/dist/dsl/events/handlers.d.ts +18 -2
- package/dist/dsl/events/handlers.d.ts.map +1 -1
- package/dist/dsl/events/handlers.js +302 -213
- package/dist/dsl/events/handlers.js.map +1 -1
- package/dist/dsl/monitor/create-monitor.d.ts +15 -0
- package/dist/dsl/monitor/create-monitor.d.ts.map +1 -1
- package/dist/dsl/monitor/create-monitor.js +46 -9
- package/dist/dsl/monitor/create-monitor.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +138 -77
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/plugin/index.d.ts +16 -1
- package/dist/dsl/plugin/index.d.ts.map +1 -1
- package/dist/dsl/plugin/index.js +35 -4
- package/dist/dsl/plugin/index.js.map +1 -1
- package/dist/dsl/plugin/options.d.ts +18 -0
- package/dist/dsl/plugin/options.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/create-scanner-module.d.ts +4 -3
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +14 -5
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -1
- package/dist/runtime/create-scanner-providers-for-run.js +12 -1
- package/dist/runtime/create-scanner-providers-for-run.js.map +1 -1
- package/dist/runtime/load-runtime-config.js +1 -1
- package/dist/runtime/load-runtime-config.js.map +1 -1
- package/dist/runtime/map-strategies-registration.js +7 -8
- package/dist/runtime/map-strategies-registration.js.map +1 -1
- package/dist/runtime/map-strategies.d.ts.map +1 -1
- package/dist/runtime/map-strategies.js +12 -3
- package/dist/runtime/map-strategies.js.map +1 -1
- package/dist/runtime/reconcile-decide.d.ts +73 -0
- package/dist/runtime/reconcile-decide.d.ts.map +1 -0
- package/dist/runtime/reconcile-decide.js +186 -0
- package/dist/runtime/reconcile-decide.js.map +1 -0
- package/dist/runtime/reconcile-run.d.ts +62 -0
- package/dist/runtime/reconcile-run.d.ts.map +1 -0
- package/dist/runtime/reconcile-run.js +173 -0
- package/dist/runtime/reconcile-run.js.map +1 -0
- package/dist/runtime/reconcile-state.d.ts +44 -0
- package/dist/runtime/reconcile-state.d.ts.map +1 -1
- package/dist/runtime/reconcile-state.js +80 -44
- package/dist/runtime/reconcile-state.js.map +1 -1
- package/dist/runtime/risk-guard.d.ts.map +1 -1
- package/dist/runtime/risk-guard.js +17 -12
- package/dist/runtime/risk-guard.js.map +1 -1
- package/dist/runtime/runtime-schema.d.ts +2912 -1052
- package/dist/runtime/runtime-schema.d.ts.map +1 -1
- package/dist/runtime/runtime-schema.js +136 -42
- 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 +254 -8
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/scanner-registry.d.ts +1 -1
- package/dist/runtime/scanner-registry.d.ts.map +1 -1
- package/dist/runtime/scanner-registry.js +3 -12
- package/dist/runtime/scanner-registry.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js +1 -1
- package/dist/runtime/supervisor/orphan-sweep.js.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts +1 -1
- package/dist/runtime/supervisor/supervisor-utils.d.ts.map +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js +1 -1
- package/dist/runtime/supervisor/supervisor-utils.js.map +1 -1
- package/dist/runtime-api/intake/acceptance-record.d.ts +10 -0
- package/dist/runtime-api/intake/acceptance-record.d.ts.map +1 -1
- package/dist/runtime-api/intake/acceptance-record.js +28 -0
- package/dist/runtime-api/intake/acceptance-record.js.map +1 -1
- package/dist/runtime-api/intake/intake-mount.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-mount.js +28 -36
- package/dist/runtime-api/intake/intake-mount.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts +20 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +57 -6
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.d.ts +18 -4
- package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.js +24 -3
- package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +16 -0
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +4 -0
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +12 -0
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/scanners/external/scaffold/__main__.py +65 -24
- package/dist/scanners/external/scaffold/ctx.py +78 -0
- package/dist/scanners/external/scaffold/delivery.py +56 -22
- package/dist/scanners/external/scaffold/entrypoint_loader.py +42 -48
- package/dist/scanners/external/scaffold/journal.py +13 -2
- package/dist/scanners/external/scaffold/requirements.txt +11 -0
- package/dist/scanners/external/scaffold/scaffold.py +159 -128
- package/dist/scanners/external/scaffold/senpi_mcp.py +250 -0
- package/dist/scanners/external/scaffold/signal_envelope.py +177 -34
- package/dist/scanners/external/scaffold/state_manager.py +175 -0
- package/dist/scanners/external-scanner-receiver.d.ts +6 -0
- package/dist/scanners/external-scanner-receiver.d.ts.map +1 -1
- package/dist/scanners/external-scanner-receiver.js +14 -1
- package/dist/scanners/external-scanner-receiver.js.map +1 -1
- package/dist/scripts/run-dsl-standalone-live.d.ts +1 -1
- package/dist/scripts/run-dsl-standalone-live.js +5 -3
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -1
- package/dist/senpi/client.d.ts +37 -4
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +101 -24
- package/dist/senpi/client.js.map +1 -1
- package/dist/state/state-manager.d.ts +17 -0
- package/dist/state/state-manager.d.ts.map +1 -1
- package/dist/state/state-manager.js +50 -4
- package/dist/state/state-manager.js.map +1 -1
- package/dist/strategy/strategy-state.d.ts +9 -1
- package/dist/strategy/strategy-state.d.ts.map +1 -1
- package/dist/strategy/strategy-state.js +62 -9
- package/dist/strategy/strategy-state.js.map +1 -1
- package/dist/tracking/constants.d.ts.map +1 -1
- package/dist/tracking/constants.js +2 -0
- package/dist/tracking/constants.js.map +1 -1
- package/dist/types/dsl/index.d.ts +1 -1
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/types/scanner.d.ts +7 -0
- package/dist/types/scanner.d.ts.map +1 -1
- package/dist/types/strategy.d.ts +3 -1
- package/dist/types/strategy.d.ts.map +1 -1
- package/dist/utils/keyed-mutex.d.ts +37 -0
- package/dist/utils/keyed-mutex.d.ts.map +1 -0
- package/dist/utils/keyed-mutex.js +77 -0
- package/dist/utils/keyed-mutex.js.map +1 -0
- package/examples/strategies/README.md +17 -12
- package/examples/strategies/iguana/README.md +135 -0
- package/examples/strategies/iguana/recipe.yaml +137 -0
- package/examples/strategies/iguana/scanners/scan.py +243 -0
- package/examples/strategies/iguana/scanners/scoring.py +152 -0
- package/examples/strategies/raptor/README.md +156 -0
- package/examples/strategies/raptor/recipe.yaml +154 -0
- package/examples/strategies/raptor/scanners/scan.py +349 -0
- package/examples/strategies/raptor/scanners/scoring.py +452 -0
- package/examples/strategies/spider/README.md +89 -0
- package/examples/strategies/spider/scalp/recipe.yaml +129 -0
- package/examples/strategies/spider/scalp/scanners/scan.py +219 -0
- package/examples/strategies/spider/scalp/scanners/scoring.py +179 -0
- package/examples/strategies/spider/swing/recipe.yaml +137 -0
- package/examples/strategies/spider/swing/scanners/scan.py +334 -0
- package/examples/strategies/spider/swing/scanners/scoring.py +184 -0
- package/examples/strategies/turbine/README.md +166 -0
- package/examples/strategies/turbine/recipe-runners.yaml +123 -0
- package/examples/strategies/turbine/recipe-volume.yaml +129 -0
- package/examples/strategies/turbine/scanners/scan.py +283 -0
- package/examples/strategies/turbine/scanners/scoring.py +190 -0
- package/package.json +1 -1
- package/dist/scanners/external/liquidation-watchdog/README.md +0 -107
- package/dist/scanners/external/liquidation-watchdog/liquidation-watchdog.yaml +0 -48
- package/dist/scanners/external/liquidation-watchdog/producer.mjs +0 -336
- package/dist/scanners/external/momentum/README.md +0 -148
- package/dist/scanners/external/momentum/momentum.yaml +0 -116
- package/dist/scanners/external/momentum/producer.mjs +0 -251
- package/dist/scanners/external/shared/ingest.mjs +0 -112
- package/examples/README.md +0 -89
- package/examples/scanners-consumer-quickstart.mjs +0 -134
- package/examples/scanners-emerging-movers-v4.mjs +0 -287
- package/examples/scanners-liquidation-watchdog.mjs +0 -341
- package/examples/scanners-live-mcp.mjs +0 -208
- package/examples/scanners-multi-strategy.mjs +0 -165
- package/examples/scanners-position-tracker-e2e.mjs +0 -225
- package/examples/scanners-scheduled-events.mjs +0 -96
- package/examples/scanners-senpi-provider-client.mjs +0 -182
- package/examples/scanners-single-strategy.mjs +0 -198
- package/examples/strategies/dsl-showcase.yaml +0 -68
- package/examples/strategies/dsl.yaml +0 -51
- package/examples/strategies/fox-minimal-loosened.yaml +0 -240
- package/examples/strategies/fox-minimal.yaml +0 -242
- package/examples/strategies/minimal.yaml +0 -46
- package/examples/strategies/momentum/how-it-works.md +0 -48
- package/examples/strategies/momentum/momentum-guarded.yaml +0 -161
- package/examples/strategies/risk-showcase.yaml +0 -93
- package/examples/strategies/viper.yaml +0 -67
- package/examples/strategies/wolf.yaml +0 -72
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +0 -123
|
@@ -39,7 +39,7 @@ Scanner types
|
|
|
39
39
|
emerging_movers
|
|
40
40
|
Watches the Senpi smart-money leaderboard for rank and contribution
|
|
41
41
|
movements. Stateful — compares each scan to stored history.
|
|
42
|
-
Typical
|
|
42
|
+
Typical interval_seconds: 20–60
|
|
43
43
|
|
|
44
44
|
Signal types (priority order):
|
|
45
45
|
FIRST_JUMP (score 0.95) 10+ rank jump from deep, first appearance
|
|
@@ -64,7 +64,7 @@ emerging_movers
|
|
|
64
64
|
momentum
|
|
65
65
|
Emits directional breakout signals based on candle price movement.
|
|
66
66
|
Works best paired with the prescreener scanner.
|
|
67
|
-
Typical
|
|
67
|
+
Typical interval_seconds: 60
|
|
68
68
|
|
|
69
69
|
Signal types: MOMENTUM_BREAKOUT (LONG or SHORT)
|
|
70
70
|
|
|
@@ -82,7 +82,7 @@ prescreener
|
|
|
82
82
|
Infrastructure scanner. Ranks liquid instruments by a composite
|
|
83
83
|
liquidity/momentum/OI score and publishes a shared artifact consumed
|
|
84
84
|
by momentum and oi_tracker. Add this scanner before those in your YAML.
|
|
85
|
-
Typical
|
|
85
|
+
Typical interval_seconds: 300
|
|
86
86
|
|
|
87
87
|
Signal types: none (artifact producer only)
|
|
88
88
|
|
|
@@ -97,7 +97,7 @@ prescreener
|
|
|
97
97
|
oi_tracker
|
|
98
98
|
Infrastructure scanner. Samples open interest per instrument and writes
|
|
99
99
|
an oi-history artifact. Used by downstream scanners that need OI trend data.
|
|
100
|
-
Typical
|
|
100
|
+
Typical interval_seconds: 60
|
|
101
101
|
|
|
102
102
|
Signal types: none (artifact producer only)
|
|
103
103
|
|
|
@@ -110,7 +110,7 @@ oi_tracker
|
|
|
110
110
|
position_tracker
|
|
111
111
|
Wallet position monitor: compares clearing-house snapshots and emits lifecycle deltas.
|
|
112
112
|
Use with action POSITION_TRACKER to feed the DSL exit engine.
|
|
113
|
-
Typical
|
|
113
|
+
Typical interval_seconds: 10–60
|
|
114
114
|
|
|
115
115
|
Type aliases (same scanner): position-tracker
|
|
116
116
|
|
|
@@ -124,29 +124,28 @@ position_tracker
|
|
|
124
124
|
|
|
125
125
|
──────────────────────────────────────────────────────────────────────────────
|
|
126
126
|
|
|
127
|
-
external_scanner
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
127
|
+
external_scanner (v2 supervised)
|
|
128
|
+
A scan(inputs, ctx) module the runtime supervises. The runtime spawns a
|
|
129
|
+
scaffold child, calls scan() every interval_seconds, and delivers the
|
|
130
|
+
returned list[dict] of signals to intake over loopback. No push, no
|
|
131
|
+
ingest CLI, no producer process.
|
|
132
|
+
|
|
133
|
+
YAML fields:
|
|
134
|
+
path string Required scan module directory
|
|
135
|
+
entrypoint string Required module exporting scan(inputs, ctx)
|
|
136
|
+
interval_seconds number Opt (30) tick cadence (integer seconds)
|
|
137
|
+
timeout_seconds number Opt per-tick budget (default = interval_seconds)
|
|
138
|
+
default_signal_validity_seconds number Required fallback signal TTL (seconds)
|
|
139
|
+
state_history_max_count number Opt (0) ctx.state bound; 0 = history disabled
|
|
140
|
+
inputs object Opt author knobs → scan(inputs, ctx)
|
|
141
|
+
signal_data_schema object Required schema of each signal's data{}
|
|
142
|
+
|
|
143
|
+
scan() returns a plain list[dict]; state via ctx.state; MCP via
|
|
144
|
+
ctx.senpi_mcp. Rejected by load: interval, depends_on, outputs, config,
|
|
145
|
+
params, blocked_assets.
|
|
143
146
|
|
|
144
147
|
Prompt/context access stays namespaced:
|
|
145
148
|
{{signal_<scanner_name>}}
|
|
146
|
-
{{context_<scanner_name>}}
|
|
147
|
-
|
|
148
|
-
Gateway ingest example:
|
|
149
|
-
openclaw gateway call senpi.ingestExternalScannerData --params '{ ... }'
|
|
150
149
|
`.trim();
|
|
151
150
|
const ACTIONS_TEXT = `
|
|
152
151
|
Action types
|
|
@@ -157,12 +156,14 @@ OPEN_POSITION
|
|
|
157
156
|
|
|
158
157
|
Required YAML fields:
|
|
159
158
|
action_type OPEN_POSITION
|
|
160
|
-
decision_mode llm |
|
|
159
|
+
decision_mode llm | rule | none
|
|
161
160
|
scanners list of scanner names that feed this action
|
|
162
161
|
min_confidence 0–10; signals below this score are skipped
|
|
162
|
+
(when omitted the effective floor is 1, not 0)
|
|
163
163
|
|
|
164
164
|
Optional fields:
|
|
165
|
-
decision_model Claude model id (
|
|
165
|
+
decision_model Claude model id (recommended when decision_mode: llm;
|
|
166
|
+
falls back to the host default if omitted)
|
|
166
167
|
context list of context fields injected into the prompt
|
|
167
168
|
currently supported: signal
|
|
168
169
|
decision_prompt system prompt template; use {{signal}} for signal JSON
|
|
@@ -184,8 +185,14 @@ Decision modes:
|
|
|
184
185
|
}
|
|
185
186
|
Trades are skipped when execute=false or confidence < min_confidence.
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
rule Deterministic; no LLM call. Executes for every qualifying
|
|
189
|
+
signal (any signal carrying an asset) and forwards all of them
|
|
190
|
+
to the action. confidence = round(highest signal score × 10),
|
|
191
|
+
clamped to 1–10. Use with tight DSL stops to manage risk.
|
|
192
|
+
|
|
193
|
+
none No-op decision: logs the decision step but opens NOTHING
|
|
194
|
+
(execute=false). Use for watch-only recipes — e.g.
|
|
195
|
+
position_tracker + DSL applying stops to existing positions.
|
|
189
196
|
`.trim();
|
|
190
197
|
const DSL_TEXT = `
|
|
191
198
|
DSL exit engine — two-phase trailing stop-loss (DSL v2)
|
|
@@ -200,8 +207,9 @@ tier (no phase2_trigger_tier). Optional hard_timeout, weak_peak_cut, and
|
|
|
200
207
|
dead_weight_cut live on the preset (not nested under phase1). When any of these
|
|
201
208
|
has enabled: true, interval_in_minutes is required (finite number > 0);
|
|
202
209
|
weak_peak_cut also requires min_value (finite ROE % > 0). hard_timeout
|
|
203
|
-
|
|
204
|
-
|
|
210
|
+
fires in either phase once interval_in_minutes elapses since entry (the timer
|
|
211
|
+
starts at entry and never resets); the only exception is the single tick that
|
|
212
|
+
first advances into phase 2, where tier advance wins that tick.
|
|
205
213
|
dead_weight_cut: stagnation clock resets every tick while current ROE > 0 (mark vs entry);
|
|
206
214
|
after interval_in_minutes with current ROE ≤ 0 on the tick, close with dead_weight_cut.
|
|
207
215
|
|
|
@@ -308,32 +316,35 @@ strategy
|
|
|
308
316
|
enabled boolean No Default true
|
|
309
317
|
|
|
310
318
|
scanners[]
|
|
311
|
-
name
|
|
312
|
-
type
|
|
313
|
-
|
|
314
|
-
blocked_assets
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
319
|
+
name string Yes Unique name referenced in actions.scanners
|
|
320
|
+
type string Yes emerging_movers | momentum | prescreener | oi_tracker | position_tracker | external_scanner
|
|
321
|
+
interval_seconds number No Built-in scanners only; integer seconds (v2.0.0+). Rejected: legacy interval duration string.
|
|
322
|
+
blocked_assets array No Built-in scanners only
|
|
323
|
+
config object No Built-in scanner config (see: senpi guide scanners)
|
|
324
|
+
advanced object No
|
|
325
|
+
|
|
326
|
+
external_scanner (v2 supervised) — distinct field set:
|
|
327
|
+
path string Yes scan module directory
|
|
328
|
+
entrypoint string Yes module exporting scan(inputs, ctx)
|
|
329
|
+
interval_seconds number No tick cadence (integer seconds; default 30)
|
|
330
|
+
timeout_seconds number No per-tick budget (default = interval_seconds)
|
|
331
|
+
default_signal_validity_seconds number Yes fallback signal TTL (seconds)
|
|
332
|
+
state_history_max_count number No ctx.state bound; 0/unset = history disabled
|
|
333
|
+
inputs object No author knobs → scan(inputs, ctx)
|
|
334
|
+
signal_data_schema object Yes per-data-key { type, required? }
|
|
335
|
+
type: string | number | boolean | object | array
|
|
336
|
+
external_scanner rejects: interval, depends_on, outputs, config, params, blocked_assets
|
|
337
|
+
|
|
327
338
|
Use namespaced prompt keys only:
|
|
328
339
|
{{signal_<scanner_name>}} and {{context_<scanner_name>}}
|
|
329
340
|
|
|
330
341
|
actions[]
|
|
331
342
|
name string Yes
|
|
332
343
|
action_type string Yes OPEN_POSITION
|
|
333
|
-
decision_mode string
|
|
334
|
-
decision_model string No
|
|
344
|
+
decision_mode string No llm | rule | none (default none)
|
|
345
|
+
decision_model string No Recommended when decision_mode: llm
|
|
335
346
|
scanners string[] No Scanner names this action listens to
|
|
336
|
-
min_confidence number No 0–10
|
|
347
|
+
min_confidence number No 0–10 (omitted ⇒ effective floor 1)
|
|
337
348
|
context string[] No [signal]
|
|
338
349
|
decision_prompt string No Prompt template with {{signal}}
|
|
339
350
|
params object No
|
|
@@ -356,23 +367,33 @@ exit
|
|
|
356
367
|
phase1.enabled and phase2.enabled cannot both be false. Each tier row:
|
|
357
368
|
lock_hw_pct [0,100]. Unknown keys under exit / presets / phase1 / phase2 / tiers throw
|
|
358
369
|
DslConfigValidationError (UNKNOWN_DSL_CONFIG_KEY) at load. DSL parse also
|
|
359
|
-
enforces strictly increasing trigger_pct per tier list
|
|
360
|
-
|
|
370
|
+
enforces strictly increasing trigger_pct per tier list (trigger_pct itself only
|
|
371
|
+
needs to be > 0 and finite — no upper cap, since ROE can exceed 100% under
|
|
372
|
+
leverage), bounds on interval/max_loss/lock_hw, and integer breach counts; see
|
|
373
|
+
dsl-reference
|
|
361
374
|
Config validation. See: senpi guide dsl
|
|
362
375
|
|
|
363
376
|
risk
|
|
364
|
-
|
|
377
|
+
data_retention_seconds number No integer 3600–604800; seconds to retain audit logs
|
|
365
378
|
guard_rails object No Guardrail thresholds (see below)
|
|
366
379
|
|
|
367
380
|
risk.guard_rails
|
|
368
381
|
daily_loss_limit_pct number No Max daily loss as % of account value at day open. Gate CLOSED when exceeded. Uses Hyperliquid trading PnL (excludes deposits/withdrawals).
|
|
369
382
|
max_entries_per_day number No Opt-in: max trade entries per day; omit to skip gate 5. Counts open+closed positions opened today via MCP (MCP: Unix seconds).
|
|
370
383
|
bypass_max_entries_per_day_on_profit boolean No At cap: keep gate 5 OPEN if today_snapshot.pnl.delta_since_open > 0 (default: false). Reuses strategy_get_pnl_and_account_value_history with gates 1–2 or one lazy fetch at cap only.
|
|
371
|
-
max_consecutive_losses number No Opt-in with
|
|
372
|
-
|
|
384
|
+
max_consecutive_losses number No Opt-in with cooldown_seconds: gate 3; omit both to skip. Stateless: derived from trade history each tick.
|
|
385
|
+
cooldown_seconds number No Min 60; opt-in with max_consecutive_losses: cooldown from last loss close (seconds)
|
|
373
386
|
drawdown_halt_pct number No 0–100; gate CLOSED when PnL drawdown from peak exceeds this %. PnL-based (immune to deposits/withdrawals).
|
|
374
387
|
drawdown_reset_on_day_rollover boolean No Reset PnL peak at UTC midnight (default: false; peak carries from prior ~24h)
|
|
375
|
-
|
|
388
|
+
per_asset_cooldown_seconds number No Min 300; gate COOLDOWN for a specific asset when closed within this many seconds. Checked via MCP per entry attempt.
|
|
389
|
+
|
|
390
|
+
telemetry
|
|
391
|
+
enabled boolean No Default true. Set false to disable OTEL event recording.
|
|
392
|
+
url string No Ingestion URL override (else SENPI_TRACKING_URL env, else built-in default).
|
|
393
|
+
Empty after env resolution degrades to default — never blocks boot.
|
|
394
|
+
flush_interval_seconds number No Integer seconds between telemetry flushes.
|
|
395
|
+
Rejected: legacy flush_interval_ms (renamed in v2.0.0).
|
|
396
|
+
A missing telemetry block defaults to enabled=true — existing recipes need no change.
|
|
376
397
|
|
|
377
398
|
Environment substitution: \${VAR} and \${VAR:-default} resolved at load time.
|
|
378
399
|
`.trim();
|
|
@@ -392,7 +413,7 @@ strategy:
|
|
|
392
413
|
scanners:
|
|
393
414
|
- name: emerging_movers
|
|
394
415
|
type: emerging_movers
|
|
395
|
-
|
|
416
|
+
interval_seconds: 60
|
|
396
417
|
config:
|
|
397
418
|
topN: 20
|
|
398
419
|
minRankJump: 5
|
|
@@ -401,7 +422,7 @@ scanners:
|
|
|
401
422
|
actions:
|
|
402
423
|
- name: log_signals
|
|
403
424
|
action_type: OPEN_POSITION
|
|
404
|
-
decision_mode:
|
|
425
|
+
decision_mode: none
|
|
405
426
|
scanners: [emerging_movers]
|
|
406
427
|
min_confidence: 0
|
|
407
428
|
|
|
@@ -421,7 +442,7 @@ export const CHEATSHEET_TEXT = `
|
|
|
421
442
|
Senpi Plugin Commands Cheatsheet
|
|
422
443
|
================================
|
|
423
444
|
|
|
424
|
-
|
|
445
|
+
Core CLI commands and gateway methods exposed by @senpi-ai/runtime.
|
|
425
446
|
|
|
426
447
|
CLI Commands
|
|
427
448
|
------------
|
|
@@ -481,13 +502,6 @@ senpi action — Action layer (execution history, decisions)
|
|
|
481
502
|
-l, --limit <n> Max rows
|
|
482
503
|
--json Raw JSON output
|
|
483
504
|
|
|
484
|
-
senpi external-scanner — Ingest external scanner data (pure-JSON output)
|
|
485
|
-
external-scanner ingest Call senpi.ingestExternalScannerData and emit JSON
|
|
486
|
-
--address <wallet> Strategy wallet address (required)
|
|
487
|
-
--scanner <name> Configured external_scanner name (required)
|
|
488
|
-
--payload <json> Inline JSON payload (asset/direction/score/signal_type/data/signals)
|
|
489
|
-
--payload-path <file> Read JSON payload from file (alternative to --payload)
|
|
490
|
-
|
|
491
505
|
senpi guide — In-shell reference
|
|
492
506
|
guide Overview and quick commands
|
|
493
507
|
guide scanners Scanner types and config fields
|
|
@@ -546,14 +560,6 @@ senpi.getActionHistory
|
|
|
546
560
|
outcomeFilter? ("with_decision" | "executed") — with_decision: decision != null; executed: decision.execute === true
|
|
547
561
|
Success: { history: ActionExecutionRecord[] }
|
|
548
562
|
|
|
549
|
-
senpi.ingestExternalScannerData
|
|
550
|
-
Params: address (string, required), scanner (string, required), plus either
|
|
551
|
-
single-ingest fields { asset?, direction?, score?, signal_type?, data }
|
|
552
|
-
or a batch signals array [{ asset, direction?, score?, signal_type?, data }]
|
|
553
|
-
Success: { accepted, address, scanner, timestamp, signalCount, contextUpdated }
|
|
554
|
-
Errors: INVALID_REQUEST, NOT_FOUND, UNAVAILABLE
|
|
555
|
-
Notes: Context-producing scanners accept single-item ingests only in v1.
|
|
556
|
-
|
|
557
563
|
Full cheatsheet with sample responses: docs/plugin-commands-cheatsheet.md
|
|
558
564
|
`.trim();
|
|
559
565
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guide-commands.js","sourceRoot":"","sources":["../../src/cli/guide-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,aAAa,GACjB,0EAA0E,CAAC;AAE7E,+EAA+E;AAE/E,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC;qBACtB,OAAO;;;;;;;;;;;;;;;;;;;CAmB3B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"guide-commands.js","sourceRoot":"","sources":["../../src/cli/guide-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,aAAa,GACjB,0EAA0E,CAAC;AAE7E,+EAA+E;AAE/E,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC;qBACtB,OAAO;;;;;;;;;;;;;;;;;;;CAmB3B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHrB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CpB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0FhB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GnB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCpB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2H9B,CAAC,IAAI,EAAE,CAAC;AAYT;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAuB,EACvB,OAAe;IAEf,MAAM,KAAK,GAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAsB;SACvD,WAAW,CAAC,0CAA0C,CAAC,CAAC;IAE3D,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,UAAU,CAAsB;SAC5C,WAAW,CAAC,iCAAiC,CAAC;SAC9C,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,SAAS,CAAsB;SAC3C,WAAW,CAAC,iCAAiC,CAAC;SAC9C,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,KAAK,CAAsB;SACvC,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,UAAU,CAAsB;SAC5C,WAAW,CAAC,uCAAuC,CAAC;SACpD,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAsB;SAC1C,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,SAAS,CAAsB;SAC3C,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,OAAO,KAAK,aAAa,IAAI,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"senpi-commands.d.ts","sourceRoot":"","sources":["../../src/cli/senpi-commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE;IAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,gBAAgB,GAAG,OAAO,CAAA;CAAE,GAChF,IAAI,
|
|
1
|
+
{"version":3,"file":"senpi-commands.d.ts","sourceRoot":"","sources":["../../src/cli/senpi-commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE;IAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,gBAAgB,GAAG,OAAO,CAAA;CAAE,GAChF,IAAI,CA8+BN;AAoMD,kEAAkE;AAClE,UAAU,gBAAgB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACvD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC/D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC9D,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACtE,MAAM,CACJ,EAAE,EACE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzD,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GACzE,gBAAgB,CAAC;CACrB"}
|
|
@@ -822,114 +822,6 @@ export function registerSenpiCli(program) {
|
|
|
822
822
|
console.log(`${r.name}: ${status}`);
|
|
823
823
|
}
|
|
824
824
|
});
|
|
825
|
-
const externalScanner = senpi.command("external-scanner");
|
|
826
|
-
externalScanner.description("External scanner ingest (pure-JSON output for producers)");
|
|
827
|
-
externalScanner
|
|
828
|
-
.command("ingest")
|
|
829
|
-
.description("Ingest external scanner data into a running runtime (calls senpi.ingestExternalScannerData). Always emits JSON.")
|
|
830
|
-
.option("--address <wallet>", "Strategy wallet address the runtime is bound to")
|
|
831
|
-
.option("--scanner <name>", "Configured external_scanner name in the runtime YAML")
|
|
832
|
-
.option("--payload <json>", "Inline JSON payload with ingest fields (asset/direction/score/signal_type/data/signals)")
|
|
833
|
-
.option("--payload-path <file>", "Path to a JSON file containing the ingest payload (alternative to --payload)")
|
|
834
|
-
.action(async (opts) => {
|
|
835
|
-
const address = typeof opts.address === "string" ? opts.address.trim() : "";
|
|
836
|
-
const scanner = typeof opts.scanner === "string" ? opts.scanner.trim() : "";
|
|
837
|
-
if (!address) {
|
|
838
|
-
emitCliJsonError("CLI_INVALID_ARGS", "--address is required (strategy wallet address of a running runtime).");
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
if (!scanner) {
|
|
842
|
-
emitCliJsonError("CLI_INVALID_ARGS", "--scanner is required (configured external_scanner name).");
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
const hasPayload = typeof opts.payload === "string" && opts.payload.length > 0;
|
|
846
|
-
const hasPayloadPath = typeof opts.payloadPath === "string" && opts.payloadPath.length > 0;
|
|
847
|
-
if (hasPayload && hasPayloadPath) {
|
|
848
|
-
emitCliJsonError("CLI_INVALID_ARGS", "Provide either --payload or --payload-path, not both.");
|
|
849
|
-
return;
|
|
850
|
-
}
|
|
851
|
-
let payloadText;
|
|
852
|
-
if (hasPayload) {
|
|
853
|
-
payloadText = opts.payload;
|
|
854
|
-
}
|
|
855
|
-
else if (hasPayloadPath) {
|
|
856
|
-
try {
|
|
857
|
-
payloadText = readFileSync(path.resolve(process.cwd(), opts.payloadPath), "utf8");
|
|
858
|
-
}
|
|
859
|
-
catch (err) {
|
|
860
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
861
|
-
emitCliJsonError("CLI_READ_FAILED", `Failed to read --payload-path: ${msg}`);
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
let payloadObj = {};
|
|
866
|
-
if (payloadText !== undefined) {
|
|
867
|
-
try {
|
|
868
|
-
const parsed = JSON.parse(payloadText);
|
|
869
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
870
|
-
emitCliJsonError("CLI_INVALID_JSON", "Payload must be a JSON object.");
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
|
-
payloadObj = parsed;
|
|
874
|
-
}
|
|
875
|
-
catch (err) {
|
|
876
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
877
|
-
emitCliJsonError("CLI_INVALID_JSON", `Payload is not valid JSON: ${msg}`);
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
const params = {
|
|
882
|
-
...payloadObj,
|
|
883
|
-
address,
|
|
884
|
-
scanner,
|
|
885
|
-
};
|
|
886
|
-
const result = spawnSync(process.argv[0], [
|
|
887
|
-
process.argv[1],
|
|
888
|
-
"gateway",
|
|
889
|
-
"call",
|
|
890
|
-
"senpi.ingestExternalScannerData",
|
|
891
|
-
"--json",
|
|
892
|
-
"--params",
|
|
893
|
-
JSON.stringify(params),
|
|
894
|
-
], {
|
|
895
|
-
stdio: ["inherit", "pipe", "pipe"],
|
|
896
|
-
cwd: process.cwd(),
|
|
897
|
-
encoding: "utf8",
|
|
898
|
-
});
|
|
899
|
-
const stdout = typeof result.stdout === "string" ? result.stdout : "";
|
|
900
|
-
let data = null;
|
|
901
|
-
if (stdout.length > 0) {
|
|
902
|
-
try {
|
|
903
|
-
data = JSON.parse(stdout);
|
|
904
|
-
}
|
|
905
|
-
catch {
|
|
906
|
-
data = null;
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
if (!data) {
|
|
910
|
-
const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
|
|
911
|
-
emitCliJsonError("CLI_GATEWAY_UNAVAILABLE", stderr.length > 0
|
|
912
|
-
? `Gateway call failed: ${stderr}`
|
|
913
|
-
: "Gateway call failed with no parseable response. Is the gateway running? (openclaw gateway run)");
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
if (data.ok === false) {
|
|
917
|
-
const err = (data.error ?? {});
|
|
918
|
-
process.stdout.write(JSON.stringify({
|
|
919
|
-
ok: false,
|
|
920
|
-
error: {
|
|
921
|
-
code: typeof err.code === "string" ? err.code : "UNAVAILABLE",
|
|
922
|
-
message: typeof err.message === "string"
|
|
923
|
-
? err.message
|
|
924
|
-
: "External scanner ingest failed.",
|
|
925
|
-
},
|
|
926
|
-
}) + "\n");
|
|
927
|
-
process.exitCode = 1;
|
|
928
|
-
return;
|
|
929
|
-
}
|
|
930
|
-
const payload = (data.payload ?? data);
|
|
931
|
-
process.stdout.write(JSON.stringify({ ok: true, result: payload }) + "\n");
|
|
932
|
-
});
|
|
933
825
|
registerGuideCommands(senpi, VERSION);
|
|
934
826
|
}
|
|
935
827
|
function emitCliJsonError(code, message) {
|