dojozero 0.3.0__tar.gz → 0.5.0__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.
Files changed (228) hide show
  1. {dojozero-0.3.0 → dojozero-0.5.0}/PKG-INFO +4 -2
  2. {dojozero-0.3.0 → dojozero-0.5.0}/pyproject.toml +5 -2
  3. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/agents/_config.py +16 -4
  4. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_cache.py +18 -3
  5. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_config.py +6 -1
  6. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_endpoints.py +95 -5
  7. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_models.py +15 -0
  8. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_server.py +10 -3
  9. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_utils.py +397 -99
  10. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/__init__.py +32 -17
  11. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_agent.py +105 -62
  12. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_broker.py +130 -27
  13. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_config.py +53 -13
  14. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_metadata.py +6 -1
  15. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_models.py +203 -8
  16. dojozero-0.5.0/src/dojozero/betting/_prediction_broker.py +1225 -0
  17. dojozero-0.5.0/src/dojozero/betting/_protocol.py +90 -0
  18. dojozero-0.5.0/src/dojozero/betting/_scoring.py +94 -0
  19. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/cli.py +98 -26
  20. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_models.py +7 -0
  21. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_tracing.py +203 -7
  22. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_game_discovery.py +188 -5
  23. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_scheduler.py +74 -6
  24. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_server.py +260 -18
  25. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_trial_manager.py +120 -54
  26. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/__init__.py +13 -0
  27. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_models.py +7 -1
  28. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_sls_source.py +11 -1
  29. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/_api.py +214 -8
  30. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/_store.py +28 -29
  31. dojozero-0.5.0/src/dojozero/data/world_cup/__init__.py +37 -0
  32. dojozero-0.5.0/src/dojozero/data/world_cup/_api.py +100 -0
  33. dojozero-0.5.0/src/dojozero/data/world_cup/_constants.py +45 -0
  34. dojozero-0.5.0/src/dojozero/data/world_cup/_events.py +162 -0
  35. dojozero-0.5.0/src/dojozero/data/world_cup/_factory.py +52 -0
  36. dojozero-0.5.0/src/dojozero/data/world_cup/_state_tracker.py +164 -0
  37. dojozero-0.5.0/src/dojozero/data/world_cup/_store.py +776 -0
  38. dojozero-0.5.0/src/dojozero/data/world_cup/_utils.py +209 -0
  39. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/__init__.py +12 -0
  40. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/_adapter.py +274 -69
  41. dojozero-0.5.0/src/dojozero/gateway/_agentid.py +182 -0
  42. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/_auth.py +20 -7
  43. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/_models.py +94 -4
  44. dojozero-0.5.0/src/dojozero/gateway/_server.py +908 -0
  45. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nba/_trial.py +14 -2
  46. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ncaa/_trial.py +14 -1
  47. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nfl/_trial.py +14 -2
  48. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/sync_service/_redis_client.py +32 -1
  49. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/sync_service/_sync.py +103 -38
  50. dojozero-0.5.0/src/dojozero/world_cup/__init__.py +8 -0
  51. dojozero-0.5.0/src/dojozero/world_cup/_agent.py +60 -0
  52. dojozero-0.5.0/src/dojozero/world_cup/_datastream.py +114 -0
  53. dojozero-0.5.0/src/dojozero/world_cup/_formatters.py +190 -0
  54. dojozero-0.5.0/src/dojozero/world_cup/_trial.py +475 -0
  55. {dojozero-0.3.0 → dojozero-0.5.0}/tests/conftest.py +19 -0
  56. dojozero-0.5.0/tests/fixtures/world_cup/cwc_2025/plays_735949_aet.json +1 -0
  57. dojozero-0.5.0/tests/fixtures/world_cup/cwc_2025/plays_735958_final.json +1 -0
  58. dojozero-0.5.0/tests/fixtures/world_cup/cwc_2025/scoreboard_20250713.json +1 -0
  59. dojozero-0.5.0/tests/fixtures/world_cup/cwc_2025/summary_735949_aet.json +1 -0
  60. dojozero-0.5.0/tests/fixtures/world_cup/cwc_2025/summary_735958_final.json +1 -0
  61. dojozero-0.5.0/tests/fixtures/world_cup/plays_684665.json +1 -0
  62. dojozero-0.5.0/tests/fixtures/world_cup/scoreboard_conmebol_20250909.json +1 -0
  63. dojozero-0.5.0/tests/fixtures/world_cup/scoreboard_fifa_world.json +1 -0
  64. dojozero-0.5.0/tests/fixtures/world_cup/summary_684665.json +1 -0
  65. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_agent_configs.py +14 -0
  66. dojozero-0.5.0/tests/test_arena_cache.py +26 -0
  67. dojozero-0.5.0/tests/test_arena_landing.py +46 -0
  68. dojozero-0.5.0/tests/test_arena_leaderboard_cache_sort.py +95 -0
  69. dojozero-0.5.0/tests/test_arena_leaderboard_prediction.py +289 -0
  70. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_arena_replay_seek.py +18 -0
  71. dojozero-0.5.0/tests/test_arena_stats_prediction.py +104 -0
  72. dojozero-0.5.0/tests/test_backtest_launch.py +91 -0
  73. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_broker.py +254 -2
  74. dojozero-0.5.0/tests/test_cli_sls_polling.py +323 -0
  75. dojozero-0.5.0/tests/test_dashboard_agentid.py +110 -0
  76. dojozero-0.5.0/tests/test_dashboard_games_endpoint.py +79 -0
  77. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_data_polymarket.py +208 -1
  78. dojozero-0.5.0/tests/test_data_world_cup.py +689 -0
  79. dojozero-0.5.0/tests/test_detect_contest_kind.py +49 -0
  80. dojozero-0.5.0/tests/test_dual_mode_trial.py +574 -0
  81. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_gateway.py +118 -15
  82. dojozero-0.5.0/tests/test_gateway_agentid.py +399 -0
  83. dojozero-0.5.0/tests/test_genai_tracing.py +196 -0
  84. dojozero-0.5.0/tests/test_materialization_tracker.py +306 -0
  85. dojozero-0.5.0/tests/test_prediction_broker.py +780 -0
  86. dojozero-0.5.0/tests/test_scoring.py +227 -0
  87. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_sls_source.py +91 -1
  88. dojozero-0.5.0/tests/test_sls_trace_reader_progress.py +302 -0
  89. dojozero-0.5.0/tests/test_sync_service_period_league_lookback.py +114 -0
  90. dojozero-0.5.0/tests/test_sync_service_world_cup_games.py +169 -0
  91. dojozero-0.5.0/tests/test_upcoming_games_from_schedules.py +149 -0
  92. dojozero-0.5.0/tests/test_world_cup_agent.py +38 -0
  93. dojozero-0.5.0/tests/test_world_cup_formatters.py +255 -0
  94. dojozero-0.5.0/tests/test_world_cup_scheduling.py +535 -0
  95. dojozero-0.5.0/tests/test_world_cup_trial.py +381 -0
  96. dojozero-0.3.0/src/dojozero/gateway/_server.py +0 -664
  97. {dojozero-0.3.0 → dojozero-0.5.0}/.gitignore +0 -0
  98. {dojozero-0.3.0 → dojozero-0.5.0}/README.md +0 -0
  99. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/__init__.py +0 -0
  100. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/_optional_alicloud.py +0 -0
  101. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/agents/__init__.py +0 -0
  102. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/agents/_social_board.py +0 -0
  103. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/agents/_toolkit.py +0 -0
  104. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/agents/_trial_utils.py +0 -0
  105. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/__init__.py +0 -0
  106. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_constants.py +0 -0
  107. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/_redis_reader.py +0 -0
  108. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/arena_server/get_snapshot.sh +0 -0
  109. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/betting/_formatters.py +0 -0
  110. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/__init__.py +0 -0
  111. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_actors.py +0 -0
  112. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_base.py +0 -0
  113. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_credentials.py +0 -0
  114. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_filesystem_orchestrator_store.py +0 -0
  115. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_metadata.py +0 -0
  116. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_registry.py +0 -0
  117. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_runtime.py +0 -0
  118. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_trial_orchestrator.py +0 -0
  119. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/core/_types.py +0 -0
  120. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/__init__.py +0 -0
  121. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_cluster.py +0 -0
  122. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_gateway_routing.py +0 -0
  123. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_jsonl_utils.py +0 -0
  124. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/dashboard_server/_types.py +0 -0
  125. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_backtest.py +0 -0
  126. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_config.py +0 -0
  127. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_context.py +0 -0
  128. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_factory.py +0 -0
  129. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_game_info.py +0 -0
  130. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_hub.py +0 -0
  131. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_processors.py +0 -0
  132. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_stores.py +0 -0
  133. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_streams.py +0 -0
  134. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_subscriptions.py +0 -0
  135. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/_utils.py +0 -0
  136. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/__init__.py +0 -0
  137. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/_api.py +0 -0
  138. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/_state_tracker.py +0 -0
  139. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/_stats_events.py +0 -0
  140. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/_stats_fetcher.py +0 -0
  141. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/espn/_utils.py +0 -0
  142. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/__init__.py +0 -0
  143. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_api.py +0 -0
  144. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_events.py +0 -0
  145. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_factory.py +0 -0
  146. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_state_tracker.py +0 -0
  147. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_store.py +0 -0
  148. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nba/_utils.py +0 -0
  149. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/__init__.py +0 -0
  150. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_api.py +0 -0
  151. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_events.py +0 -0
  152. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_factory.py +0 -0
  153. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_state_tracker.py +0 -0
  154. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_store.py +0 -0
  155. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/ncaa/_utils.py +0 -0
  156. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/__init__.py +0 -0
  157. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_api.py +0 -0
  158. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_events.py +0 -0
  159. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_factory.py +0 -0
  160. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_state_tracker.py +0 -0
  161. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_store.py +0 -0
  162. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/nfl/_utils.py +0 -0
  163. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/__init__.py +0 -0
  164. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/_events.py +0 -0
  165. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/_factory.py +0 -0
  166. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/polymarket/_models.py +0 -0
  167. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/__init__.py +0 -0
  168. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_api.py +0 -0
  169. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_events.py +0 -0
  170. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_factory.py +0 -0
  171. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_formatters.py +0 -0
  172. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_store.py +0 -0
  173. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/socialmedia/_watchlist.py +0 -0
  174. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/__init__.py +0 -0
  175. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/_api.py +0 -0
  176. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/_events.py +0 -0
  177. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/_factory.py +0 -0
  178. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/_formatters.py +0 -0
  179. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/data/websearch/_store.py +0 -0
  180. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/_rate_limit.py +0 -0
  181. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/gateway/_sse.py +0 -0
  182. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nba/__init__.py +0 -0
  183. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nba/_agent.py +0 -0
  184. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nba/_datastream.py +0 -0
  185. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nba/_formatters.py +0 -0
  186. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ncaa/__init__.py +0 -0
  187. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ncaa/_agent.py +0 -0
  188. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ncaa/_datastream.py +0 -0
  189. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ncaa/_formatters.py +0 -0
  190. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nfl/__init__.py +0 -0
  191. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nfl/_agent.py +0 -0
  192. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nfl/_datastream.py +0 -0
  193. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/nfl/_formatters.py +0 -0
  194. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ray_runtime/__init__.py +0 -0
  195. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/ray_runtime/_impl.py +0 -0
  196. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/sync_service/__init__.py +0 -0
  197. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/sync_service/main.py +0 -0
  198. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/utils/__init__.py +0 -0
  199. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/utils/oss.py +0 -0
  200. {dojozero-0.3.0 → dojozero-0.5.0}/src/dojozero/utils/time.py +0 -0
  201. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_agent_event_throttle.py +0 -0
  202. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_arena_event_deserialization.py +0 -0
  203. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_arena_span_grouping.py +0 -0
  204. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_backtest_cache_naming.py +0 -0
  205. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_betting_formatters.py +0 -0
  206. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_cli_agents.py +0 -0
  207. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_cli_dev_span_start.py +0 -0
  208. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_cluster.py +0 -0
  209. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_dashboard.py +0 -0
  210. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_data_hub.py +0 -0
  211. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_data_nba.py +0 -0
  212. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_data_nfl.py +0 -0
  213. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_game_state_tracker.py +0 -0
  214. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_metadata.py +0 -0
  215. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_nba_formatters.py +0 -0
  216. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_nba_moneyline_agent.py +0 -0
  217. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_nfl_formatters.py +0 -0
  218. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_nfl_moneyline_agent.py +0 -0
  219. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_oss.py +0 -0
  220. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_registry.py +0 -0
  221. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_scheduler.py +0 -0
  222. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_social_board.py +0 -0
  223. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_socialmedia_events.py +0 -0
  224. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_span_models.py +0 -0
  225. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_stats_insight_events.py +0 -0
  226. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_subscriptions.py +0 -0
  227. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_websearch_events.py +0 -0
  228. {dojozero-0.3.0 → dojozero-0.5.0}/tests/test_websearch_formatters.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dojozero
3
- Version: 0.3.0
3
+ Version: 0.5.0
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
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
18
  Requires-Python: >=3.11
19
- Requires-Dist: agentscope[gemini]>=1.0.14
19
+ Requires-Dist: agentscope[gemini]<2,>=1.0.14
20
20
  Requires-Dist: aiohttp>=3.9.0
21
21
  Requires-Dist: dashscope>=1.0.0
22
22
  Requires-Dist: fastapi>=0.128.0
@@ -32,6 +32,8 @@ Requires-Dist: pyyaml>=6.0
32
32
  Requires-Dist: tavily-python>=0.7.12
33
33
  Requires-Dist: uvicorn>=0.40.0
34
34
  Requires-Dist: xdk>=0.9.0
35
+ Provides-Extra: agentid
36
+ Requires-Dist: agent-id-service-sdk>=0.3.0; extra == 'agentid'
35
37
  Provides-Extra: alicloud
36
38
  Requires-Dist: alibabacloud-credentials>=1.0.0; extra == 'alicloud'
37
39
  Requires-Dist: aliyun-log-python-sdk; extra == 'alicloud'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "dojozero"
7
- version = "0.3.0"
7
+ version = "0.5.0"
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"
@@ -26,7 +26,7 @@ dependencies = [
26
26
  "PyYAML>=6.0",
27
27
  "pydantic>=2.12.4",
28
28
  "aiohttp>=3.9.0",
29
- "agentscope[gemini]>=1.0.14",
29
+ "agentscope[gemini]>=1.0.14,<2",
30
30
  "py-clob-client>=0.1.0",
31
31
  "fastapi>=0.128.0",
32
32
  "uvicorn>=0.40.0",
@@ -61,3 +61,6 @@ alicloud = [
61
61
  redis = [
62
62
  "redis>=7.2.1",
63
63
  ]
64
+ agentid = [
65
+ "agent-id-service-sdk>=0.3.0",
66
+ ]
@@ -122,8 +122,14 @@ def load_persona_config(config_path: str | Path) -> PersonaConfig:
122
122
  Parsed PersonaConfig dictionary
123
123
  """
124
124
  path = Path(config_path)
125
- with path.open("r", encoding="utf-8") as f:
126
- data: dict[str, Any] = yaml.safe_load(f)
125
+ try:
126
+ with path.open("r", encoding="utf-8") as f:
127
+ data: dict[str, Any] = yaml.safe_load(f)
128
+ except FileNotFoundError as e:
129
+ raise FileNotFoundError(
130
+ f"Persona config file not found: {path}. Check the persona_config_path "
131
+ "referenced by your agent or trial-source config."
132
+ ) from e
127
133
 
128
134
  return PersonaConfig(sys_prompt=data.get("sys_prompt", ""))
129
135
 
@@ -156,8 +162,14 @@ def load_llm_file_config(config_path: str | Path) -> LLMFileConfig:
156
162
  Parsed LLMFileConfig dictionary with llm as a list of LLMConfig
157
163
  """
158
164
  path = Path(config_path)
159
- with path.open("r", encoding="utf-8") as f:
160
- data: dict[str, Any] = yaml.safe_load(f)
165
+ try:
166
+ with path.open("r", encoding="utf-8") as f:
167
+ data: dict[str, Any] = yaml.safe_load(f)
168
+ except FileNotFoundError as e:
169
+ raise FileNotFoundError(
170
+ f"LLM config file not found: {path}. Check the llm_config_path "
171
+ "referenced by your agent or trial-source config."
172
+ ) from e
161
173
 
162
174
  llm_configs: list[LLMConfig] = []
163
175
 
@@ -40,7 +40,21 @@ class CacheConfig:
40
40
  trials_limit: int = 500
41
41
 
42
42
  # Time range
43
- trials_lookback_days: int = 90
43
+ trials_lookback_days: int = 365
44
+ # Per-league lookback override (in days). League name uppercase.
45
+ # Used to filter per-league cached views (leaderboard/games/stats/agent_actions).
46
+ # May exceed trials_lookback_days: the SLS fetch window auto-expands to
47
+ # max(trials_lookback_days, max(league_lookback_days.values())) in _sync, so a
48
+ # larger per-league window is still fully covered.
49
+ league_lookback_days: dict[str, int] = field(
50
+ default_factory=lambda: {"NBA": 90, "NFL": 365}
51
+ )
52
+
53
+ def get_league_lookback(self, league: str | None) -> int:
54
+ """Effective lookback (days) for a given league. Falls back to global."""
55
+ if league is None:
56
+ return self.trials_lookback_days
57
+ return self.league_lookback_days.get(league.upper(), self.trials_lookback_days)
44
58
 
45
59
  @classmethod
46
60
  def from_arena_config(cls, config: "ArenaServerConfig") -> "CacheConfig":
@@ -55,6 +69,7 @@ class CacheConfig:
55
69
  leaderboard_limit=config.query_limits.leaderboard_limit,
56
70
  trials_limit=config.cache.trials_limit,
57
71
  trials_lookback_days=config.cache.trials_lookback_days,
72
+ league_lookback_days=dict(config.cache.league_lookback_days),
58
73
  )
59
74
 
60
75
 
@@ -62,7 +77,7 @@ class CacheConfig:
62
77
  from dojozero.arena_server._config import ArenaServerConfig # noqa: E402
63
78
 
64
79
  DEFAULT_CACHE_CONFIG = CacheConfig()
65
- CACHEABLE_LEAGUES: frozenset[str] = frozenset({"NBA", "NFL"})
80
+ CACHEABLE_LEAGUES: frozenset[str] = frozenset({"NBA", "NFL", "WORLD_CUP"})
66
81
  LEADERBOARD_PERIODS: tuple[str, ...] = ("7d", "14d", "30d")
67
82
 
68
83
 
@@ -102,7 +117,7 @@ class LandingPageCache:
102
117
  - leaderboard: Agent rankings (global + per-league)
103
118
  - agent_actions: Recent agent actions (global + per-league)
104
119
 
105
- Per-league caches are maintained for CACHEABLE_LEAGUES (NBA, NFL).
120
+ Per-league caches are maintained for CACHEABLE_LEAGUES.
106
121
 
107
122
  Note: No lock is needed because BackgroundRefresher is the single writer
108
123
  and Python's GIL ensures atomic reference assignments.
@@ -20,7 +20,12 @@ class CacheConfig(BaseModel):
20
20
 
21
21
  # Time range
22
22
  trials_lookback_days: int = Field(
23
- default=90, description="Days to look back for trials"
23
+ default=365,
24
+ description="Days to look back for trials (global SLS fetch window; auto-expanded to cover any larger league_lookback_days)",
25
+ )
26
+ league_lookback_days: dict[str, int] = Field(
27
+ default_factory=lambda: {"NBA": 90, "NFL": 365},
28
+ description="Per-league lookback (days). Used to filter per-league cached views.",
24
29
  )
25
30
  trials_limit: int = Field(default=500, description="Max trials to fetch per query")
26
31
 
@@ -237,7 +237,11 @@ def register_rest_endpoints(app: FastAPI) -> None:
237
237
  superbowl_game = next(
238
238
  (g for g in all_games if SUPER_BOWL_GAME_ID in g.id), None
239
239
  )
240
- if superbowl_game and superbowl_game not in live_games:
240
+ if (
241
+ superbowl_game
242
+ and superbowl_game.status == "live"
243
+ and superbowl_game not in live_games
244
+ ):
241
245
  live_games = [superbowl_game] + list(live_games)
242
246
 
243
247
  # only for mock test
@@ -385,9 +389,13 @@ def register_rest_endpoints(app: FastAPI) -> None:
385
389
  default=None,
386
390
  description="Agent type filter: 'built_in' or 'external'.",
387
391
  ),
392
+ mode: str | None = Query(
393
+ default=None,
394
+ description="Leaderboard mode filter: 'market' or 'prediction'.",
395
+ ),
388
396
  sort_by: str = Query(
389
397
  default="winnings",
390
- description="Sort field: 'winnings', 'win_rate', 'roi', 'total_bets'.",
398
+ description="Sort field: 'winnings', 'win_rate', 'roi', 'total_bets', 'sharpe', 'prediction_score', 'accuracy', 'total_predictions'.",
391
399
  ),
392
400
  sort_order: str = Query(
393
401
  default="desc",
@@ -413,6 +421,37 @@ def register_rest_endpoints(app: FastAPI) -> None:
413
421
  "error": f"Invalid period '{period}'. Must be one of: {', '.join(sorted(valid_periods))}"
414
422
  },
415
423
  )
424
+ valid_modes = {None, "market", "prediction"}
425
+ if mode not in valid_modes:
426
+ return JSONResponse(
427
+ status_code=400,
428
+ content={"error": "Invalid mode. Must be one of: market, prediction."},
429
+ )
430
+ valid_sort_by = {
431
+ "winnings",
432
+ "win_rate",
433
+ "roi",
434
+ "total_bets",
435
+ "sharpe",
436
+ "prediction_score",
437
+ "accuracy",
438
+ "total_predictions",
439
+ }
440
+ if sort_by not in valid_sort_by:
441
+ return JSONResponse(
442
+ status_code=400,
443
+ content={
444
+ "error": f"Invalid sort_by '{sort_by}'. Must be one of: {', '.join(sorted(valid_sort_by))}"
445
+ },
446
+ )
447
+ valid_sort_orders = {"asc", "desc"}
448
+ if sort_order not in valid_sort_orders:
449
+ return JSONResponse(
450
+ status_code=400,
451
+ content={
452
+ "error": f"Invalid sort_order '{sort_order}'. Must be one of: asc, desc"
453
+ },
454
+ )
416
455
 
417
456
  # All paths now read from pre-computed cache
418
457
  effective_period = period if period != "all" else None
@@ -437,16 +476,67 @@ def register_rest_endpoints(app: FastAPI) -> None:
437
476
  elif agent_type == "built_in":
438
477
  leaderboard = [e for e in leaderboard if not e.agent.is_external]
439
478
 
440
- # 2. Sort (cached path is already sorted by winnings desc; re-sort only when needed)
441
- if sort_by != "winnings" or sort_order != "desc":
479
+ # Mode split: agents are shared across sports, so an agent can have both
480
+ # betting PnL (market) and a prediction score. Filter by *activity* rather
481
+ # than mutual exclusion so a top bettor that also predicted still shows on
482
+ # the market board (with winnings) and on the prediction board (with score).
483
+ if mode == "prediction":
484
+ leaderboard = [e for e in leaderboard if e.prediction_score is not None]
485
+ elif mode == "market":
486
+ leaderboard = [
487
+ e for e in leaderboard if e.total_bets > 0 or e.winnings != 0
488
+ ]
489
+
490
+ # 2. Sort (prediction-mode rows use ScoringSys metrics, not betting PnL)
491
+ has_prediction_data = any(e.prediction_score is not None for e in leaderboard)
492
+ is_world_cup_view = league is not None and league.upper() == "WORLD_CUP"
493
+ # mode="market" is an explicit betting view: never remap its sort to
494
+ # prediction_score, even for World Cup. Only an unspecified mode falls
495
+ # back to the league's default (prediction) view.
496
+ is_prediction_view = mode == "prediction" or (
497
+ is_world_cup_view and mode is None
498
+ )
499
+ effective_sort_by = sort_by
500
+ if (
501
+ is_prediction_view
502
+ and has_prediction_data
503
+ and sort_by
504
+ in (
505
+ "winnings",
506
+ "win_rate",
507
+ "roi",
508
+ "total_bets",
509
+ "sharpe",
510
+ )
511
+ ):
512
+ effective_sort_by = "prediction_score"
513
+
514
+ if (
515
+ sort_by != "winnings"
516
+ or sort_order != "desc"
517
+ or effective_sort_by != sort_by
518
+ ):
442
519
  sort_key_map = {
443
520
  "winnings": lambda x: x.winnings,
444
521
  "win_rate": lambda x: x.win_rate,
445
522
  "roi": lambda x: x.roi,
446
523
  "sharpe": lambda x: x.sharpe,
447
524
  "total_bets": lambda x: x.total_bets,
525
+ "prediction_score": lambda x: (
526
+ x.prediction_score
527
+ if x.prediction_score is not None
528
+ else -float("inf")
529
+ ),
530
+ "accuracy": lambda x: (
531
+ x.accuracy if x.accuracy is not None else -float("inf")
532
+ ),
533
+ "total_predictions": lambda x: (
534
+ x.total_predictions
535
+ if x.total_predictions is not None
536
+ else -float("inf")
537
+ ),
448
538
  }
449
- key_fn = sort_key_map.get(sort_by, sort_key_map["winnings"])
539
+ key_fn = sort_key_map.get(effective_sort_by, sort_key_map["winnings"])
450
540
  leaderboard = sorted(leaderboard, key=key_fn, reverse=(sort_order != "asc"))
451
541
 
452
542
  # 3. Limit
@@ -42,6 +42,7 @@ class AgentProfileStats(BaseModel):
42
42
  win_rate: float = Field(default=0.0, serialization_alias="winRate")
43
43
  total_bets: int = Field(default=0, serialization_alias="totalBets")
44
44
  roi: float = 0.0
45
+ sharpe: float = 0.0
45
46
 
46
47
 
47
48
  class AgentProfileResponse(BaseModel):
@@ -75,11 +76,20 @@ class StatsResponse(BaseModel):
75
76
 
76
77
  model_config = ConfigDict(frozen=True, populate_by_name=True)
77
78
 
79
+ # serialization_alias matches the field name; kept for consistency with the
80
+ # rest of the model (every field declares its wire name) and rename-safety.
81
+ mode: Literal["betting", "prediction", "mixed"] = Field(
82
+ default="betting", serialization_alias="mode"
83
+ )
78
84
  games_played: int = Field(default=0, serialization_alias="gamesPlayed")
79
85
  live_now: int = Field(default=0, serialization_alias="liveNow")
80
86
  wagered_today: int = Field(default=0, serialization_alias="wageredToday")
81
87
  total_agents: int = Field(default=0, serialization_alias="totalAgents")
82
88
  bet_counts: int = Field(default=0, serialization_alias="betCounts")
89
+ prediction_count: int = Field(default=0, serialization_alias="predictionCount")
90
+ prediction_points: float = Field(
91
+ default=0.0, serialization_alias="predictionPoints"
92
+ )
83
93
 
84
94
 
85
95
  class GameCardData(BaseModel):
@@ -89,6 +99,11 @@ class GameCardData(BaseModel):
89
99
 
90
100
  id: str
91
101
  league: str = ""
102
+ # Contest type for sports run as multiple trials per match (e.g. World Cup
103
+ # runs both a window-pool "prediction" trial and a moneyline "betting"
104
+ # trial). Empty when unknown / not applicable. Used by the landing dedup to
105
+ # prefer the prediction trial. See _detect_contest_kind.
106
+ contest_kind: str = Field(default="", serialization_alias="contestKind")
92
107
  home_team: TeamIdentity = Field(
93
108
  default_factory=TeamIdentity,
94
109
  serialization_alias="homeTeam",
@@ -29,7 +29,7 @@ Filtering:
29
29
 
30
30
  Supported endpoints: /api/landing, /api/stats, /api/games, /api/leaderboard, /api/agent-actions
31
31
 
32
- Per-league results are cached separately for leagues in CACHEABLE_LEAGUES (NBA, NFL).
32
+ Per-league results are cached separately for leagues in CACHEABLE_LEAGUES.
33
33
  To add a new league, update CACHEABLE_LEAGUES in the code.
34
34
 
35
35
  Configuration:
@@ -90,6 +90,7 @@ from dojozero.arena_server._utils import (
90
90
  _compute_leaderboard,
91
91
  _compute_leaderboard_from_spans,
92
92
  _load_replay_data,
93
+ ARENA_RENDERED_OPERATIONS,
93
94
  TRIAL_INFO_OPERATION_NAMES,
94
95
  trial_id_for_span_grouping,
95
96
  )
@@ -789,7 +790,11 @@ class BackgroundRefresher:
789
790
  tid: str, span_start: datetime | None
790
791
  ) -> tuple[str, list[SpanData]]:
791
792
  async with sem:
792
- spans = await self.trace_reader.get_spans(tid, start_time=span_start)
793
+ spans = await self.trace_reader.get_spans(
794
+ tid,
795
+ start_time=span_start,
796
+ operation_names=ARENA_RENDERED_OPERATIONS,
797
+ )
793
798
  return tid, spans
794
799
 
795
800
  if is_initial or self._last_span_fetch_time is None:
@@ -1417,7 +1422,9 @@ class BackgroundRefresher:
1417
1422
 
1418
1423
  # Fallback to SLS (slow path)
1419
1424
  if not spans:
1420
- spans = await self.trace_reader.get_spans(trial_id)
1425
+ spans = await self.trace_reader.get_spans(
1426
+ trial_id, operation_names=ARENA_RENDERED_OPERATIONS
1427
+ )
1421
1428
 
1422
1429
  existing = self.cache.get_trial_details(trial_id)
1423
1430