fix: route feedback issue links by category (#6840)

## Summary
- TUI feedback note now only links to the bug-report template when the
category is bug/bad result.
- Good result/other feedback shows a thank-you+thread ID instead of
funneling people to file a bug.
- Added a helper + unit test so future changes keep the behavior
consistent.

## Testing
  - just fmt
  - just fix -p codex-tui
  - cargo test -p codex-tui

  Fixes #6839
This commit is contained in:
Weiller Carvalho
2025-11-20 13:20:03 -08:00
committed by GitHub
parent e4257f432e
commit a8a6cbdd1c
+49 -9
View File
@@ -26,7 +26,8 @@ use super::popup_consts::standard_popup_hint_line;
use super::textarea::TextArea; use super::textarea::TextArea;
use super::textarea::TextAreaState; use super::textarea::TextAreaState;
const BASE_ISSUE_URL: &str = "https://github.com/openai/codex/issues/new?template=2-bug-report.yml"; const BASE_BUG_ISSUE_URL: &str =
"https://github.com/openai/codex/issues/new?template=2-bug-report.yml";
/// Minimal input overlay to collect an optional feedback note, then upload /// Minimal input overlay to collect an optional feedback note, then upload
/// both logs and rollout with classification + metadata. /// both logs and rollout with classification + metadata.
@@ -88,26 +89,38 @@ impl FeedbackNoteView {
match result { match result {
Ok(()) => { Ok(()) => {
let issue_url = format!("{BASE_ISSUE_URL}&steps=Uploaded%20thread:%20{thread_id}");
let prefix = if self.include_logs { let prefix = if self.include_logs {
"• Feedback uploaded." "• Feedback uploaded."
} else { } else {
"• Feedback recorded (no logs)." "• Feedback recorded (no logs)."
}; };
self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new( let issue_url = issue_url_for_category(self.category, &thread_id);
history_cell::PlainHistoryCell::new(vec![ let mut lines = vec![Line::from(match issue_url.as_ref() {
Line::from(format!( Some(_) => format!("{prefix} Please open an issue using the following URL:"),
"{prefix} Please open an issue using the following URL:" None => format!("{prefix} Thanks for the feedback!"),
)), })];
if let Some(url) = issue_url {
lines.extend([
"".into(), "".into(),
Line::from(vec![" ".into(), issue_url.cyan().underlined()]), Line::from(vec![" ".into(), url.cyan().underlined()]),
"".into(), "".into(),
Line::from(vec![ Line::from(vec![
" Or mention your thread ID ".into(), " Or mention your thread ID ".into(),
std::mem::take(&mut thread_id).bold(), std::mem::take(&mut thread_id).bold(),
" in an existing issue.".into(), " in an existing issue.".into(),
]), ]),
]), ]);
} else {
lines.extend([
"".into(),
Line::from(vec![
" Thread ID: ".into(),
std::mem::take(&mut thread_id).bold(),
]),
]);
}
self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new(
history_cell::PlainHistoryCell::new(lines),
))); )));
} }
Err(e) => { Err(e) => {
@@ -320,6 +333,15 @@ fn feedback_classification(category: FeedbackCategory) -> &'static str {
} }
} }
fn issue_url_for_category(category: FeedbackCategory, thread_id: &str) -> Option<String> {
match category {
FeedbackCategory::Bug | FeedbackCategory::BadResult | FeedbackCategory::Other => Some(
format!("{BASE_BUG_ISSUE_URL}&steps=Uploaded%20thread:%20{thread_id}"),
),
FeedbackCategory::GoodResult => None,
}
}
// Build the selection popup params for feedback categories. // Build the selection popup params for feedback categories.
pub(crate) fn feedback_selection_params( pub(crate) fn feedback_selection_params(
app_event_tx: AppEventSender, app_event_tx: AppEventSender,
@@ -514,4 +536,22 @@ mod tests {
let rendered = render(&view, 60); let rendered = render(&view, 60);
insta::assert_snapshot!("feedback_view_other", rendered); insta::assert_snapshot!("feedback_view_other", rendered);
} }
#[test]
fn issue_url_available_for_bug_bad_result_and_other() {
let bug_url = issue_url_for_category(FeedbackCategory::Bug, "thread-1");
assert!(
bug_url
.as_deref()
.is_some_and(|url| url.contains("template=2-bug-report"))
);
let bad_result_url = issue_url_for_category(FeedbackCategory::BadResult, "thread-2");
assert!(bad_result_url.is_some());
let other_url = issue_url_for_category(FeedbackCategory::Other, "thread-3");
assert!(other_url.is_some());
assert!(issue_url_for_category(FeedbackCategory::GoodResult, "t").is_none());
}
} }