@@ -194,6 +194,26 @@ def _highlight_ini(text: str) -> str:
194194}
195195
196196
197+ def _detect_has_more (data : Any ) -> bool :
198+ """Check whether a paginated response has more pages to fetch.
199+
200+ Handles two pagination styles:
201+ * ``has_more`` flag (standard Databricks APIs).
202+ * SCIM-style ``totalResults`` / ``startIndex`` / ``itemsPerPage``.
203+ """
204+ if not isinstance (data , dict ):
205+ return False
206+ if data .get ("has_more" ):
207+ return True
208+ # SCIM pagination: totalResults, startIndex, itemsPerPage
209+ total = data .get ("totalResults" )
210+ start = data .get ("startIndex" )
211+ per_page = data .get ("itemsPerPage" )
212+ if isinstance (total , int ) and isinstance (start , int ) and isinstance (per_page , int ):
213+ return (start + per_page - 1 ) < total
214+ return False
215+
216+
197217def _detect_next_page_token (data : Any ) -> Optional [str ]:
198218 """Extract a ``next_page_token`` from a paginated API response.
199219
@@ -759,10 +779,9 @@ def build_response_panel(
759779 if isinstance (data , list ):
760780 item_count = f" · { len (data )} items"
761781 elif isinstance (data , dict ):
762- for v in data .values ():
763- if isinstance (v , list ):
764- item_count = f" · { len (v )} items"
765- break
782+ list_key = _find_list_key (data )
783+ if list_key :
784+ item_count = f" · { len (data [list_key ])} items"
766785
767786 # CSV response: render as a scrollable HTML table
768787 csv_text = result .get ("_csv" )
@@ -2428,7 +2447,7 @@ def execute_api_call(n_clicks, endpoint, param_values, param_ids, body_text, tim
24282447
24292448 chips = extract_chips (endpoint .get ("id" , "" ), result ["data" ]) if result ["success" ] else []
24302449 resp_data = result ["data" ] if isinstance (result ["data" ], dict ) else {}
2431- has_more = bool (resp_data . get ( "has_more" ) )
2450+ has_more = _detect_has_more (resp_data )
24322451 last_req = {
24332452 "path" : path ,
24342453 "method" : method ,
@@ -2439,6 +2458,7 @@ def execute_api_call(n_clicks, endpoint, param_values, param_ids, body_text, tim
24392458 "elapsed_ms" : result ["elapsed_ms" ],
24402459 "status_code" : result ["status_code" ],
24412460 "url" : result .get ("url" , "" ),
2461+ "is_account" : is_account ,
24422462 }
24432463 ep_id = endpoint .get ("id" , "" )
24442464 new_cache = dict (cache or {})
@@ -2461,8 +2481,8 @@ def start_pagination(last_req):
24612481 if not last_req :
24622482 return {}, True
24632483 initial_data = last_req .get ("initial_data" , {})
2464- # Skip auto-pagination when has_more is present — "Load All" handles those
2465- if isinstance (initial_data , dict ) and initial_data . get ( "has_more" ):
2484+ # Skip auto-pagination when has_more is detected — "Load All" handles those
2485+ if isinstance (initial_data , dict ) and _detect_has_more ( initial_data ):
24662486 return {"run_id" : time .time ()}, True
24672487 next_token = _detect_next_page_token (initial_data )
24682488 list_key = _find_list_key (initial_data ) if next_token else None
@@ -2704,6 +2724,10 @@ def _load_all_worker(last_req, host, token, list_key, initial_data):
27042724 offset = len (items )
27052725 next_token = _detect_next_page_token (initial_data )
27062726 use_token = next_token is not None
2727+ # Detect SCIM-style pagination (startIndex / count / totalResults)
2728+ is_scim = "totalResults" in initial_data and "startIndex" in initial_data
2729+ scim_total = int (initial_data .get ("totalResults" , 0 )) if is_scim else 0
2730+ scim_start = int (initial_data .get ("startIndex" , 1 )) + int (initial_data .get ("itemsPerPage" , limit ))
27072731 total_elapsed = last_req .get ("elapsed_ms" , 0 )
27082732 pages = 1
27092733
@@ -2716,6 +2740,9 @@ def _load_all_worker(last_req, host, token, list_key, initial_data):
27162740 qp = dict (last_req .get ("query_params" ) or {})
27172741 if use_token and next_token :
27182742 qp ["page_token" ] = next_token
2743+ elif is_scim :
2744+ qp ["startIndex" ] = str (scim_start )
2745+ qp ["count" ] = str (limit )
27192746 else :
27202747 qp ["offset" ] = str (offset )
27212748 qp ["limit" ] = str (limit )
@@ -2731,17 +2758,24 @@ def _load_all_worker(last_req, host, token, list_key, initial_data):
27312758
27322759 page_data = r ["data" ]
27332760 new_page_items = page_data .get (list_key , [])
2761+ if not new_page_items :
2762+ break
27342763 items .extend (new_page_items )
27352764 pages += 1
27362765 offset += limit
2766+ scim_start += len (new_page_items )
27372767 next_token = _detect_next_page_token (page_data )
27382768
27392769 state ["items" ] = items
27402770 state ["pages" ] = pages
27412771 state ["total_items" ] = len (items )
27422772 state ["elapsed_ms" ] = total_elapsed
27432773
2744- if not page_data .get ("has_more" ):
2774+ # Determine whether more pages remain
2775+ if is_scim :
2776+ if len (items ) >= scim_total :
2777+ break
2778+ elif not _detect_has_more (page_data ):
27452779 break
27462780
27472781 state ["running" ] = False
@@ -2765,13 +2799,18 @@ def start_load_all(n_clicks, last_req, conn_config):
27652799 if not n_clicks or not last_req :
27662800 return NO
27672801 initial_data = last_req .get ("initial_data" , {})
2768- if not isinstance (initial_data , dict ) or not initial_data . get ( "has_more" ):
2802+ if not isinstance (initial_data , dict ) or not _detect_has_more ( initial_data ):
27692803 return NO
27702804 list_key = _find_list_key (initial_data )
27712805 if not list_key :
27722806 return NO
27732807
2774- host , token = _resolve_conn (conn_config )
2808+ # Resolve host/token — account-scope APIs need the accounts console credentials
2809+ ws_host , ws_token = _resolve_conn (conn_config )
2810+ if last_req .get ("is_account" ) and ws_host :
2811+ host , token = resolve_account_connection (conn_config , _accounts_host (ws_host ))
2812+ else :
2813+ host , token = ws_host , ws_token
27752814 if not token or not host :
27762815 return NO
27772816
@@ -2856,6 +2895,10 @@ def poll_load_all(n_intervals, cache):
28562895 merged_data = {** initial_data , list_key : items }
28572896 merged_data .pop ("has_more" , None )
28582897 merged_data .pop ("next_page_token" , None )
2898+ # Clean up SCIM pagination fields in merged result
2899+ merged_data .pop ("totalResults" , None )
2900+ merged_data .pop ("startIndex" , None )
2901+ merged_data .pop ("itemsPerPage" , None )
28592902 merged_result = {
28602903 "status_code" : last_req .get ("status_code" , 200 ),
28612904 "elapsed_ms" : elapsed ,
0 commit comments