MCPcopy Index your code
hub / github.com/codeaashu/claude-code / createGitHubIssueUrl

Function createGitHubIssueUrl

src/components/Feedback.tsx:393–446  ·  view source on GitHub ↗
(feedbackId: string, title: string, description: string, errors: Array<{
  error?: string;
  timestamp?: string;
}>)

Source from the content-addressed store, hash-verified

391 </Dialog>;
392}
393export function createGitHubIssueUrl(feedbackId: string, title: string, description: string, errors: Array<{
394 error?: string;
395 timestamp?: string;
396}>): string {
397 const sanitizedTitle = redactSensitiveInfo(title);
398 const sanitizedDescription = redactSensitiveInfo(description);
399 const bodyPrefix = `**Bug Description**\n${sanitizedDescription}\n\n` + `**Environment Info**\n` + `- Platform: ${env.platform}\n` + `- Terminal: ${env.terminal}\n` + `- Version: ${MACRO.VERSION || 'unknown'}\n` + `- Feedback ID: ${feedbackId}\n` + `\n**Errors**\n\`\`\`json\n`;
400 const errorSuffix = `\n\`\`\`\n`;
401 const errorsJson = jsonStringify(errors);
402 const baseUrl = `${GITHUB_ISSUES_REPO_URL}/new?title=${encodeURIComponent(sanitizedTitle)}&labels=user-reported,bug&body=`;
403 const truncationNote = `\n**Note:** Content was truncated.\n`;
404 const encodedPrefix = encodeURIComponent(bodyPrefix);
405 const encodedSuffix = encodeURIComponent(errorSuffix);
406 const encodedNote = encodeURIComponent(truncationNote);
407 const encodedErrors = encodeURIComponent(errorsJson);
408
409 // Calculate space available for errors
410 const spaceForErrors = GITHUB_URL_LIMIT - baseUrl.length - encodedPrefix.length - encodedSuffix.length - encodedNote.length;
411
412 // If description alone exceeds limit, truncate everything
413 if (spaceForErrors <= 0) {
414 const ellipsis = encodeURIComponent('…');
415 const buffer = 50; // Extra safety margin
416 const maxEncodedLength = GITHUB_URL_LIMIT - baseUrl.length - ellipsis.length - encodedNote.length - buffer;
417 const fullBody = bodyPrefix + errorsJson + errorSuffix;
418 let encodedFullBody = encodeURIComponent(fullBody);
419 if (encodedFullBody.length > maxEncodedLength) {
420 encodedFullBody = encodedFullBody.slice(0, maxEncodedLength);
421 // Don't cut in middle of %XX sequence
422 const lastPercent = encodedFullBody.lastIndexOf('%');
423 if (lastPercent >= encodedFullBody.length - 2) {
424 encodedFullBody = encodedFullBody.slice(0, lastPercent);
425 }
426 }
427 return baseUrl + encodedFullBody + ellipsis + encodedNote;
428 }
429
430 // If errors fit, no truncation needed
431 if (encodedErrors.length <= spaceForErrors) {
432 return baseUrl + encodedPrefix + encodedErrors + encodedSuffix;
433 }
434
435 // Truncate errors to fit (prioritize keeping description)
436 // Slice encoded errors directly, then trim to avoid cutting %XX sequences
437 const ellipsis = encodeURIComponent('…');
438 const buffer = 50; // Extra safety margin
439 let truncatedEncodedErrors = encodedErrors.slice(0, spaceForErrors - ellipsis.length - buffer);
440 // If we cut in middle of %XX, back up to before the %
441 const lastPercent = truncatedEncodedErrors.lastIndexOf('%');
442 if (lastPercent >= truncatedEncodedErrors.length - 2) {
443 truncatedEncodedErrors = truncatedEncodedErrors.slice(0, lastPercent);
444 }
445 return baseUrl + encodedPrefix + truncatedEncodedErrors + ellipsis + encodedSuffix + encodedNote;
446}
447async function generateTitle(description: string, abortSignal: AbortSignal): Promise<string> {
448 try {
449 const response = await queryHaiku({

Callers 1

FeedbackFunction · 0.85

Calls 2

redactSensitiveInfoFunction · 0.85
jsonStringifyFunction · 0.85

Tested by

no test coverage detected