| 473 | } |
| 474 | } |
| 475 | function createFallbackTitle(description: string): string { |
| 476 | // Create a safe fallback title based on the bug description |
| 477 | |
| 478 | // Try to extract a meaningful title from the first line |
| 479 | const firstLine = description.split('\n')[0] || ''; |
| 480 | |
| 481 | // If the first line is very short, use it directly |
| 482 | if (firstLine.length <= 60 && firstLine.length > 5) { |
| 483 | return firstLine; |
| 484 | } |
| 485 | |
| 486 | // For longer descriptions, create a truncated version |
| 487 | // Truncate at word boundaries when possible |
| 488 | let truncated = firstLine.slice(0, 60); |
| 489 | if (firstLine.length > 60) { |
| 490 | // Find the last space before the 60 char limit |
| 491 | const lastSpace = truncated.lastIndexOf(' '); |
| 492 | if (lastSpace > 30) { |
| 493 | // Only trim at word if we're not cutting too much |
| 494 | truncated = truncated.slice(0, lastSpace); |
| 495 | } |
| 496 | truncated += '...'; |
| 497 | } |
| 498 | return truncated.length < 10 ? 'Bug Report' : truncated; |
| 499 | } |
| 500 | |
| 501 | // Helper function to sanitize and log errors without exposing API keys |
| 502 | function sanitizeAndLogError(err: unknown): void { |