1- """Feedback submission command."""
2-
31from typing import Optional
42
53import typer
64from rich .console import Console
75
8- from ..utils .feedback import run_feedback_command
9-
10- console = Console ()
6+ from prime_cli import __version__
7+ from prime_cli .core import APIClient , APIError , Config
118
129app = typer .Typer (
1310 help = "Submit feedback about Prime." ,
1411 no_args_is_help = False ,
1512 invoke_without_command = True ,
1613)
14+ console = Console ()
15+
16+
17+ def send_feedback (
18+ message : str ,
19+ product : str ,
20+ category : str = "general" ,
21+ run_id : Optional [str ] = None ,
22+ ) -> None :
23+ cfg = Config ()
24+
25+ payload = {
26+ "message" : message ,
27+ "product" : product ,
28+ "category" : category ,
29+ "run_id" : run_id ,
30+ "cli_version" : __version__ ,
31+ "user_id" : cfg .user_id ,
32+ "team_id" : cfg .team_id ,
33+ "team_name" : cfg .team_name ,
34+ }
35+
36+ client = APIClient ()
37+ client .post ("/feedback" , json = payload )
38+
39+
40+ def prompt_for_feedback () -> tuple [Optional [str ], str , str , Optional [str ]]:
41+ console .print ("\n [bold]Prime Feedback[/bold]" )
42+ console .print ("[dim]Share bugs, feature ideas, or general thoughts.[/dim]\n " )
43+
44+ # Product selection
45+ console .print ("[bold]Product:[/bold]" )
46+ console .print (" 1. Hosted RL" )
47+ console .print (" 2. Other" )
48+
49+ try :
50+ product_choice = typer .prompt ("\n Select" , type = int , default = 1 )
51+ except (KeyboardInterrupt , typer .Abort ):
52+ return None , "other" , "general" , None
53+
54+ product = {1 : "hosted rl" }.get (product_choice , "other" )
55+
56+ # Category selection
57+ console .print ("\n [bold]Feedback type:[/bold]" )
58+ console .print (" 1. Bug report" )
59+ console .print (" 2. Feature request" )
60+ console .print (" 3. General feedback" )
61+
62+ try :
63+ category_choice = typer .prompt ("\n Select" , type = int , default = 3 )
64+ except (KeyboardInterrupt , typer .Abort ):
65+ return None , product , "general" , None
66+
67+ category = {1 : "bug" , 2 : "feature" }.get (category_choice , "general" )
68+
69+ # Run ID prompt (only for hosted rl)
70+ run_id = None
71+ if product == "hosted rl" :
72+ console .print ("\n [dim]If this is related to a specific run, enter the Run ID (or press Enter to skip)[/dim]" )
73+ try :
74+ run_id = typer .prompt ("Run ID" , default = "" , show_default = False ).strip () or None
75+ except (KeyboardInterrupt , typer .Abort ):
76+ return None , product , category , None
77+
78+ # Feedback message
79+ console .print ("\n [bold]Enter your feedback:[/bold]" )
80+
81+ try :
82+ message = typer .prompt ("" ).strip ()
83+ except (KeyboardInterrupt , typer .Abort ):
84+ return None , product , category , None
85+
86+ return message if message else None , product , category , run_id
1787
1888
1989@app .callback (invoke_without_command = True )
@@ -33,5 +103,75 @@ def feedback(
33103 prime feedback --bug --run abc123 "OOM error"
34104 prime feedback
35105 """
36- if ctx .invoked_subcommand is None :
37- run_feedback_command (message , bug = bug , feature = feature , run_id = run_id )
106+ if ctx .invoked_subcommand is not None :
107+ return
108+
109+ # Determine category from flags
110+ if bug :
111+ category : Optional [str ] = "bug"
112+ elif feature :
113+ category = "feature"
114+ else :
115+ category = None
116+
117+ # If message provided via CLI, still need to prompt for product
118+ if message :
119+ console .print ("\n [bold]Prime Feedback[/bold]\n " )
120+
121+ # Product selection
122+ console .print ("[bold]Product:[/bold]" )
123+ console .print (" 1. Hosted RL" )
124+ console .print (" 2. Other" )
125+
126+ try :
127+ product_choice = typer .prompt ("\n Select" , type = int , default = 1 )
128+ except (KeyboardInterrupt , typer .Abort ):
129+ console .print ("\n [yellow]Cancelled[/yellow]" )
130+ raise typer .Exit (0 )
131+
132+ product = {1 : "hosted rl" }.get (product_choice , "other" )
133+
134+ # If no category from flags, prompt for it
135+ if category is None :
136+ console .print ("\n [bold]Feedback type:[/bold]" )
137+ console .print (" 1. Bug report" )
138+ console .print (" 2. Feature request" )
139+ console .print (" 3. General feedback" )
140+
141+ try :
142+ category_choice = typer .prompt ("\n Select" , type = int , default = 3 )
143+ except (KeyboardInterrupt , typer .Abort ):
144+ console .print ("\n [yellow]Cancelled[/yellow]" )
145+ raise typer .Exit (0 )
146+
147+ category = {1 : "bug" , 2 : "feature" }.get (category_choice , "general" )
148+
149+ # Prompt for run ID if hosted rl and not provided
150+ if product == "hosted rl" and run_id is None :
151+ console .print (
152+ "\n [dim]If this is related to a specific run, enter the Run ID (or press Enter to skip)[/dim]"
153+ )
154+ try :
155+ run_id = typer .prompt ("Run ID" , default = "" , show_default = False ).strip () or None
156+ except (KeyboardInterrupt , typer .Abort ):
157+ console .print ("\n [yellow]Cancelled[/yellow]" )
158+ raise typer .Exit (0 )
159+ else :
160+ # Fully interactive mode
161+ prompted_message , product , prompted_category , prompted_run_id = prompt_for_feedback ()
162+ if not prompted_message :
163+ console .print ("\n [yellow]Cancelled[/yellow]" )
164+ raise typer .Exit (0 )
165+ message = prompted_message
166+ if category is None :
167+ category = prompted_category
168+ if run_id is None :
169+ run_id = prompted_run_id
170+
171+ try :
172+ with console .status ("Submitting..." , spinner = "dots" ):
173+ send_feedback (message , product , category , run_id )
174+ console .print ("[green]Feedback submitted. Thanks![/green]" )
175+ except APIError as e :
176+ console .print (f"[red]Error:[/red] { str (e )} " )
177+ raise typer .Exit (1 )
0 commit comments