dojozero 0.2.0__tar.gz → 0.2.1__tar.gz
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.
- {dojozero-0.2.0 → dojozero-0.2.1}/.gitignore +4 -2
- {dojozero-0.2.0 → dojozero-0.2.1}/PKG-INFO +5 -71
- dojozero-0.2.1/README.md +25 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/pyproject.toml +1 -1
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/agents/_config.py +30 -5
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_cache.py +6 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_constants.py +32 -5
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_server.py +23 -8
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_utils.py +44 -8
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_agent.py +1 -6
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_broker.py +5 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_metadata.py +4 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/cli.py +56 -4
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_models.py +2 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_tracing.py +51 -23
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_scheduler.py +84 -4
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_server.py +20 -9
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_trial_manager.py +152 -4
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/__init__.py +6 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_hub.py +26 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/_store.py +1 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nba/_trial.py +2 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ncaa/_trial.py +2 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nfl/_trial.py +2 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/sync_service/_sync.py +27 -7
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_agent_configs.py +105 -0
- dojozero-0.2.1/tests/test_arena_replay_seek.py +60 -0
- dojozero-0.2.0/README.md +0 -91
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/_optional_alicloud.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/agents/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/agents/_social_board.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/agents/_toolkit.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/agents/_trial_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_config.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_endpoints.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/_redis_reader.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/arena_server/get_snapshot.sh +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_config.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/betting/_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_actors.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_base.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_credentials.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_filesystem_orchestrator_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_metadata.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_registry.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_runtime.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_trial_orchestrator.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/core/_types.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_game_discovery.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_gateway_routing.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_jsonl_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/dashboard_server/_types.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_backtest.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_config.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_context.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_game_info.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_processors.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_stores.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_streams.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_subscriptions.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/_state_tracker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/_stats_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/_stats_fetcher.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/espn/_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_state_tracker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nba/_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_state_tracker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/ncaa/_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_state_tracker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/nfl/_utils.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/polymarket/_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/socialmedia/_watchlist.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/_api.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/_factory.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/data/websearch/_store.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_adapter.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_auth.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_rate_limit.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_server.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/gateway/_sse.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nba/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nba/_agent.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nba/_datastream.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nba/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ncaa/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ncaa/_agent.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ncaa/_datastream.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ncaa/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nfl/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nfl/_agent.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nfl/_datastream.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/nfl/_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ray_runtime/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/ray_runtime/_impl.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/sync_service/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/sync_service/_redis_client.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/sync_service/main.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/utils/__init__.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/utils/oss.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/src/dojozero/utils/time.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/conftest.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_agent_event_throttle.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_arena_event_deserialization.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_arena_span_grouping.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_betting_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_broker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_cli_agents.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_dashboard.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_data_hub.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_data_nba.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_data_nfl.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_data_polymarket.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_game_state_tracker.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_gateway.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_metadata.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_nba_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_nba_moneyline_agent.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_nfl_formatters.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_nfl_moneyline_agent.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_oss.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_registry.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_scheduler.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_social_board.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_socialmedia_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_span_models.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_stats_insight_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_subscriptions.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_websearch_events.py +0 -0
- {dojozero-0.2.0 → dojozero-0.2.1}/tests/test_websearch_formatters.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dojozero
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A platform for running AI agents on realtime sport data and make predictions about game outcomes.
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentscope-ai/DojoZero
|
|
6
6
|
Project-URL: Repository, https://github.com/agentscope-ai/DojoZero
|
|
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
|
|
45
45
|
# DojoZero
|
|
46
46
|
|
|
47
|
-
A platform for running AI agents on realtime sport data and make predictions
|
|
47
|
+
A platform for running AI agents on realtime sport data to reason about game outcomes and make predictions. DojoZero provides an actor-based runtime with live data streams, agent orchestration, trial management, backtesting, and tracing. Currently supports NBA, NFL, and NCAA.
|
|
48
48
|
|
|
49
49
|
## Installation
|
|
50
50
|
|
|
@@ -52,83 +52,17 @@ A platform for running AI agents on realtime sport data and make predictions abo
|
|
|
52
52
|
pip install dojozero
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
Optional extras:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
pip install dojozero[alicloud] # Alibaba Cloud integration (OSS,
|
|
58
|
+
pip install dojozero[alicloud] # Alibaba Cloud integration (OSS, SLS tracing)
|
|
59
59
|
pip install dojozero[redis] # Redis-backed data stores
|
|
60
60
|
pip install dojozero[ray] # Distributed execution via Ray
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
## Environment Setup
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
cp .env.example .env
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Quick Start
|
|
70
|
-
|
|
71
|
-
### Run a single trial locally
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
dojo0 run --params trial_params/nba-moneyline.yaml --trial-id nba-local-001
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Resume an interrupted trial
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
dojo0 run --trial-id nba-local-001 --resume-latest
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Run through dashboard server
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
# Start server with tracing
|
|
87
|
-
dojo0 serve --trace-backend jaeger
|
|
88
|
-
|
|
89
|
-
# Submit a trial from another terminal
|
|
90
|
-
dojo0 run \
|
|
91
|
-
--params trial_params/nba-moneyline.yaml \
|
|
92
|
-
--trial-id nba-server-001 \
|
|
93
|
-
--server http://localhost:8000
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Automatic scheduling with trial sources
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
dojo0 serve --trace-backend jaeger --trial-source "trial_sources/daily/*.yaml"
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Backtest from captured events
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
dojo0 backtest \
|
|
106
|
-
--events outputs/2026-01-12/401772976.jsonl \
|
|
107
|
-
--params outputs/2026-01-12/401772976.yaml \
|
|
108
|
-
--speed 100 --max-sleep 1
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Arena (live visualization)
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
dojo0 arena --trace-backend jaeger
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Command Index
|
|
118
|
-
|
|
119
|
-
| Command | Purpose |
|
|
120
|
-
|---------|---------|
|
|
121
|
-
| `dojo0 run` | Start a local or server-submitted trial |
|
|
122
|
-
| `dojo0 serve` | Dashboard / orchestration server |
|
|
123
|
-
| `dojo0 arena` | Trace-backed Arena visualization server |
|
|
124
|
-
| `dojo0 backtest` | Replay persisted event streams |
|
|
125
|
-
| `dojo0 list-sources` | List trial sources |
|
|
126
|
-
| `dojo0 list-trials` | List scheduled trials |
|
|
127
|
-
| `dojo0 clear-schedules` | Clear scheduled runs |
|
|
128
|
-
|
|
129
63
|
## Documentation
|
|
130
64
|
|
|
131
|
-
|
|
65
|
+
See the [full documentation](https://github.com/agentscope-ai/DojoZero/tree/main/docs) for setup, configuration, and usage guides.
|
|
132
66
|
|
|
133
67
|
## License
|
|
134
68
|
|
dojozero-0.2.1/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# DojoZero
|
|
2
|
+
|
|
3
|
+
A platform for running AI agents on realtime sport data to reason about game outcomes and make predictions. DojoZero provides an actor-based runtime with live data streams, agent orchestration, trial management, backtesting, and tracing. Currently supports NBA, NFL, and NCAA.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install dojozero
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Optional extras:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install dojozero[alicloud] # Alibaba Cloud integration (OSS, SLS tracing)
|
|
15
|
+
pip install dojozero[redis] # Redis-backed data stores
|
|
16
|
+
pip install dojozero[ray] # Distributed execution via Ray
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Documentation
|
|
20
|
+
|
|
21
|
+
See the [full documentation](https://github.com/agentscope-ai/DojoZero/tree/main/docs) for setup, configuration, and usage guides.
|
|
22
|
+
|
|
23
|
+
## License
|
|
24
|
+
|
|
25
|
+
MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dojozero"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "A platform for running AI agents on realtime sport data and make predictions about game outcomes."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -278,7 +278,10 @@ def create_model(llm_config: LLMConfig) -> ChatModelBase:
|
|
|
278
278
|
if model_type in "grok":
|
|
279
279
|
grok_client_kwargs: dict[str, Any] = {"base_url": "https://api.x.ai/v1"}
|
|
280
280
|
return OpenAIChatModel(
|
|
281
|
-
model_name=model_name,
|
|
281
|
+
model_name=model_name,
|
|
282
|
+
api_key=api_key,
|
|
283
|
+
stream=False,
|
|
284
|
+
client_kwargs=grok_client_kwargs,
|
|
282
285
|
)
|
|
283
286
|
elif model_type == "openai":
|
|
284
287
|
if base_url:
|
|
@@ -286,14 +289,36 @@ def create_model(llm_config: LLMConfig) -> ChatModelBase:
|
|
|
286
289
|
else:
|
|
287
290
|
client_kwargs = {}
|
|
288
291
|
return OpenAIChatModel(
|
|
289
|
-
model_name=model_name,
|
|
292
|
+
model_name=model_name,
|
|
293
|
+
api_key=api_key,
|
|
294
|
+
stream=False,
|
|
295
|
+
client_kwargs=client_kwargs,
|
|
290
296
|
)
|
|
291
297
|
elif model_type == "dashscope":
|
|
292
|
-
|
|
298
|
+
# qwen3.5-* series requires the MultiModalConversation endpoint even
|
|
299
|
+
# for text-only usage. The upstream agentscope SDK only auto-detects
|
|
300
|
+
# "-vl" / "qvq" suffixes/name patterns, so we explicitly opt-in here.
|
|
301
|
+
multimodality: bool | None = None
|
|
302
|
+
if model_name.startswith("qwen3.5"):
|
|
303
|
+
multimodality = True
|
|
304
|
+
return DashScopeChatModel(
|
|
305
|
+
model_name=model_name,
|
|
306
|
+
api_key=api_key,
|
|
307
|
+
multimodality=multimodality,
|
|
308
|
+
stream=False,
|
|
309
|
+
)
|
|
293
310
|
elif model_type == "anthropic":
|
|
294
|
-
return AnthropicChatModel(
|
|
311
|
+
return AnthropicChatModel(
|
|
312
|
+
model_name=model_name,
|
|
313
|
+
api_key=api_key,
|
|
314
|
+
stream=False,
|
|
315
|
+
)
|
|
295
316
|
elif model_type == "gemini":
|
|
296
|
-
return GeminiChatModel(
|
|
317
|
+
return GeminiChatModel(
|
|
318
|
+
model_name=model_name,
|
|
319
|
+
api_key=api_key,
|
|
320
|
+
stream=False,
|
|
321
|
+
)
|
|
297
322
|
else:
|
|
298
323
|
raise ValueError(f"Unknown model_type: {model_type}")
|
|
299
324
|
|
|
@@ -519,6 +519,12 @@ class ReplayMetaInfo:
|
|
|
519
519
|
odds_update_indices: list[int] = field(
|
|
520
520
|
default_factory=list
|
|
521
521
|
) # Indices of odds_update events
|
|
522
|
+
broker_state_update_indices: list[int] = field(
|
|
523
|
+
default_factory=list
|
|
524
|
+
) # Indices of broker.state_update events
|
|
525
|
+
broker_final_stats_indices: list[int] = field(
|
|
526
|
+
default_factory=list
|
|
527
|
+
) # Indices of broker.final_stats events
|
|
522
528
|
|
|
523
529
|
|
|
524
530
|
@dataclass
|
|
@@ -266,18 +266,45 @@ _NFL_TEAMS: dict[str, TeamIdentity] = {
|
|
|
266
266
|
_DEFAULT_TEAM_COLOR = "#666666"
|
|
267
267
|
|
|
268
268
|
|
|
269
|
-
def _get_team_identity(
|
|
269
|
+
def _get_team_identity(
|
|
270
|
+
tricode: str, league: str = "NBA", *, team_id: str = ""
|
|
271
|
+
) -> TeamIdentity:
|
|
270
272
|
"""Get team identity by tricode.
|
|
271
273
|
|
|
272
274
|
Returns TeamIdentity from static lookup. Falls back to a minimal identity
|
|
273
|
-
with the tricode as the name if not found
|
|
274
|
-
|
|
275
|
+
with the tricode as the name if not found.
|
|
276
|
+
|
|
277
|
+
For NBA/NFL, unknown tricodes use the ESPN CDN pattern
|
|
278
|
+
``/teamlogos/{league}/500/{tricode}.png``.
|
|
279
|
+
|
|
280
|
+
NCAA mens basketball logos on ESPN use **numeric** team IDs in
|
|
281
|
+
``/teamlogos/ncaa/500/{id}.png``; tricode-based URLs usually 404, so pass
|
|
282
|
+
``team_id`` from trial metadata when available, otherwise ``logo_url`` is
|
|
283
|
+
left empty to avoid broken images.
|
|
275
284
|
"""
|
|
276
|
-
|
|
285
|
+
lu = league.upper()
|
|
286
|
+
if lu == "NBA":
|
|
287
|
+
teams = _NBA_TEAMS
|
|
288
|
+
elif lu == "NFL":
|
|
289
|
+
teams = _NFL_TEAMS
|
|
290
|
+
else:
|
|
291
|
+
teams = {}
|
|
277
292
|
if tricode in teams:
|
|
278
293
|
return teams[tricode]
|
|
279
294
|
|
|
280
|
-
|
|
295
|
+
if lu == "NCAA":
|
|
296
|
+
logo_url = ""
|
|
297
|
+
tid = (team_id or "").strip()
|
|
298
|
+
if tid.isdigit():
|
|
299
|
+
logo_url = f"https://a.espncdn.com/i/teamlogos/ncaa/500/{tid}.png"
|
|
300
|
+
return TeamIdentity(
|
|
301
|
+
name=tricode,
|
|
302
|
+
tricode=tricode,
|
|
303
|
+
team_id=tid,
|
|
304
|
+
color=_DEFAULT_TEAM_COLOR,
|
|
305
|
+
logo_url=logo_url,
|
|
306
|
+
)
|
|
307
|
+
|
|
281
308
|
league_lower = league.lower()
|
|
282
309
|
logo_url = (
|
|
283
310
|
f"https://a.espncdn.com/i/teamlogos/{league_lower}/500/{tricode.lower()}.png"
|
|
@@ -1473,6 +1473,8 @@ class TrialReplayController:
|
|
|
1473
1473
|
The snapshot includes:
|
|
1474
1474
|
- Meta events: agent_initialize, game_initialize, game_start
|
|
1475
1475
|
- Latest odds_update before the target position
|
|
1476
|
+
- Latest broker snapshot before the target position
|
|
1477
|
+
(prefer final_stats over state_update)
|
|
1476
1478
|
- Recent play items up to and including the target
|
|
1477
1479
|
|
|
1478
1480
|
Args:
|
|
@@ -1497,6 +1499,15 @@ class TrialReplayController:
|
|
|
1497
1499
|
# Collect item indices to include in snapshot (use set to avoid duplicates)
|
|
1498
1500
|
snapshot_indices: set[int] = set()
|
|
1499
1501
|
|
|
1502
|
+
def _latest_index_before(indices: list[int]) -> int | None:
|
|
1503
|
+
latest_idx = None
|
|
1504
|
+
for idx in indices:
|
|
1505
|
+
if idx <= target_item_index:
|
|
1506
|
+
latest_idx = idx
|
|
1507
|
+
else:
|
|
1508
|
+
break
|
|
1509
|
+
return latest_idx
|
|
1510
|
+
|
|
1500
1511
|
# 1. Add meta events (agent_initialize, game_initialize, game_start)
|
|
1501
1512
|
if self.meta.agent_initialize_item_index is not None:
|
|
1502
1513
|
snapshot_indices.add(self.meta.agent_initialize_item_index)
|
|
@@ -1507,17 +1518,21 @@ class TrialReplayController:
|
|
|
1507
1518
|
|
|
1508
1519
|
# 2. Find and add the latest odds_update before target_item_index
|
|
1509
1520
|
if self.meta.odds_update_indices:
|
|
1510
|
-
|
|
1511
|
-
latest_odds_idx = None
|
|
1512
|
-
for idx in self.meta.odds_update_indices:
|
|
1513
|
-
if idx <= target_item_index:
|
|
1514
|
-
latest_odds_idx = idx
|
|
1515
|
-
else:
|
|
1516
|
-
break # odds_update_indices are in chronological order
|
|
1521
|
+
latest_odds_idx = _latest_index_before(self.meta.odds_update_indices)
|
|
1517
1522
|
if latest_odds_idx is not None:
|
|
1518
1523
|
snapshot_indices.add(latest_odds_idx)
|
|
1519
1524
|
|
|
1520
|
-
# 3. Add
|
|
1525
|
+
# 3. Add the latest broker snapshot before target_item_index.
|
|
1526
|
+
# final_stats is preferred because it contains the ranking/statistics payload.
|
|
1527
|
+
latest_broker_idx = _latest_index_before(self.meta.broker_final_stats_indices)
|
|
1528
|
+
if latest_broker_idx is None:
|
|
1529
|
+
latest_broker_idx = _latest_index_before(
|
|
1530
|
+
self.meta.broker_state_update_indices
|
|
1531
|
+
)
|
|
1532
|
+
if latest_broker_idx is not None:
|
|
1533
|
+
snapshot_indices.add(latest_broker_idx)
|
|
1534
|
+
|
|
1535
|
+
# 4. Add recent items up to and including the target
|
|
1521
1536
|
start = max(0, target_item_index + 1 - self.snapshot_size)
|
|
1522
1537
|
for i in range(start, target_item_index + 1):
|
|
1523
1538
|
snapshot_indices.add(i)
|
|
@@ -46,6 +46,7 @@ TRIAL_INFO_OPERATION_NAMES = [
|
|
|
46
46
|
"event.game_result",
|
|
47
47
|
"event.nba_game_update",
|
|
48
48
|
"event.nfl_game_update",
|
|
49
|
+
"event.ncaa_game_update",
|
|
49
50
|
]
|
|
50
51
|
|
|
51
52
|
# Tag used by DojoZero to correlate all spans for a trial (see TrialOrchestrator, create_span_from_event).
|
|
@@ -258,15 +259,25 @@ def _resolve_team_identity(
|
|
|
258
259
|
fallback_tricode: str,
|
|
259
260
|
fallback_name: str,
|
|
260
261
|
league: str,
|
|
262
|
+
*,
|
|
263
|
+
team_id: str = "",
|
|
261
264
|
) -> TeamIdentity:
|
|
262
265
|
"""Resolve a team to a TeamIdentity, applying fallbacks as needed."""
|
|
263
266
|
if isinstance(team, TeamIdentity) and team:
|
|
264
|
-
|
|
267
|
+
resolved = team
|
|
265
268
|
if not team.tricode and fallback_tricode:
|
|
266
|
-
|
|
267
|
-
|
|
269
|
+
resolved = resolved.model_copy(update={"tricode": fallback_tricode})
|
|
270
|
+
if league.upper() == "NCAA" and not resolved.logo_url:
|
|
271
|
+
tid = (resolved.team_id or team_id or "").strip()
|
|
272
|
+
if tid.isdigit():
|
|
273
|
+
resolved = resolved.model_copy(
|
|
274
|
+
update={
|
|
275
|
+
"logo_url": f"https://a.espncdn.com/i/teamlogos/ncaa/500/{tid}.png"
|
|
276
|
+
}
|
|
277
|
+
)
|
|
278
|
+
return resolved
|
|
268
279
|
# Fallback to static lookup, then override name if provided
|
|
269
|
-
identity = _get_team_identity(fallback_tricode, league)
|
|
280
|
+
identity = _get_team_identity(fallback_tricode, league, team_id=team_id)
|
|
270
281
|
if fallback_name and fallback_name != identity.name:
|
|
271
282
|
return identity.model_copy(update={"name": fallback_name})
|
|
272
283
|
return identity
|
|
@@ -433,17 +444,33 @@ async def _extract_games_from_trials(
|
|
|
433
444
|
game_init = trial_info.get("game_init")
|
|
434
445
|
if isinstance(game_init, GameInitializeEvent):
|
|
435
446
|
home_team = _resolve_team_identity(
|
|
436
|
-
game_init.home_team,
|
|
447
|
+
game_init.home_team,
|
|
448
|
+
home_tricode,
|
|
449
|
+
"",
|
|
450
|
+
league,
|
|
451
|
+
team_id=str(metadata.get("home_team_id", "") or ""),
|
|
437
452
|
)
|
|
438
453
|
away_team = _resolve_team_identity(
|
|
439
|
-
game_init.away_team,
|
|
454
|
+
game_init.away_team,
|
|
455
|
+
away_tricode,
|
|
456
|
+
"",
|
|
457
|
+
league,
|
|
458
|
+
team_id=str(metadata.get("away_team_id", "") or ""),
|
|
440
459
|
)
|
|
441
460
|
else:
|
|
442
461
|
home_team = _resolve_team_identity(
|
|
443
|
-
"",
|
|
462
|
+
"",
|
|
463
|
+
home_tricode,
|
|
464
|
+
metadata.get("home_team_name", ""),
|
|
465
|
+
league,
|
|
466
|
+
team_id=str(metadata.get("home_team_id", "") or ""),
|
|
444
467
|
)
|
|
445
468
|
away_team = _resolve_team_identity(
|
|
446
|
-
"",
|
|
469
|
+
"",
|
|
470
|
+
away_tricode,
|
|
471
|
+
metadata.get("away_team_name", ""),
|
|
472
|
+
league,
|
|
473
|
+
team_id=str(metadata.get("away_team_id", "") or ""),
|
|
447
474
|
)
|
|
448
475
|
|
|
449
476
|
# Fetch bets for live games only (performance optimization)
|
|
@@ -962,6 +989,7 @@ def _compute_replay_meta(
|
|
|
962
989
|
- play_item_indices: mapping from play_index to item_index
|
|
963
990
|
- periods: list of PeriodInfo with play counts per period
|
|
964
991
|
- meta event indices: agent_initialize, game_initialize, game_start, odds_update
|
|
992
|
+
- broker snapshot indices: state_update and final_stats
|
|
965
993
|
|
|
966
994
|
Args:
|
|
967
995
|
items: List of serialized span dicts with "category" and "data" keys
|
|
@@ -979,6 +1007,8 @@ def _compute_replay_meta(
|
|
|
979
1007
|
game_initialize_item_index: int | None = None
|
|
980
1008
|
game_start_item_index: int | None = None
|
|
981
1009
|
odds_update_indices: list[int] = []
|
|
1010
|
+
broker_state_update_indices: list[int] = []
|
|
1011
|
+
broker_final_stats_indices: list[int] = []
|
|
982
1012
|
|
|
983
1013
|
current_period: int = 1 # Default period
|
|
984
1014
|
|
|
@@ -995,6 +1025,10 @@ def _compute_replay_meta(
|
|
|
995
1025
|
game_start_item_index = item_index
|
|
996
1026
|
elif category == "odds_update":
|
|
997
1027
|
odds_update_indices.append(item_index)
|
|
1028
|
+
elif category == "state_update":
|
|
1029
|
+
broker_state_update_indices.append(item_index)
|
|
1030
|
+
elif category == "final_stats":
|
|
1031
|
+
broker_final_stats_indices.append(item_index)
|
|
998
1032
|
|
|
999
1033
|
# Track core category items (plays)
|
|
1000
1034
|
if category in core_categories:
|
|
@@ -1031,6 +1065,8 @@ def _compute_replay_meta(
|
|
|
1031
1065
|
game_initialize_item_index=game_initialize_item_index,
|
|
1032
1066
|
game_start_item_index=game_start_item_index,
|
|
1033
1067
|
odds_update_indices=odds_update_indices,
|
|
1068
|
+
broker_state_update_indices=broker_state_update_indices,
|
|
1069
|
+
broker_final_stats_indices=broker_final_stats_indices,
|
|
1034
1070
|
)
|
|
1035
1071
|
|
|
1036
1072
|
|
|
@@ -516,12 +516,7 @@ class BettingAgent(AgentBase, Agent[BettingAgentConfig]):
|
|
|
516
516
|
summary_request = self._build_summary_request()
|
|
517
517
|
if summary_request:
|
|
518
518
|
model = self._react_agent.model
|
|
519
|
-
|
|
520
|
-
model.stream = False
|
|
521
|
-
try:
|
|
522
|
-
resp = await model(summary_request)
|
|
523
|
-
finally:
|
|
524
|
-
model.stream = original_stream
|
|
519
|
+
resp = await model(summary_request)
|
|
525
520
|
resp_content = getattr(resp, "content", None)
|
|
526
521
|
events_summary, _ = _parse_response_content(resp_content)
|
|
527
522
|
if not events_summary:
|
|
@@ -262,6 +262,11 @@ class BrokerOperator(OperatorBase, Operator[BrokerOperatorConfig]):
|
|
|
262
262
|
len(self._bets),
|
|
263
263
|
)
|
|
264
264
|
|
|
265
|
+
@property
|
|
266
|
+
def has_unsettled_bets(self) -> bool:
|
|
267
|
+
"""Return True if there are active (unsettled) bets."""
|
|
268
|
+
return any(bet.status == BetStatus.ACTIVE for bet in self._bets.values())
|
|
269
|
+
|
|
265
270
|
def ensure_event_initialized(
|
|
266
271
|
self,
|
|
267
272
|
event_id: str,
|
|
@@ -67,6 +67,10 @@ class BettingTrialMetadata(BaseTrialMetadata):
|
|
|
67
67
|
away_team_name: str
|
|
68
68
|
game_date: str
|
|
69
69
|
|
|
70
|
+
# ESPN team IDs (for Arena logos, APIs; optional, default from game lookup)
|
|
71
|
+
home_team_id: str = ""
|
|
72
|
+
away_team_id: str = ""
|
|
73
|
+
|
|
70
74
|
# Polymarket (optional)
|
|
71
75
|
market_url: str | None = None
|
|
72
76
|
|
|
@@ -339,7 +339,9 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
339
339
|
default=[],
|
|
340
340
|
help="Path or glob pattern for trial source YAML files (repeatable). "
|
|
341
341
|
"Enables automatic scheduling for the specified sports/scenarios. "
|
|
342
|
-
"Requires filesystem store to be configured."
|
|
342
|
+
"Requires filesystem store to be configured. "
|
|
343
|
+
"Optional env DOJOZERO_MAX_DAILY_GAMES overrides config.max_daily_games "
|
|
344
|
+
"for every loaded source (integer; 0 = unlimited).",
|
|
343
345
|
)
|
|
344
346
|
serve_parser.add_argument(
|
|
345
347
|
"--no-auto-resume",
|
|
@@ -347,6 +349,13 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
347
349
|
action="store_true",
|
|
348
350
|
help="Disable automatic resuming of interrupted trials from previous shutdown.",
|
|
349
351
|
)
|
|
352
|
+
serve_parser.add_argument(
|
|
353
|
+
"--no-scheduler",
|
|
354
|
+
dest="no_scheduler",
|
|
355
|
+
action="store_true",
|
|
356
|
+
help="Disable the trial scheduler entirely. No trial sources will be loaded "
|
|
357
|
+
"or auto-resolved, and persisted sources will be ignored.",
|
|
358
|
+
)
|
|
350
359
|
serve_parser.add_argument(
|
|
351
360
|
"--stale-threshold-hours",
|
|
352
361
|
dest="stale_threshold_hours",
|
|
@@ -1881,6 +1890,29 @@ def _expand_compact_trial_source(
|
|
|
1881
1890
|
config.setdefault(key, value)
|
|
1882
1891
|
|
|
1883
1892
|
|
|
1893
|
+
def _parse_max_daily_games_env_override() -> int | None:
|
|
1894
|
+
"""Parse ``DOJOZERO_MAX_DAILY_GAMES`` for ``serve`` trial source loading.
|
|
1895
|
+
|
|
1896
|
+
Returns:
|
|
1897
|
+
``None`` if unset or empty (YAML values are used as-is).
|
|
1898
|
+
|
|
1899
|
+
Note:
|
|
1900
|
+
``0`` means unlimited, consistent with scheduler / trial source YAML.
|
|
1901
|
+
"""
|
|
1902
|
+
raw = os.environ.get("DOJOZERO_MAX_DAILY_GAMES", "").strip()
|
|
1903
|
+
if not raw:
|
|
1904
|
+
return None
|
|
1905
|
+
try:
|
|
1906
|
+
value = int(raw, 10)
|
|
1907
|
+
except ValueError as e:
|
|
1908
|
+
raise DojoZeroCLIError(
|
|
1909
|
+
f"DOJOZERO_MAX_DAILY_GAMES must be an integer, got {raw!r}"
|
|
1910
|
+
) from e
|
|
1911
|
+
if value < 0:
|
|
1912
|
+
raise DojoZeroCLIError(f"DOJOZERO_MAX_DAILY_GAMES must be >= 0, got {value}")
|
|
1913
|
+
return value
|
|
1914
|
+
|
|
1915
|
+
|
|
1884
1916
|
def _load_trial_source_from_yaml(path: Path) -> InitialTrialSourceDict:
|
|
1885
1917
|
"""Load a trial source configuration from a YAML file.
|
|
1886
1918
|
|
|
@@ -1956,13 +1988,17 @@ async def _serve_command(args: argparse.Namespace) -> int:
|
|
|
1956
1988
|
trace_backend = getattr(args, "trace_backend", None)
|
|
1957
1989
|
trace_ingest_endpoint = getattr(args, "trace_ingest_endpoint", None)
|
|
1958
1990
|
service_name = getattr(args, "service_name", "dojozero")
|
|
1991
|
+
no_scheduler = getattr(args, "no_scheduler", False)
|
|
1959
1992
|
trial_source_files: list[str] = getattr(args, "trial_sources", []) or []
|
|
1960
1993
|
auto_resume = not getattr(args, "no_auto_resume", False)
|
|
1961
1994
|
stale_threshold_hours = getattr(args, "stale_threshold_hours", 24.0)
|
|
1962
1995
|
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1996
|
+
if no_scheduler:
|
|
1997
|
+
trial_source_files = []
|
|
1998
|
+
LOGGER.info("Scheduler disabled via --no-scheduler")
|
|
1999
|
+
elif not trial_source_files:
|
|
2000
|
+
# Auto-resolve trial sources from DOJOZERO_ENV / SIGMA_APP_STAGE if not
|
|
2001
|
+
# explicitly provided via --trial-source.
|
|
1966
2002
|
env_tier = _resolve_env_tier()
|
|
1967
2003
|
trial_sources_dir = Path("trial_sources") / env_tier
|
|
1968
2004
|
if trial_sources_dir.is_dir():
|
|
@@ -2010,6 +2046,21 @@ async def _serve_command(args: argparse.Namespace) -> int:
|
|
|
2010
2046
|
source_data.get("source_id"),
|
|
2011
2047
|
)
|
|
2012
2048
|
|
|
2049
|
+
env_max_daily = _parse_max_daily_games_env_override()
|
|
2050
|
+
if env_max_daily is not None:
|
|
2051
|
+
if initial_trial_sources:
|
|
2052
|
+
for source_data in initial_trial_sources:
|
|
2053
|
+
source_data["config"]["max_daily_games"] = env_max_daily
|
|
2054
|
+
LOGGER.info(
|
|
2055
|
+
"DOJOZERO_MAX_DAILY_GAMES=%s overrides max_daily_games for %d trial source(s)",
|
|
2056
|
+
env_max_daily,
|
|
2057
|
+
len(initial_trial_sources),
|
|
2058
|
+
)
|
|
2059
|
+
else:
|
|
2060
|
+
LOGGER.warning(
|
|
2061
|
+
"DOJOZERO_MAX_DAILY_GAMES is set but no trial sources were loaded; ignoring override"
|
|
2062
|
+
)
|
|
2063
|
+
|
|
2013
2064
|
LOGGER.info("Starting Dashboard Server at http://%s:%d", host, port)
|
|
2014
2065
|
LOGGER.info("Trial API: http://%s:%d/api/trials", host, port)
|
|
2015
2066
|
LOGGER.info("Trial Source API: http://%s:%d/api/trial-sources", host, port)
|
|
@@ -2072,6 +2123,7 @@ async def _serve_command(args: argparse.Namespace) -> int:
|
|
|
2072
2123
|
stale_threshold_hours=stale_threshold_hours,
|
|
2073
2124
|
enable_gateway=enable_gateway,
|
|
2074
2125
|
authenticator=authenticator,
|
|
2126
|
+
no_scheduler=no_scheduler,
|
|
2075
2127
|
)
|
|
2076
2128
|
return 0
|
|
2077
2129
|
|
|
@@ -277,8 +277,10 @@ _OPERATION_NAME_MAP: dict[str, str] = {
|
|
|
277
277
|
_SPORT_UNIFY_MAP: dict[str, str] = {
|
|
278
278
|
"nba_play": "play",
|
|
279
279
|
"nfl_play": "play",
|
|
280
|
+
"ncaa_play": "play",
|
|
280
281
|
"nba_game_update": "game_update",
|
|
281
282
|
"nfl_game_update": "game_update",
|
|
283
|
+
"ncaa_game_update": "game_update",
|
|
282
284
|
}
|
|
283
285
|
|
|
284
286
|
|