@@ -644,9 +644,9 @@ def update_data_link(
644644
645645@app .command ("browse" )
646646def browse_data_link (
647- data_link_id : Annotated [
647+ data_link : Annotated [
648648 str ,
649- typer .Option ( "-i" , "--id" , help = "Data link ID." ),
649+ typer .Argument ( help = "Data link ID or name ." ),
650650 ],
651651 workspace : Annotated [
652652 str | None ,
@@ -684,6 +684,9 @@ def browse_data_link(
684684 if credentials :
685685 cred_id = _resolve_credentials_id (client , workspace_id , credentials )
686686
687+ # Resolve data link ID or name to ID
688+ data_link_id = _resolve_data_link_id_or_name (client , workspace_id , data_link , cred_id )
689+
687690 # Build request params for describe
688691 describe_params : dict [str , Any ] = {}
689692 if workspace_id :
@@ -693,7 +696,7 @@ def browse_data_link(
693696
694697 # Get data link details
695698 describe_response = client .get (f"/data-links/{ data_link_id } " , params = describe_params )
696- data_link = describe_response .get ("dataLink" , describe_response )
699+ data_link_info = describe_response .get ("dataLink" , describe_response )
697700
698701 # Build browse params
699702 browse_params : dict [str , Any ] = {}
@@ -717,7 +720,7 @@ def browse_data_link(
717720 browse_response = client .get (browse_url , params = browse_params )
718721
719722 result = DataLinkContentList (
720- data_link = data_link ,
723+ data_link = data_link_info ,
721724 path = path ,
722725 objects = browse_response .get ("objects" , []),
723726 next_page_token = browse_response .get ("nextPageToken" ),
@@ -821,6 +824,59 @@ def _explore_data_link_tree(
821824 return response .get ("items" , [])
822825
823826
827+ def _resolve_data_link_id_or_name (
828+ client : SeqeraClient ,
829+ workspace_id : int | None ,
830+ id_or_name : str ,
831+ credentials_id : str | None = None ,
832+ ) -> str :
833+ """Resolve data link ID or name to data link ID.
834+
835+ First tries to use the value as an ID directly, then falls back to exact name match.
836+ """
837+ # First, try to use it as an ID directly
838+ params : dict [str , Any ] = {}
839+ if workspace_id :
840+ params ["workspaceId" ] = workspace_id
841+ if credentials_id :
842+ params ["credentialsId" ] = credentials_id
843+
844+ try :
845+ response = client .get (f"/data-links/{ id_or_name } " , params = params )
846+ data_link = response .get ("dataLink" , response )
847+ if data_link and data_link .get ("id" ):
848+ return data_link .get ("id" )
849+ except Exception :
850+ pass # Not a valid ID, try searching by name
851+
852+ # Search by name
853+ search_params = {** params , "search" : id_or_name }
854+ response = client .get ("/data-links" , params = search_params )
855+ data_links = response .get ("dataLinks" , [])
856+
857+ # Only accept exact name matches
858+ exact_matches = [dl for dl in data_links if dl .get ("name" ) == id_or_name ]
859+ if len (exact_matches ) == 1 :
860+ return exact_matches [0 ].get ("id" )
861+
862+ if len (exact_matches ) > 1 :
863+ output_error (
864+ f"Multiple data links found with name '{ id_or_name } '. "
865+ "Please use the data link ID instead."
866+ )
867+ raise typer .Exit (1 )
868+
869+ # No exact match found - suggest partial matches if any
870+ if data_links :
871+ suggestions = [dl .get ("name" ) for dl in data_links [:5 ]] # Limit to 5 suggestions
872+ suggestion_str = ", " .join (f"'{ s } '" for s in suggestions )
873+ output_error (f"Data link '{ id_or_name } ' not found. " f"Did you mean: { suggestion_str } ?" )
874+ else :
875+ output_error (f"Data link '{ id_or_name } ' not found" )
876+
877+ raise typer .Exit (1 )
878+
879+
824880def _resolve_data_link_id (
825881 client : SeqeraClient ,
826882 workspace_id : int | None ,
0 commit comments