(data: FeedbackData, signal?: AbortSignal)
| 516 | } |
| 517 | } |
| 518 | async function submitFeedback(data: FeedbackData, signal?: AbortSignal): Promise<{ |
| 519 | success: boolean; |
| 520 | feedbackId?: string; |
| 521 | isZdrOrg?: boolean; |
| 522 | }> { |
| 523 | if (isEssentialTrafficOnly()) { |
| 524 | return { |
| 525 | success: false |
| 526 | }; |
| 527 | } |
| 528 | try { |
| 529 | // Ensure OAuth token is fresh before getting auth headers |
| 530 | // This prevents 401 errors from stale cached tokens |
| 531 | await checkAndRefreshOAuthTokenIfNeeded(); |
| 532 | const authResult = getAuthHeaders(); |
| 533 | if (authResult.error) { |
| 534 | return { |
| 535 | success: false |
| 536 | }; |
| 537 | } |
| 538 | const headers: Record<string, string> = { |
| 539 | 'Content-Type': 'application/json', |
| 540 | 'User-Agent': getUserAgent(), |
| 541 | ...authResult.headers |
| 542 | }; |
| 543 | const response = await axios.post('https://api.anthropic.com/api/claude_cli_feedback', { |
| 544 | content: jsonStringify(data) |
| 545 | }, { |
| 546 | headers, |
| 547 | timeout: 30000, |
| 548 | // 30 second timeout to prevent hanging |
| 549 | signal |
| 550 | }); |
| 551 | if (response.status === 200) { |
| 552 | const result = response.data; |
| 553 | if (result?.feedback_id) { |
| 554 | return { |
| 555 | success: true, |
| 556 | feedbackId: result.feedback_id |
| 557 | }; |
| 558 | } |
| 559 | sanitizeAndLogError(new Error('Failed to submit feedback: request did not return feedback_id')); |
| 560 | return { |
| 561 | success: false |
| 562 | }; |
| 563 | } |
| 564 | sanitizeAndLogError(new Error('Failed to submit feedback:' + response.status)); |
| 565 | return { |
| 566 | success: false |
| 567 | }; |
| 568 | } catch (err) { |
| 569 | // Handle cancellation/abort - don't log as error |
| 570 | if (axios.isCancel(err)) { |
| 571 | return { |
| 572 | success: false |
| 573 | }; |
| 574 | } |
| 575 | if (axios.isAxiosError(err) && err.response?.status === 403) { |
no test coverage detected