@@ -163,7 +163,7 @@ def _load_alphasift_hotspot_detail_cache(
163163 if stale and not allow_stale :
164164 return None
165165
166- cached = dict (payload )
166+ cached = _ensure_hotspot_detail_compat_fields ( dict (payload ) )
167167 cached .update ({
168168 "enabled" : True ,
169169 "provider" : provider or cached .get ("provider" ) or "akshare" ,
@@ -181,7 +181,7 @@ def _write_alphasift_hotspot_detail_cache(*, provider: str, topic: str, payload:
181181 cache_path = _alphasift_hotspot_detail_cache_path (provider = provider , topic = topic )
182182 try :
183183 cache_path .parent .mkdir (parents = True , exist_ok = True )
184- cleaned = _remove_non_finite_json_values (dict (payload ))
184+ cleaned = _remove_non_finite_json_values (_ensure_hotspot_detail_compat_fields ( dict (payload ) ))
185185 cached_at = _utc_now_iso ()
186186 cache_path .write_text (
187187 json .dumps (
@@ -201,6 +201,25 @@ def _write_alphasift_hotspot_detail_cache(*, provider: str, topic: str, payload:
201201 logger .warning ("Failed to write AlphaSift hotspot detail cache for %s: %s" , topic , exc )
202202
203203
204+ def _ensure_hotspot_detail_compat_fields (payload : Dict [str , Any ]) -> Dict [str , Any ]:
205+ """Keep old and new AlphaSift hotspot detail consumers on the same shape."""
206+ stocks = payload .get ("stocks" )
207+ leader_stocks = payload .get ("leader_stocks" )
208+ if not isinstance (stocks , list ):
209+ stocks = []
210+ if not isinstance (leader_stocks , list ):
211+ leader_stocks = []
212+ if not stocks and leader_stocks :
213+ stocks = leader_stocks
214+ if not leader_stocks and stocks :
215+ leader_stocks = stocks
216+ payload ["stocks" ] = stocks
217+ payload ["leader_stocks" ] = leader_stocks
218+ if not isinstance (payload .get ("stock_count" ), int ):
219+ payload ["stock_count" ] = len (stocks )
220+ return payload
221+
222+
204223def _load_alphasift_hotspot_cache (* , provider : str , top : int ) -> Optional [Dict [str , Any ]]:
205224 cache_path = _alphasift_hotspot_cache_path ()
206225 try :
@@ -1028,6 +1047,7 @@ def hotspot_detail(self, *, topic: str, provider: str = "", refresh: bool = Fals
10281047 if search_routes :
10291048 route = normalized .get ("route" )
10301049 normalized ["route" ] = search_routes + (route if isinstance (route , list ) else [])
1050+ normalized = _ensure_hotspot_detail_compat_fields (normalized )
10311051 normalized ["enabled" ] = True
10321052 normalized ["provider" ] = provider_name
10331053 cleaned = _remove_non_finite_json_values (normalized )
@@ -1105,7 +1125,13 @@ def _normalize_alphasift_hotspot_detail(detail: Any, *, provider: str, requested
11051125 summary_value = raw .get ("summary" )
11061126 summary : Dict [str , Any ] = summary_value if isinstance (summary_value , dict ) else {}
11071127 stocks_value = raw .get ("stocks" )
1128+ leader_stocks_value = raw .get ("leader_stocks" )
11081129 stocks : List [Any ] = stocks_value if isinstance (stocks_value , list ) else []
1130+ leader_stocks : List [Any ] = leader_stocks_value if isinstance (leader_stocks_value , list ) else []
1131+ if not stocks and leader_stocks :
1132+ stocks = leader_stocks
1133+ if not leader_stocks and stocks :
1134+ leader_stocks = stocks
11091135 timeline_value = raw .get ("timeline" )
11101136 timeline : List [Any ] = timeline_value if isinstance (timeline_value , list ) else []
11111137 route_value = raw .get ("route" )
@@ -1122,7 +1148,7 @@ def _normalize_alphasift_hotspot_detail(detail: Any, *, provider: str, requested
11221148 if isinstance (summary_text_value , str )
11231149 else _build_alphasift_hotspot_summary_text (summary , topic = topic , canonical_topic = canonical_topic )
11241150 )
1125- return {
1151+ return _ensure_hotspot_detail_compat_fields ( {
11261152 "enabled" : True ,
11271153 "provider" : provider ,
11281154 "topic" : topic ,
@@ -1134,6 +1160,7 @@ def _normalize_alphasift_hotspot_detail(detail: Any, *, provider: str, requested
11341160 "route" : route ,
11351161 "timeline" : timeline ,
11361162 "stocks" : stocks ,
1163+ "leader_stocks" : leader_stocks ,
11371164 "stock_count" : len (stocks ),
11381165 "source_errors" : source_errors ,
11391166 "quality_status" : quality_status ,
@@ -1142,7 +1169,7 @@ def _normalize_alphasift_hotspot_detail(detail: Any, *, provider: str, requested
11421169 "stale" : bool (summary .get ("stale" ) or raw .get ("stale" ) or False ),
11431170 "stale_age_hours" : summary .get ("stale_age_hours" ) or raw .get ("stale_age_hours" ),
11441171 "resolver_candidates" : _list_dict_values (summary .get ("resolver_candidates" ) or raw .get ("resolver_candidates" )),
1145- }
1172+ })
11461173
11471174
11481175def _list_text_values (value : Any ) -> List [str ]:
@@ -2190,16 +2217,17 @@ def hotspot_detail(self, topic: str) -> Dict[str, Any]:
21902217 "change_pct" : None ,
21912218 "hot_stock_score" : 60.0 ,
21922219 })
2193- return {
2220+ return _ensure_hotspot_detail_compat_fields ( {
21942221 "topic" : topic ,
21952222 "name" : self ._display_hotspot_name (topic ),
21962223 "canonical_topic" : topic ,
21972224 "summary" : self ._build_hotspot_summary (topic , summary ),
21982225 "route" : route ,
21992226 "stocks" : stocks [:30 ],
2227+ "leader_stocks" : stocks [:30 ],
22002228 "stock_count" : len (stocks ),
22012229 "source_errors" : [],
2202- }
2230+ })
22032231
22042232 def _fetch_board_changes (self ) -> Any :
22052233 import pandas as pd
0 commit comments