Skip to content

Commit 28a44a4

Browse files
committed
make feedback request generic
1 parent 1e95aa4 commit 28a44a4

1 file changed

Lines changed: 147 additions & 7 deletions

File tree

packages/prime/src/prime_cli/commands/feedback.py

Lines changed: 147 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,89 @@
1-
"""Feedback submission command."""
2-
31
from typing import Optional
42

53
import typer
64
from 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

129
app = 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("\nSelect", 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("\nSelect", 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("\nSelect", 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("\nSelect", 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

Comments
 (0)