@senpi/trading-runtime 1.0.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/README.md +117 -0
- package/dist/actions/decision-engine.d.ts +28 -0
- package/dist/actions/decision-engine.d.ts.map +1 -0
- package/dist/actions/decision-engine.js +65 -0
- package/dist/actions/decision-engine.js.map +1 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts +12 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.js +74 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -0
- package/dist/actions/llm-decision/factory.d.ts +17 -0
- package/dist/actions/llm-decision/factory.d.ts.map +1 -0
- package/dist/actions/llm-decision/factory.js +29 -0
- package/dist/actions/llm-decision/factory.js.map +1 -0
- package/dist/actions/llm-decision/index.d.ts +8 -0
- package/dist/actions/llm-decision/index.d.ts.map +1 -0
- package/dist/actions/llm-decision/index.js +5 -0
- package/dist/actions/llm-decision/index.js.map +1 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts +14 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js +58 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -0
- package/dist/actions/llm-decision/shared.d.ts +41 -0
- package/dist/actions/llm-decision/shared.d.ts.map +1 -0
- package/dist/actions/llm-decision/shared.js +117 -0
- package/dist/actions/llm-decision/shared.js.map +1 -0
- package/dist/actions/open-position/open-position.action.d.ts +15 -0
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -0
- package/dist/actions/open-position/open-position.action.js +302 -0
- package/dist/actions/open-position/open-position.action.js.map +1 -0
- package/dist/actions/types.d.ts +123 -0
- package/dist/actions/types.d.ts.map +1 -0
- package/dist/actions/types.js +3 -0
- package/dist/actions/types.js.map +1 -0
- package/dist/cli/guide-commands.d.ts +26 -0
- package/dist/cli/guide-commands.d.ts.map +1 -0
- package/dist/cli/guide-commands.js +332 -0
- package/dist/cli/guide-commands.js.map +1 -0
- package/dist/cli/senpi-commands.d.ts +22 -0
- package/dist/cli/senpi-commands.d.ts.map +1 -0
- package/dist/cli/senpi-commands.js +138 -0
- package/dist/cli/senpi-commands.js.map +1 -0
- package/dist/constants/dsl/index.d.ts +39 -0
- package/dist/constants/dsl/index.d.ts.map +1 -0
- package/dist/constants/dsl/index.js +39 -0
- package/dist/constants/dsl/index.js.map +1 -0
- package/dist/context/context-builder.d.ts +14 -0
- package/dist/context/context-builder.d.ts.map +1 -0
- package/dist/context/context-builder.js +36 -0
- package/dist/context/context-builder.js.map +1 -0
- package/dist/context/index.d.ts +5 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +5 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/interpolate.d.ts +6 -0
- package/dist/context/interpolate.d.ts.map +1 -0
- package/dist/context/interpolate.js +15 -0
- package/dist/context/interpolate.js.map +1 -0
- package/dist/context/providers/asset-trend.provider.d.ts +42 -0
- package/dist/context/providers/asset-trend.provider.d.ts.map +1 -0
- package/dist/context/providers/asset-trend.provider.js +94 -0
- package/dist/context/providers/asset-trend.provider.js.map +1 -0
- package/dist/context/providers/index.d.ts +5 -0
- package/dist/context/providers/index.d.ts.map +1 -0
- package/dist/context/providers/index.js +5 -0
- package/dist/context/providers/index.js.map +1 -0
- package/dist/context/providers/regime.provider.d.ts +14 -0
- package/dist/context/providers/regime.provider.d.ts.map +1 -0
- package/dist/context/providers/regime.provider.js +29 -0
- package/dist/context/providers/regime.provider.js.map +1 -0
- package/dist/context/providers/signal.provider.d.ts +11 -0
- package/dist/context/providers/signal.provider.d.ts.map +1 -0
- package/dist/context/providers/signal.provider.js +27 -0
- package/dist/context/providers/signal.provider.js.map +1 -0
- package/dist/context/providers/strategy.provider.d.ts +14 -0
- package/dist/context/providers/strategy.provider.d.ts.map +1 -0
- package/dist/context/providers/strategy.provider.js +68 -0
- package/dist/context/providers/strategy.provider.js.map +1 -0
- package/dist/context/types.d.ts +30 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +2 -0
- package/dist/context/types.js.map +1 -0
- package/dist/dsl/config/index.d.ts +43 -0
- package/dist/dsl/config/index.d.ts.map +1 -0
- package/dist/dsl/config/index.js +108 -0
- package/dist/dsl/config/index.js.map +1 -0
- package/dist/dsl/constants/index.d.ts +3 -0
- package/dist/dsl/constants/index.d.ts.map +1 -0
- package/dist/dsl/constants/index.js +3 -0
- package/dist/dsl/constants/index.js.map +1 -0
- package/dist/dsl/engine/index.d.ts +7 -0
- package/dist/dsl/engine/index.d.ts.map +1 -0
- package/dist/dsl/engine/index.js +123 -0
- package/dist/dsl/engine/index.js.map +1 -0
- package/dist/dsl/events/bus-types.d.ts +7 -0
- package/dist/dsl/events/bus-types.d.ts.map +1 -0
- package/dist/dsl/events/bus-types.js +6 -0
- package/dist/dsl/events/bus-types.js.map +1 -0
- package/dist/dsl/events/guards.d.ts +17 -0
- package/dist/dsl/events/guards.d.ts.map +1 -0
- package/dist/dsl/events/guards.js +94 -0
- package/dist/dsl/events/guards.js.map +1 -0
- package/dist/dsl/events/handlers.d.ts +15 -0
- package/dist/dsl/events/handlers.d.ts.map +1 -0
- package/dist/dsl/events/handlers.js +229 -0
- package/dist/dsl/events/handlers.js.map +1 -0
- package/dist/dsl/events/index.d.ts +4 -0
- package/dist/dsl/events/index.d.ts.map +1 -0
- package/dist/dsl/events/index.js +4 -0
- package/dist/dsl/events/index.js.map +1 -0
- package/dist/dsl/index.d.ts +13 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +35 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl/monitor/index.d.ts +18 -0
- package/dist/dsl/monitor/index.d.ts.map +1 -0
- package/dist/dsl/monitor/index.js +296 -0
- package/dist/dsl/monitor/index.js.map +1 -0
- package/dist/dsl/plugin/index.d.ts +29 -0
- package/dist/dsl/plugin/index.d.ts.map +1 -0
- package/dist/dsl/plugin/index.js +85 -0
- package/dist/dsl/plugin/index.js.map +1 -0
- package/dist/dsl/types/index.d.ts +3 -0
- package/dist/dsl/types/index.d.ts.map +1 -0
- package/dist/dsl/types/index.js +3 -0
- package/dist/dsl/types/index.js.map +1 -0
- package/dist/health/index.d.ts +9 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js +9 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +218 -0
- package/dist/index.js.map +1 -0
- package/dist/risk/index.d.ts +9 -0
- package/dist/risk/index.d.ts.map +1 -0
- package/dist/risk/index.js +9 -0
- package/dist/risk/index.js.map +1 -0
- package/dist/runtime/action-registry.d.ts +12 -0
- package/dist/runtime/action-registry.d.ts.map +1 -0
- package/dist/runtime/action-registry.js +18 -0
- package/dist/runtime/action-registry.js.map +1 -0
- package/dist/runtime/build-action-scan-payload.d.ts +20 -0
- package/dist/runtime/build-action-scan-payload.d.ts.map +1 -0
- package/dist/runtime/build-action-scan-payload.js +52 -0
- package/dist/runtime/build-action-scan-payload.js.map +1 -0
- package/dist/runtime/bus.d.ts +6 -0
- package/dist/runtime/bus.d.ts.map +1 -0
- package/dist/runtime/bus.js +19 -0
- package/dist/runtime/bus.js.map +1 -0
- package/dist/runtime/create-action-context.d.ts +34 -0
- package/dist/runtime/create-action-context.d.ts.map +1 -0
- package/dist/runtime/create-action-context.js +22 -0
- package/dist/runtime/create-action-context.js.map +1 -0
- package/dist/runtime/create-actions.d.ts +30 -0
- package/dist/runtime/create-actions.d.ts.map +1 -0
- package/dist/runtime/create-actions.js +78 -0
- package/dist/runtime/create-actions.js.map +1 -0
- package/dist/runtime/create-runtime-context.d.ts +33 -0
- package/dist/runtime/create-runtime-context.d.ts.map +1 -0
- package/dist/runtime/create-runtime-context.js +32 -0
- package/dist/runtime/create-runtime-context.js.map +1 -0
- package/dist/runtime/create-scanner-module.d.ts +14 -0
- package/dist/runtime/create-scanner-module.d.ts.map +1 -0
- package/dist/runtime/create-scanner-module.js +26 -0
- package/dist/runtime/create-scanner-module.js.map +1 -0
- package/dist/runtime/create-scanner-providers-for-run.d.ts +20 -0
- package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -0
- package/dist/runtime/create-scanner-providers-for-run.js +34 -0
- package/dist/runtime/create-scanner-providers-for-run.js.map +1 -0
- package/dist/runtime/default-state-dir.d.ts +10 -0
- package/dist/runtime/default-state-dir.d.ts.map +1 -0
- package/dist/runtime/default-state-dir.js +22 -0
- package/dist/runtime/default-state-dir.js.map +1 -0
- package/dist/runtime/env-resolve.d.ts +17 -0
- package/dist/runtime/env-resolve.d.ts.map +1 -0
- package/dist/runtime/env-resolve.js +45 -0
- package/dist/runtime/env-resolve.js.map +1 -0
- package/dist/runtime/hook-system.d.ts +7 -0
- package/dist/runtime/hook-system.d.ts.map +1 -0
- package/dist/runtime/hook-system.js +16 -0
- package/dist/runtime/hook-system.js.map +1 -0
- package/dist/runtime/index.d.ts +37 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +26 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/load-trading-strategy.d.ts +18 -0
- package/dist/runtime/load-trading-strategy.d.ts.map +1 -0
- package/dist/runtime/load-trading-strategy.js +51 -0
- package/dist/runtime/load-trading-strategy.js.map +1 -0
- package/dist/runtime/map-exit-config.d.ts +12 -0
- package/dist/runtime/map-exit-config.d.ts.map +1 -0
- package/dist/runtime/map-exit-config.js +89 -0
- package/dist/runtime/map-exit-config.js.map +1 -0
- package/dist/runtime/map-strategies-registration.d.ts +12 -0
- package/dist/runtime/map-strategies-registration.d.ts.map +1 -0
- package/dist/runtime/map-strategies-registration.js +52 -0
- package/dist/runtime/map-strategies-registration.js.map +1 -0
- package/dist/runtime/map-strategies.d.ts +12 -0
- package/dist/runtime/map-strategies.d.ts.map +1 -0
- package/dist/runtime/map-strategies.js +46 -0
- package/dist/runtime/map-strategies.js.map +1 -0
- package/dist/runtime/notifications.d.ts +10 -0
- package/dist/runtime/notifications.d.ts.map +1 -0
- package/dist/runtime/notifications.js +14 -0
- package/dist/runtime/notifications.js.map +1 -0
- package/dist/runtime/parse-interval.d.ts +11 -0
- package/dist/runtime/parse-interval.d.ts.map +1 -0
- package/dist/runtime/parse-interval.js +35 -0
- package/dist/runtime/parse-interval.js.map +1 -0
- package/dist/runtime/reconcile-state.d.ts +25 -0
- package/dist/runtime/reconcile-state.d.ts.map +1 -0
- package/dist/runtime/reconcile-state.js +114 -0
- package/dist/runtime/reconcile-state.js.map +1 -0
- package/dist/runtime/risk-guard.d.ts +6 -0
- package/dist/runtime/risk-guard.d.ts.map +1 -0
- package/dist/runtime/risk-guard.js +14 -0
- package/dist/runtime/risk-guard.js.map +1 -0
- package/dist/runtime/run.d.ts +21 -0
- package/dist/runtime/run.d.ts.map +1 -0
- package/dist/runtime/run.js +43 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/runtime.d.ts +40 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +249 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/scanner-registry.d.ts +22 -0
- package/dist/runtime/scanner-registry.d.ts.map +1 -0
- package/dist/runtime/scanner-registry.js +72 -0
- package/dist/runtime/scanner-registry.js.map +1 -0
- package/dist/runtime/strategy-registry.d.ts +49 -0
- package/dist/runtime/strategy-registry.d.ts.map +1 -0
- package/dist/runtime/strategy-registry.js +150 -0
- package/dist/runtime/strategy-registry.js.map +1 -0
- package/dist/runtime/trading-strategy-config.d.ts +6 -0
- package/dist/runtime/trading-strategy-config.d.ts.map +1 -0
- package/dist/runtime/trading-strategy-config.js +5 -0
- package/dist/runtime/trading-strategy-config.js.map +1 -0
- package/dist/runtime/trading-strategy-schema.d.ts +19757 -0
- package/dist/runtime/trading-strategy-schema.d.ts.map +1 -0
- package/dist/runtime/trading-strategy-schema.js +107 -0
- package/dist/runtime/trading-strategy-schema.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/index.d.ts +3 -0
- package/dist/scanners/__tests__/fixtures/index.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/index.js +3 -0
- package/dist/scanners/__tests__/fixtures/index.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/scan-results.d.ts +23 -0
- package/dist/scanners/__tests__/fixtures/scan-results.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/scan-results.js +128 -0
- package/dist/scanners/__tests__/fixtures/scan-results.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/signals.d.ts +18 -0
- package/dist/scanners/__tests__/fixtures/signals.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/signals.js +84 -0
- package/dist/scanners/__tests__/fixtures/signals.js.map +1 -0
- package/dist/scanners/__tests__/test-helpers.d.ts +4 -0
- package/dist/scanners/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/scanners/__tests__/test-helpers.js +23 -0
- package/dist/scanners/__tests__/test-helpers.js.map +1 -0
- package/dist/scanners/artifacts.d.ts +119 -0
- package/dist/scanners/artifacts.d.ts.map +1 -0
- package/dist/scanners/artifacts.js +72 -0
- package/dist/scanners/artifacts.js.map +1 -0
- package/dist/scanners/create-scanner.d.ts +13 -0
- package/dist/scanners/create-scanner.d.ts.map +1 -0
- package/dist/scanners/create-scanner.js +11 -0
- package/dist/scanners/create-scanner.js.map +1 -0
- package/dist/scanners/engine/config-validator.d.ts +7 -0
- package/dist/scanners/engine/config-validator.d.ts.map +1 -0
- package/dist/scanners/engine/config-validator.js +16 -0
- package/dist/scanners/engine/config-validator.js.map +1 -0
- package/dist/scanners/engine/data-providers.d.ts +43 -0
- package/dist/scanners/engine/data-providers.d.ts.map +1 -0
- package/dist/scanners/engine/data-providers.js +8 -0
- package/dist/scanners/engine/data-providers.js.map +1 -0
- package/dist/scanners/engine/engine.d.ts +76 -0
- package/dist/scanners/engine/engine.d.ts.map +1 -0
- package/dist/scanners/engine/engine.js +399 -0
- package/dist/scanners/engine/engine.js.map +1 -0
- package/dist/scanners/engine/index.d.ts +9 -0
- package/dist/scanners/engine/index.d.ts.map +1 -0
- package/dist/scanners/engine/index.js +7 -0
- package/dist/scanners/engine/index.js.map +1 -0
- package/dist/scanners/engine/input-resolver.d.ts +21 -0
- package/dist/scanners/engine/input-resolver.d.ts.map +1 -0
- package/dist/scanners/engine/input-resolver.js +140 -0
- package/dist/scanners/engine/input-resolver.js.map +1 -0
- package/dist/scanners/engine/lifecycle.d.ts +21 -0
- package/dist/scanners/engine/lifecycle.d.ts.map +1 -0
- package/dist/scanners/engine/lifecycle.js +2 -0
- package/dist/scanners/engine/lifecycle.js.map +1 -0
- package/dist/scanners/engine/result-builder.d.ts +30 -0
- package/dist/scanners/engine/result-builder.d.ts.map +1 -0
- package/dist/scanners/engine/result-builder.js +129 -0
- package/dist/scanners/engine/result-builder.js.map +1 -0
- package/dist/scanners/engine/strategy-registry.d.ts +45 -0
- package/dist/scanners/engine/strategy-registry.d.ts.map +1 -0
- package/dist/scanners/engine/strategy-registry.js +93 -0
- package/dist/scanners/engine/strategy-registry.js.map +1 -0
- package/dist/scanners/events.d.ts +41 -0
- package/dist/scanners/events.d.ts.map +1 -0
- package/dist/scanners/events.js +33 -0
- package/dist/scanners/events.js.map +1 -0
- package/dist/scanners/implementations/emerging-movers.d.ts +212 -0
- package/dist/scanners/implementations/emerging-movers.d.ts.map +1 -0
- package/dist/scanners/implementations/emerging-movers.js +702 -0
- package/dist/scanners/implementations/emerging-movers.js.map +1 -0
- package/dist/scanners/implementations/index.d.ts +8 -0
- package/dist/scanners/implementations/index.d.ts.map +1 -0
- package/dist/scanners/implementations/index.js +8 -0
- package/dist/scanners/implementations/index.js.map +1 -0
- package/dist/scanners/implementations/indicators.d.ts +40 -0
- package/dist/scanners/implementations/indicators.d.ts.map +1 -0
- package/dist/scanners/implementations/indicators.js +114 -0
- package/dist/scanners/implementations/indicators.js.map +1 -0
- package/dist/scanners/implementations/market-regime.d.ts +52 -0
- package/dist/scanners/implementations/market-regime.d.ts.map +1 -0
- package/dist/scanners/implementations/market-regime.js +201 -0
- package/dist/scanners/implementations/market-regime.js.map +1 -0
- package/dist/scanners/implementations/momentum.d.ts +21 -0
- package/dist/scanners/implementations/momentum.d.ts.map +1 -0
- package/dist/scanners/implementations/momentum.js +128 -0
- package/dist/scanners/implementations/momentum.js.map +1 -0
- package/dist/scanners/implementations/oi-tracker.d.ts +13 -0
- package/dist/scanners/implementations/oi-tracker.d.ts.map +1 -0
- package/dist/scanners/implementations/oi-tracker.js +67 -0
- package/dist/scanners/implementations/oi-tracker.js.map +1 -0
- package/dist/scanners/implementations/opportunity.d.ts +104 -0
- package/dist/scanners/implementations/opportunity.d.ts.map +1 -0
- package/dist/scanners/implementations/opportunity.js +441 -0
- package/dist/scanners/implementations/opportunity.js.map +1 -0
- package/dist/scanners/implementations/prescreener.d.ts +20 -0
- package/dist/scanners/implementations/prescreener.d.ts.map +1 -0
- package/dist/scanners/implementations/prescreener.js +97 -0
- package/dist/scanners/implementations/prescreener.js.map +1 -0
- package/dist/scanners/implementations/sm-flip.d.ts +43 -0
- package/dist/scanners/implementations/sm-flip.d.ts.map +1 -0
- package/dist/scanners/implementations/sm-flip.js +200 -0
- package/dist/scanners/implementations/sm-flip.js.map +1 -0
- package/dist/scanners/index.d.ts +24 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +17 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/input-descriptors.d.ts +49 -0
- package/dist/scanners/input-descriptors.d.ts.map +1 -0
- package/dist/scanners/input-descriptors.js +35 -0
- package/dist/scanners/input-descriptors.js.map +1 -0
- package/dist/scanners/protocol/context.d.ts +71 -0
- package/dist/scanners/protocol/context.d.ts.map +1 -0
- package/dist/scanners/protocol/context.js +2 -0
- package/dist/scanners/protocol/context.js.map +1 -0
- package/dist/scanners/protocol/hooks.d.ts +18 -0
- package/dist/scanners/protocol/hooks.d.ts.map +1 -0
- package/dist/scanners/protocol/hooks.js +12 -0
- package/dist/scanners/protocol/hooks.js.map +1 -0
- package/dist/scanners/protocol/index.d.ts +5 -0
- package/dist/scanners/protocol/index.d.ts.map +1 -0
- package/dist/scanners/protocol/index.js +2 -0
- package/dist/scanners/protocol/index.js.map +1 -0
- package/dist/scanners/protocol/scanner.d.ts +47 -0
- package/dist/scanners/protocol/scanner.d.ts.map +1 -0
- package/dist/scanners/protocol/scanner.js +2 -0
- package/dist/scanners/protocol/scanner.js.map +1 -0
- package/dist/scanners/providers/adapter.d.ts +23 -0
- package/dist/scanners/providers/adapter.d.ts.map +1 -0
- package/dist/scanners/providers/adapter.js +227 -0
- package/dist/scanners/providers/adapter.js.map +1 -0
- package/dist/scanners/providers/cache.d.ts +20 -0
- package/dist/scanners/providers/cache.d.ts.map +1 -0
- package/dist/scanners/providers/cache.js +61 -0
- package/dist/scanners/providers/cache.js.map +1 -0
- package/dist/scanners/providers/client.d.ts +53 -0
- package/dist/scanners/providers/client.d.ts.map +1 -0
- package/dist/scanners/providers/client.js +174 -0
- package/dist/scanners/providers/client.js.map +1 -0
- package/dist/scanners/providers/factory.d.ts +42 -0
- package/dist/scanners/providers/factory.d.ts.map +1 -0
- package/dist/scanners/providers/factory.js +156 -0
- package/dist/scanners/providers/factory.js.map +1 -0
- package/dist/scanners/providers/types.d.ts +61 -0
- package/dist/scanners/providers/types.d.ts.map +1 -0
- package/dist/scanners/providers/types.js +6 -0
- package/dist/scanners/providers/types.js.map +1 -0
- package/dist/scanners/runtime-module.d.ts +54 -0
- package/dist/scanners/runtime-module.d.ts.map +1 -0
- package/dist/scanners/runtime-module.js +94 -0
- package/dist/scanners/runtime-module.js.map +1 -0
- package/dist/scanners/scanner-definition.d.ts +58 -0
- package/dist/scanners/scanner-definition.d.ts.map +1 -0
- package/dist/scanners/scanner-definition.js +19 -0
- package/dist/scanners/scanner-definition.js.map +1 -0
- package/dist/scanners/schema-utils.d.ts +6 -0
- package/dist/scanners/schema-utils.d.ts.map +1 -0
- package/dist/scanners/schema-utils.js +14 -0
- package/dist/scanners/schema-utils.js.map +1 -0
- package/dist/scanners/score-utils.d.ts +19 -0
- package/dist/scanners/score-utils.d.ts.map +1 -0
- package/dist/scanners/score-utils.js +47 -0
- package/dist/scanners/score-utils.js.map +1 -0
- package/dist/scanners/store/fs-utils.d.ts +12 -0
- package/dist/scanners/store/fs-utils.d.ts.map +1 -0
- package/dist/scanners/store/fs-utils.js +47 -0
- package/dist/scanners/store/fs-utils.js.map +1 -0
- package/dist/scanners/store/index.d.ts +5 -0
- package/dist/scanners/store/index.d.ts.map +1 -0
- package/dist/scanners/store/index.js +5 -0
- package/dist/scanners/store/index.js.map +1 -0
- package/dist/scanners/store/runtime-store.d.ts +50 -0
- package/dist/scanners/store/runtime-store.d.ts.map +1 -0
- package/dist/scanners/store/runtime-store.js +91 -0
- package/dist/scanners/store/runtime-store.js.map +1 -0
- package/dist/scanners/store/shared-artifact-store.d.ts +31 -0
- package/dist/scanners/store/shared-artifact-store.d.ts.map +1 -0
- package/dist/scanners/store/shared-artifact-store.js +89 -0
- package/dist/scanners/store/shared-artifact-store.js.map +1 -0
- package/dist/scanners/store/signal-store.d.ts +36 -0
- package/dist/scanners/store/signal-store.d.ts.map +1 -0
- package/dist/scanners/store/signal-store.js +135 -0
- package/dist/scanners/store/signal-store.js.map +1 -0
- package/dist/scanners/types.d.ts +115 -0
- package/dist/scanners/types.d.ts.map +1 -0
- package/dist/scanners/types.js +3 -0
- package/dist/scanners/types.js.map +1 -0
- package/dist/scripts/run-dsl-standalone-live.d.ts +27 -0
- package/dist/scripts/run-dsl-standalone-live.d.ts.map +1 -0
- package/dist/scripts/run-dsl-standalone-live.js +207 -0
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -0
- package/dist/scripts/run-dsl-standalone-mock.d.ts +13 -0
- package/dist/scripts/run-dsl-standalone-mock.d.ts.map +1 -0
- package/dist/scripts/run-dsl-standalone-mock.js +255 -0
- package/dist/scripts/run-dsl-standalone-mock.js.map +1 -0
- package/dist/senpi/client.d.ts +70 -0
- package/dist/senpi/client.d.ts.map +1 -0
- package/dist/senpi/client.js +482 -0
- package/dist/senpi/client.js.map +1 -0
- package/dist/senpi/constants.d.ts +7 -0
- package/dist/senpi/constants.d.ts.map +1 -0
- package/dist/senpi/constants.js +7 -0
- package/dist/senpi/constants.js.map +1 -0
- package/dist/senpi/index.d.ts +3 -0
- package/dist/senpi/index.d.ts.map +1 -0
- package/dist/senpi/index.js +2 -0
- package/dist/senpi/index.js.map +1 -0
- package/dist/senpi/types.d.ts +132 -0
- package/dist/senpi/types.d.ts.map +1 -0
- package/dist/senpi/types.js +3 -0
- package/dist/senpi/types.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +3 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/paths.d.ts +8 -0
- package/dist/state/paths.d.ts.map +1 -0
- package/dist/state/paths.js +19 -0
- package/dist/state/paths.js.map +1 -0
- package/dist/state/state-manager.d.ts +56 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +213 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.d.ts.map +1 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/strategy/strategy-state.d.ts +47 -0
- package/dist/strategy/strategy-state.d.ts.map +1 -0
- package/dist/strategy/strategy-state.js +179 -0
- package/dist/strategy/strategy-state.js.map +1 -0
- package/dist/types/action.d.ts +15 -0
- package/dist/types/action.d.ts.map +1 -0
- package/dist/types/action.js +2 -0
- package/dist/types/action.js.map +1 -0
- package/dist/types/dsl/index.d.ts +156 -0
- package/dist/types/dsl/index.d.ts.map +1 -0
- package/dist/types/dsl/index.js +5 -0
- package/dist/types/dsl/index.js.map +1 -0
- package/dist/types/event-bus.d.ts +11 -0
- package/dist/types/event-bus.d.ts.map +1 -0
- package/dist/types/event-bus.js +6 -0
- package/dist/types/event-bus.js.map +1 -0
- package/dist/types/hooks.d.ts +27 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +15 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/notification.d.ts +4 -0
- package/dist/types/notification.d.ts.map +1 -0
- package/dist/types/notification.js +3 -0
- package/dist/types/notification.js.map +1 -0
- package/dist/types/runtime.d.ts +16 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/runtime.js +2 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/scanner.d.ts +59 -0
- package/dist/types/scanner.d.ts.map +1 -0
- package/dist/types/scanner.js +13 -0
- package/dist/types/scanner.js.map +1 -0
- package/dist/types/strategy.d.ts +97 -0
- package/dist/types/strategy.d.ts.map +1 -0
- package/dist/types/strategy.js +2 -0
- package/dist/types/strategy.js.map +1 -0
- package/dist/utils/logger/dsl.d.ts +8 -0
- package/dist/utils/logger/dsl.d.ts.map +1 -0
- package/dist/utils/logger/dsl.js +7 -0
- package/dist/utils/logger/dsl.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +65 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/response.d.ts +14 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +44 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/examples/.env.example +15 -0
- package/examples/README.md +75 -0
- package/examples/scanners-consumer-quickstart.mjs +134 -0
- package/examples/scanners-emerging-movers-v4.mjs +285 -0
- package/examples/scanners-live-mcp.mjs +208 -0
- package/examples/scanners-multi-strategy.mjs +165 -0
- package/examples/scanners-scheduled-events.mjs +95 -0
- package/examples/scanners-senpi-provider-client.mjs +182 -0
- package/examples/scanners-single-strategy.mjs +198 -0
- package/examples/strategies/README.md +45 -0
- package/examples/strategies/dsl-showcase.yaml +62 -0
- package/examples/strategies/fox.yaml +55 -0
- package/examples/strategies/minimal.yaml +41 -0
- package/examples/strategies/viper.yaml +63 -0
- package/examples/strategies/wolf.yaml +60 -0
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +111 -0
- package/openclaw.plugin.json +15 -0
- package/package.json +52 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { access, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
/** Returns true when a filesystem path exists and is accessible. */
|
|
4
|
+
export async function pathExists(path) {
|
|
5
|
+
try {
|
|
6
|
+
await access(path);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Serializes JSON with stable formatting and writes atomically. */
|
|
14
|
+
export async function writeJsonAtomic(path, data) {
|
|
15
|
+
const content = `${JSON.stringify(data, null, 2)}\n`;
|
|
16
|
+
await writeTextAtomic(path, content);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Writes text atomically by writing to a temporary file then renaming in-place.
|
|
20
|
+
* Ensures readers never observe partial content.
|
|
21
|
+
*/
|
|
22
|
+
export async function writeTextAtomic(path, content) {
|
|
23
|
+
const dir = dirname(path);
|
|
24
|
+
const tmpPath = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random()
|
|
25
|
+
.toString(16)
|
|
26
|
+
.slice(2)}`;
|
|
27
|
+
await mkdir(dir, { recursive: true });
|
|
28
|
+
try {
|
|
29
|
+
await writeFile(tmpPath, content, "utf8");
|
|
30
|
+
await rename(tmpPath, path);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
await rm(tmpPath, { force: true });
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Reads and parses JSON; returns null when file does not exist or is invalid. */
|
|
38
|
+
export async function readJsonFile(path) {
|
|
39
|
+
try {
|
|
40
|
+
const raw = await readFile(path, "utf8");
|
|
41
|
+
return JSON.parse(raw);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=fs-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../../src/scanners/store/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,IAAa;IAC/D,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACrD,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IACjE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE;SACtE,QAAQ,CAAC,EAAE,CAAC;SACZ,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACd,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAY;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SignalStore } from "./signal-store.js";
|
|
2
|
+
export { RuntimeStore, type ScannerRuntimeState, type RuntimeSeed } from "./runtime-store.js";
|
|
3
|
+
export { SharedArtifactStore } from "./shared-artifact-store.js";
|
|
4
|
+
export { writeJsonAtomic, writeTextAtomic, readJsonFile, pathExists } from "./fs-utils.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SignalStore } from "./signal-store.js";
|
|
2
|
+
export { RuntimeStore } from "./runtime-store.js";
|
|
3
|
+
export { SharedArtifactStore } from "./shared-artifact-store.js";
|
|
4
|
+
export { writeJsonAtomic, writeTextAtomic, readJsonFile, pathExists } from "./fs-utils.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAA8C,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ScannerId } from "../types.js";
|
|
2
|
+
/** Persisted mutable state for one scanner instance under one strategy. */
|
|
3
|
+
export interface ScannerRuntimeState<Cfg = unknown, St = unknown> {
|
|
4
|
+
address: string;
|
|
5
|
+
scannerId: ScannerId;
|
|
6
|
+
config: Cfg;
|
|
7
|
+
state: St;
|
|
8
|
+
configVersion: number;
|
|
9
|
+
updatedAt: number;
|
|
10
|
+
}
|
|
11
|
+
/** Seed payload used when first creating runtime state via ensure(). */
|
|
12
|
+
export interface RuntimeSeed<Cfg = unknown, St = unknown> {
|
|
13
|
+
config: Cfg;
|
|
14
|
+
state?: St;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Persists scanner runtime lifecycle state (config + state + version).
|
|
18
|
+
* Keyed by (address, scannerId), with one scanner instance per strategy.
|
|
19
|
+
*/
|
|
20
|
+
export declare class RuntimeStore {
|
|
21
|
+
private readonly stateDir;
|
|
22
|
+
private readonly now;
|
|
23
|
+
/**
|
|
24
|
+
* @param stateDir Root runtime state directory.
|
|
25
|
+
* @param now Injectable clock for deterministic tests.
|
|
26
|
+
*/
|
|
27
|
+
constructor(stateDir: string, now?: () => number);
|
|
28
|
+
/** Reads persisted runtime state for a scanner instance. */
|
|
29
|
+
read<Cfg = unknown, St = unknown>(address: string, scannerId: ScannerId): Promise<ScannerRuntimeState<Cfg, St> | null>;
|
|
30
|
+
/** Writes full runtime state snapshot atomically. */
|
|
31
|
+
write<Cfg = unknown, St = unknown>(data: ScannerRuntimeState<Cfg, St>): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Ensures runtime exists and returns it.
|
|
34
|
+
* Creates a new runtime with version=1 when missing.
|
|
35
|
+
*/
|
|
36
|
+
ensure<Cfg = unknown, St = unknown>(address: string, scannerId: ScannerId, seed: RuntimeSeed<Cfg, St>): Promise<ScannerRuntimeState<Cfg, St>>;
|
|
37
|
+
/**
|
|
38
|
+
* Updates runtime config and increments configVersion.
|
|
39
|
+
* Throws when runtime does not exist to keep lifecycle explicit.
|
|
40
|
+
*/
|
|
41
|
+
setConfig<Cfg = unknown, St = unknown>(address: string, scannerId: ScannerId, config: Cfg): Promise<ScannerRuntimeState<Cfg, St>>;
|
|
42
|
+
/**
|
|
43
|
+
* Updates runtime scanner-local state while preserving current config/version.
|
|
44
|
+
* Throws when runtime does not exist to avoid implicit bootstrap.
|
|
45
|
+
*/
|
|
46
|
+
setState<Cfg = unknown, St = unknown>(address: string, scannerId: ScannerId, state: St): Promise<ScannerRuntimeState<Cfg, St>>;
|
|
47
|
+
/** Resolves runtime state file path for a scanner instance. */
|
|
48
|
+
private runtimePath;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=runtime-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-store.d.ts","sourceRoot":"","sources":["../../../src/scanners/store/runtime-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,EAAE,EAAE,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO;IACtD,MAAM,EAAE,GAAG,CAAC;IACZ,KAAK,CAAC,EAAE,EAAE,CAAC;CACZ;AAED;;;GAGG;AACH,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB;;;OAGG;gBAEgB,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAM,MAAiB;IAG/C,4DAA4D;IACtD,IAAI,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,EACpC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;IAM/C,qDAAqD;IAC/C,KAAK,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,EACrC,IAAI,EAAE,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IAIhB;;;OAGG;IACG,MAAM,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,EACtC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,GACzB,OAAO,CAAC,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAmBxC;;;OAGG;IACG,SAAS,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,EACzC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAmBxC;;;OAGG;IACG,QAAQ,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,EACxC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,EAAE,GACR,OAAO,CAAC,mBAAmB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAmBxC,+DAA+D;IAC/D,OAAO,CAAC,WAAW;CAUpB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { readJsonFile, writeJsonAtomic } from "./fs-utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Persists scanner runtime lifecycle state (config + state + version).
|
|
5
|
+
* Keyed by (address, scannerId), with one scanner instance per strategy.
|
|
6
|
+
*/
|
|
7
|
+
export class RuntimeStore {
|
|
8
|
+
stateDir;
|
|
9
|
+
now;
|
|
10
|
+
/**
|
|
11
|
+
* @param stateDir Root runtime state directory.
|
|
12
|
+
* @param now Injectable clock for deterministic tests.
|
|
13
|
+
*/
|
|
14
|
+
constructor(stateDir, now = Date.now) {
|
|
15
|
+
this.stateDir = stateDir;
|
|
16
|
+
this.now = now;
|
|
17
|
+
}
|
|
18
|
+
/** Reads persisted runtime state for a scanner instance. */
|
|
19
|
+
async read(address, scannerId) {
|
|
20
|
+
return readJsonFile(this.runtimePath(address, scannerId));
|
|
21
|
+
}
|
|
22
|
+
/** Writes full runtime state snapshot atomically. */
|
|
23
|
+
async write(data) {
|
|
24
|
+
await writeJsonAtomic(this.runtimePath(data.address, data.scannerId), data);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Ensures runtime exists and returns it.
|
|
28
|
+
* Creates a new runtime with version=1 when missing.
|
|
29
|
+
*/
|
|
30
|
+
async ensure(address, scannerId, seed) {
|
|
31
|
+
const existing = await this.read(address, scannerId);
|
|
32
|
+
if (existing) {
|
|
33
|
+
return existing;
|
|
34
|
+
}
|
|
35
|
+
const next = {
|
|
36
|
+
address,
|
|
37
|
+
scannerId,
|
|
38
|
+
config: seed.config,
|
|
39
|
+
state: (seed.state ?? {}),
|
|
40
|
+
configVersion: 1,
|
|
41
|
+
updatedAt: this.now(),
|
|
42
|
+
};
|
|
43
|
+
await this.write(next);
|
|
44
|
+
return next;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Updates runtime config and increments configVersion.
|
|
48
|
+
* Throws when runtime does not exist to keep lifecycle explicit.
|
|
49
|
+
*/
|
|
50
|
+
async setConfig(address, scannerId, config) {
|
|
51
|
+
const existing = await this.read(address, scannerId);
|
|
52
|
+
if (!existing) {
|
|
53
|
+
throw new Error(`Runtime state not found for strategy '${address}' and scanner '${scannerId}'.`);
|
|
54
|
+
}
|
|
55
|
+
const next = {
|
|
56
|
+
address,
|
|
57
|
+
scannerId,
|
|
58
|
+
config,
|
|
59
|
+
state: existing.state,
|
|
60
|
+
configVersion: existing.configVersion + 1,
|
|
61
|
+
updatedAt: this.now(),
|
|
62
|
+
};
|
|
63
|
+
await this.write(next);
|
|
64
|
+
return next;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Updates runtime scanner-local state while preserving current config/version.
|
|
68
|
+
* Throws when runtime does not exist to avoid implicit bootstrap.
|
|
69
|
+
*/
|
|
70
|
+
async setState(address, scannerId, state) {
|
|
71
|
+
const existing = await this.read(address, scannerId);
|
|
72
|
+
if (!existing) {
|
|
73
|
+
throw new Error(`Runtime state not found for strategy '${address}' and scanner '${scannerId}'.`);
|
|
74
|
+
}
|
|
75
|
+
const next = {
|
|
76
|
+
address,
|
|
77
|
+
scannerId,
|
|
78
|
+
config: existing.config,
|
|
79
|
+
state,
|
|
80
|
+
configVersion: existing.configVersion,
|
|
81
|
+
updatedAt: this.now(),
|
|
82
|
+
};
|
|
83
|
+
await this.write(next);
|
|
84
|
+
return next;
|
|
85
|
+
}
|
|
86
|
+
/** Resolves runtime state file path for a scanner instance. */
|
|
87
|
+
runtimePath(address, scannerId) {
|
|
88
|
+
return join(this.stateDir, "strategies", address, "scanners", scannerId, "runtime.json");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=runtime-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-store.js","sourceRoot":"","sources":["../../../src/scanners/store/runtime-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SharedArtifactContract, SharedArtifactValue } from "../artifacts.js";
|
|
2
|
+
import type { ArtifactEnvelope, SharedArtifactKey } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Stores strategy-scoped shared artifacts used by multiple scanners.
|
|
5
|
+
* Artifacts are separated from scanner-local runtime state to avoid coupling.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SharedArtifactStore {
|
|
8
|
+
private readonly stateDir;
|
|
9
|
+
private readonly now;
|
|
10
|
+
/**
|
|
11
|
+
* @param stateDir Root runtime state directory.
|
|
12
|
+
* @param now Injectable clock for deterministic freshness checks in tests.
|
|
13
|
+
*/
|
|
14
|
+
constructor(stateDir: string, now?: () => number);
|
|
15
|
+
/** Reads full artifact envelope for a strategy/key pair. */
|
|
16
|
+
loadEnvelope<T>(address: string, artifact: SharedArtifactKey | SharedArtifactContract<SharedArtifactKey>): Promise<ArtifactEnvelope<T> | null>;
|
|
17
|
+
/** Writes full artifact envelope for a strategy/key pair. */
|
|
18
|
+
saveEnvelope<T>(address: string, artifact: SharedArtifactKey | SharedArtifactContract<SharedArtifactKey>, value: ArtifactEnvelope<T>): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Reads artifact payload only.
|
|
21
|
+
* Returns null when missing/invalid/stale according to maxAgeMs.
|
|
22
|
+
*/
|
|
23
|
+
load<Key extends SharedArtifactKey>(address: string, artifact: Key | SharedArtifactContract<Key>, opts?: {
|
|
24
|
+
maxAgeMs?: number;
|
|
25
|
+
}): Promise<SharedArtifactValue<Key> | null>;
|
|
26
|
+
/** Saves payload by wrapping it into a timestamped envelope. */
|
|
27
|
+
save<Key extends SharedArtifactKey>(address: string, artifact: Key | SharedArtifactContract<Key>, value: SharedArtifactValue<Key>): Promise<void>;
|
|
28
|
+
/** Resolves shared artifact path for one strategy and artifact key. */
|
|
29
|
+
private artifactPath;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=shared-artifact-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-artifact-store.d.ts","sourceRoot":"","sources":["../../../src/scanners/store/shared-artifact-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,aAAa,CAAC;AASrB;;;GAGG;AACH,qBAAa,mBAAmB;IAM5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB;;;OAGG;gBAEgB,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAM,MAAiB;IAG/C,4DAA4D;IACtD,YAAY,CAAC,CAAC,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,GACtE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAYtC,6DAA6D;IACvD,YAAY,CAAC,CAAC,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,iBAAiB,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,EACvE,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,IAAI,CAAC;IAShB;;;OAGG;IACG,IAAI,CAAC,GAAG,SAAS,iBAAiB,EACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,GAAG,GAAG,sBAAsB,CAAC,GAAG,CAAC,EAC3C,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3B,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAwB3C,gEAAgE;IAC1D,IAAI,CAAC,GAAG,SAAS,iBAAiB,EACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,GAAG,GAAG,sBAAsB,CAAC,GAAG,CAAC,EAC3C,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC;IAchB,uEAAuE;IACvE,OAAO,CAAC,YAAY;CASrB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { describeSchemaValidationError, isSchemaValueValid, } from "../schema-utils.js";
|
|
3
|
+
import { readJsonFile, writeJsonAtomic } from "./fs-utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* Stores strategy-scoped shared artifacts used by multiple scanners.
|
|
6
|
+
* Artifacts are separated from scanner-local runtime state to avoid coupling.
|
|
7
|
+
*/
|
|
8
|
+
export class SharedArtifactStore {
|
|
9
|
+
stateDir;
|
|
10
|
+
now;
|
|
11
|
+
/**
|
|
12
|
+
* @param stateDir Root runtime state directory.
|
|
13
|
+
* @param now Injectable clock for deterministic freshness checks in tests.
|
|
14
|
+
*/
|
|
15
|
+
constructor(stateDir, now = Date.now) {
|
|
16
|
+
this.stateDir = stateDir;
|
|
17
|
+
this.now = now;
|
|
18
|
+
}
|
|
19
|
+
/** Reads full artifact envelope for a strategy/key pair. */
|
|
20
|
+
async loadEnvelope(address, artifact) {
|
|
21
|
+
const key = resolveArtifactKey(artifact);
|
|
22
|
+
const envelope = await readJsonFile(this.artifactPath(address, key));
|
|
23
|
+
if (!isArtifactEnvelope(envelope)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return envelope;
|
|
27
|
+
}
|
|
28
|
+
/** Writes full artifact envelope for a strategy/key pair. */
|
|
29
|
+
async saveEnvelope(address, artifact, value) {
|
|
30
|
+
const key = resolveArtifactKey(artifact);
|
|
31
|
+
if (!isArtifactEnvelope(value)) {
|
|
32
|
+
throw new Error(`Invalid artifact envelope for key '${key}'.`);
|
|
33
|
+
}
|
|
34
|
+
await writeJsonAtomic(this.artifactPath(address, key), value);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Reads artifact payload only.
|
|
38
|
+
* Returns null when missing/invalid/stale according to maxAgeMs.
|
|
39
|
+
*/
|
|
40
|
+
async load(address, artifact, opts) {
|
|
41
|
+
const envelope = await this.loadEnvelope(address, artifact);
|
|
42
|
+
if (!envelope) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (typeof opts?.maxAgeMs === "number" &&
|
|
46
|
+
this.now() - envelope.updatedAt > opts.maxAgeMs) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (isArtifactContract(artifact) &&
|
|
50
|
+
artifact.schema &&
|
|
51
|
+
!isSchemaValueValid(artifact.schema, envelope.data)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return envelope.data;
|
|
55
|
+
}
|
|
56
|
+
/** Saves payload by wrapping it into a timestamped envelope. */
|
|
57
|
+
async save(address, artifact, value) {
|
|
58
|
+
const contract = isArtifactContract(artifact) ? artifact : null;
|
|
59
|
+
if (contract?.schema && !isSchemaValueValid(contract.schema, value)) {
|
|
60
|
+
throw new Error(`Invalid artifact value for key '${contract.key}': ${describeSchemaValidationError(contract.schema, value)}`);
|
|
61
|
+
}
|
|
62
|
+
await this.saveEnvelope(address, artifact, {
|
|
63
|
+
updatedAt: this.now(),
|
|
64
|
+
data: value,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/** Resolves shared artifact path for one strategy and artifact key. */
|
|
68
|
+
artifactPath(address, key) {
|
|
69
|
+
return join(this.stateDir, "strategies", address, "shared", `${key}.json`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Runtime check for the lightweight artifact envelope shape. */
|
|
73
|
+
function isArtifactEnvelope(value) {
|
|
74
|
+
if (!isRecord(value)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return typeof value.updatedAt === "number" && "data" in value;
|
|
78
|
+
}
|
|
79
|
+
/** Runtime check for plain object values. */
|
|
80
|
+
function isRecord(value) {
|
|
81
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
82
|
+
}
|
|
83
|
+
function resolveArtifactKey(artifact) {
|
|
84
|
+
return typeof artifact === "string" ? artifact : artifact.key;
|
|
85
|
+
}
|
|
86
|
+
function isArtifactContract(artifact) {
|
|
87
|
+
return typeof artifact !== "string";
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=shared-artifact-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-artifact-store.js","sourceRoot":"","sources":["../../../src/scanners/store/shared-artifact-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ScannerDefinition } from "../scanner-definition.js";
|
|
2
|
+
import type { ReadHistoryOptions, ReadSignalsFilter, ScanResult, Signal } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Persists scanner execution outputs per (address, scannerId).
|
|
5
|
+
* Stores one latest result plus optional bounded history depending on retention policy.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SignalStore {
|
|
8
|
+
private readonly stateDir;
|
|
9
|
+
/** @param stateDir Root runtime state directory. */
|
|
10
|
+
constructor(stateDir: string);
|
|
11
|
+
/**
|
|
12
|
+
* Persists one scan result and applies retention behavior immediately.
|
|
13
|
+
* Use this as the single write path from engine execution.
|
|
14
|
+
*/
|
|
15
|
+
write(result: ScanResult, definition: Pick<ScannerDefinition, "retention" | "retentionMaxRuns">): Promise<void>;
|
|
16
|
+
/** Reads the most recent persisted result for a scanner instance. */
|
|
17
|
+
readLatest(address: string, scannerId: string): Promise<ScanResult | null>;
|
|
18
|
+
/** Reads persisted history for a scanner instance, optionally limited to recent entries. */
|
|
19
|
+
readHistory(address: string, scannerId: string, opts?: ReadHistoryOptions): Promise<ScanResult[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Queries latest signals across strategy/scanner folders.
|
|
22
|
+
* This is intended for user/tool queries and dashboard views.
|
|
23
|
+
*/
|
|
24
|
+
readSignals(filter?: ReadSignalsFilter): Promise<Signal[]>;
|
|
25
|
+
/** Loads all latest results that match filter boundaries. */
|
|
26
|
+
private readAllLatestResults;
|
|
27
|
+
/** Reads line-delimited history JSON and returns empty list on file/parse errors. */
|
|
28
|
+
private readHistoryInternal;
|
|
29
|
+
/** Writes the full history snapshot as JSONL atomically. */
|
|
30
|
+
private writeHistory;
|
|
31
|
+
/** Resolves latest result path for a scanner instance. */
|
|
32
|
+
private latestPath;
|
|
33
|
+
/** Resolves history file path for a scanner instance. */
|
|
34
|
+
private historyPath;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=signal-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-store.d.ts","sourceRoot":"","sources":["../../../src/scanners/store/signal-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,MAAM,EACP,MAAM,aAAa,CAAC;AAGrB;;;GAGG;AACH,qBAAa,WAAW;IAEV,OAAO,CAAC,QAAQ,CAAC,QAAQ;IADrC,oDAAoD;gBACvB,QAAQ,EAAE,MAAM;IAE7C;;;OAGG;IACG,KAAK,CACT,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,GAAG,kBAAkB,CAAC,GACpE,OAAO,CAAC,IAAI,CAAC;IAoBhB,qEAAqE;IAC/D,UAAU,CACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI7B,4FAA4F;IACtF,WAAW,CACf,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,kBAAkB,GACxB,OAAO,CAAC,UAAU,EAAE,CAAC;IAUxB;;;OAGG;IACG,WAAW,CAAC,MAAM,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA0BpE,6DAA6D;YAC/C,oBAAoB;IA2ClC,qFAAqF;YACvE,mBAAmB;IAiBjC,4DAA4D;YAC9C,YAAY;IAO1B,0DAA0D;IAC1D,OAAO,CAAC,UAAU;IAWlB,yDAAyD;IACzD,OAAO,CAAC,WAAW;CAUpB"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { readdir, readFile, rm } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { RetentionPolicy } from "../scanner-definition.js";
|
|
4
|
+
import { pathExists, readJsonFile, writeJsonAtomic, writeTextAtomic } from "./fs-utils.js";
|
|
5
|
+
/**
|
|
6
|
+
* Persists scanner execution outputs per (address, scannerId).
|
|
7
|
+
* Stores one latest result plus optional bounded history depending on retention policy.
|
|
8
|
+
*/
|
|
9
|
+
export class SignalStore {
|
|
10
|
+
stateDir;
|
|
11
|
+
/** @param stateDir Root runtime state directory. */
|
|
12
|
+
constructor(stateDir) {
|
|
13
|
+
this.stateDir = stateDir;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Persists one scan result and applies retention behavior immediately.
|
|
17
|
+
* Use this as the single write path from engine execution.
|
|
18
|
+
*/
|
|
19
|
+
async write(result, definition) {
|
|
20
|
+
const latestPath = this.latestPath(result.address, result.scannerId);
|
|
21
|
+
const historyPath = this.historyPath(result.address, result.scannerId);
|
|
22
|
+
await writeJsonAtomic(latestPath, result);
|
|
23
|
+
if (definition.retention === RetentionPolicy.LAST_ONLY) {
|
|
24
|
+
await rm(historyPath, { force: true });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const history = await this.readHistoryInternal(historyPath);
|
|
28
|
+
history.push(result);
|
|
29
|
+
if (definition.retention === RetentionPolicy.ROLLING_WINDOW) {
|
|
30
|
+
const maxRuns = definition.retentionMaxRuns ?? 100;
|
|
31
|
+
const trimmed = history.slice(-maxRuns);
|
|
32
|
+
await this.writeHistory(historyPath, trimmed);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Reads the most recent persisted result for a scanner instance. */
|
|
36
|
+
async readLatest(address, scannerId) {
|
|
37
|
+
return readJsonFile(this.latestPath(address, scannerId));
|
|
38
|
+
}
|
|
39
|
+
/** Reads persisted history for a scanner instance, optionally limited to recent entries. */
|
|
40
|
+
async readHistory(address, scannerId, opts) {
|
|
41
|
+
const history = await this.readHistoryInternal(this.historyPath(address, scannerId));
|
|
42
|
+
if (!opts?.limit || opts.limit <= 0) {
|
|
43
|
+
return history;
|
|
44
|
+
}
|
|
45
|
+
return history.slice(-opts.limit);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Queries latest signals across strategy/scanner folders.
|
|
49
|
+
* This is intended for user/tool queries and dashboard views.
|
|
50
|
+
*/
|
|
51
|
+
async readSignals(filter = {}) {
|
|
52
|
+
const latestResults = await this.readAllLatestResults(filter);
|
|
53
|
+
const signals = latestResults.flatMap((result) => result.signals);
|
|
54
|
+
const filtered = signals
|
|
55
|
+
.filter((signal) => filter.address ? signal.address === filter.address : true)
|
|
56
|
+
.filter((signal) => filter.scannerId ? signal.scannerId === filter.scannerId : true)
|
|
57
|
+
.filter((signal) => typeof filter.minScore === "number"
|
|
58
|
+
? signal.score >= filter.minScore
|
|
59
|
+
: true)
|
|
60
|
+
.filter((signal) => (filter.asset ? signal.asset === filter.asset : true))
|
|
61
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
62
|
+
const limit = filter.limit ?? 0;
|
|
63
|
+
if (limit > 0) {
|
|
64
|
+
return filtered.slice(0, limit);
|
|
65
|
+
}
|
|
66
|
+
return filtered;
|
|
67
|
+
}
|
|
68
|
+
/** Loads all latest results that match filter boundaries. */
|
|
69
|
+
async readAllLatestResults(filter) {
|
|
70
|
+
const root = join(this.stateDir, "strategies");
|
|
71
|
+
if (!(await pathExists(root))) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
const results = [];
|
|
75
|
+
const strategies = await readdir(root, { withFileTypes: true });
|
|
76
|
+
for (const strategyEntry of strategies) {
|
|
77
|
+
if (!strategyEntry.isDirectory()) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (filter.address && strategyEntry.name !== filter.address) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const scannersRoot = join(root, strategyEntry.name, "scanners");
|
|
84
|
+
if (!(await pathExists(scannersRoot))) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const scanners = await readdir(scannersRoot, { withFileTypes: true });
|
|
88
|
+
for (const scannerEntry of scanners) {
|
|
89
|
+
if (!scannerEntry.isDirectory()) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (filter.scannerId && scannerEntry.name !== filter.scannerId) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const latest = await this.readLatest(strategyEntry.name, scannerEntry.name);
|
|
96
|
+
if (latest) {
|
|
97
|
+
results.push(latest);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
/** Reads line-delimited history JSON and returns empty list on file/parse errors. */
|
|
104
|
+
async readHistoryInternal(path) {
|
|
105
|
+
if (!(await pathExists(path))) {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const raw = await readFile(path, "utf8");
|
|
110
|
+
return raw
|
|
111
|
+
.split("\n")
|
|
112
|
+
.map((line) => line.trim())
|
|
113
|
+
.filter(Boolean)
|
|
114
|
+
.map((line) => JSON.parse(line));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Writes the full history snapshot as JSONL atomically. */
|
|
121
|
+
async writeHistory(path, entries) {
|
|
122
|
+
const content = entries.map((entry) => JSON.stringify(entry)).join("\n") +
|
|
123
|
+
(entries.length > 0 ? "\n" : "");
|
|
124
|
+
await writeTextAtomic(path, content);
|
|
125
|
+
}
|
|
126
|
+
/** Resolves latest result path for a scanner instance. */
|
|
127
|
+
latestPath(address, scannerId) {
|
|
128
|
+
return join(this.stateDir, "strategies", address, "scanners", scannerId, "latest.json");
|
|
129
|
+
}
|
|
130
|
+
/** Resolves history file path for a scanner instance. */
|
|
131
|
+
historyPath(address, scannerId) {
|
|
132
|
+
return join(this.stateDir, "strategies", address, "scanners", scannerId, "history.jsonl");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=signal-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-store.js","sourceRoot":"","sources":["../../../src/scanners/store/signal-store.ts"],"names":[],"mappings":"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"}
|