report-issue.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. const { execSync } = require("child_process")
  2. const readline = require("readline")
  3. const os = require("os")
  4. const rl = readline.createInterface({
  5. input: process.stdin,
  6. output: process.stdout,
  7. })
  8. const ask = (question) => new Promise((resolve) => rl.question(`\n${question}`, resolve))
  9. const getClineVersion = () => {
  10. try {
  11. const extensions = execSync("code --list-extensions --show-versions").toString()
  12. const clineMatch = extensions.match(/claude-dev@(\d+\.\d+\.\d+)/)
  13. return clineMatch ? clineMatch[1] : "Not installed"
  14. } catch (_err) {
  15. return "Error getting version"
  16. }
  17. }
  18. const collectSystemInfo = () => {
  19. let cpuInfo = "N/A"
  20. let memoryInfo = "N/A"
  21. try {
  22. if (process.platform === "darwin") {
  23. cpuInfo = execSync("sysctl -n machdep.cpu.brand_string").toString().trim()
  24. memoryInfo = execSync("sysctl -n hw.memsize").toString().trim()
  25. memoryInfo = `${Math.round(parseInt(memoryInfo) / 1e9)} GB RAM`
  26. } else {
  27. // Linux specific commands
  28. cpuInfo = execSync("lscpu").toString().split("\n").slice(0, 5).join("\n")
  29. memoryInfo = execSync("free -h").toString()
  30. }
  31. } catch (_err) {
  32. // Fallback for unsupported systems
  33. cpuInfo = Array.from(new Set(os.cpus().map((c) => c.model))).join("\n")
  34. memoryInfo = `${Math.round(os.totalmem() / 1e9)} GB RAM`
  35. }
  36. return {
  37. cpuInfo,
  38. memoryInfo,
  39. os: `${os.arch()}; ${os.version()}`,
  40. nodeVersion: execSync("node -v").toString().trim(),
  41. npmVersion: execSync("npm -v").toString().trim(),
  42. clineVersion: getClineVersion(),
  43. }
  44. }
  45. const checkGitHubAuth = async () => {
  46. try {
  47. execSync("gh auth status", { stdio: "ignore" })
  48. return true
  49. } catch (_err) {
  50. console.log("\nGitHub authentication required.")
  51. console.log("\nPlease run the following command in your terminal to authenticate:")
  52. console.log("\n gh auth login\n")
  53. console.log("After authenticating, run this script again.")
  54. return false
  55. }
  56. }
  57. const createIssueUrl = (systemInfo, issueTitle) => {
  58. return (
  59. `https://github.com/cline/cline/issues/new?template=bug_report.yml` +
  60. `&title=${issueTitle}` +
  61. `&operating-system=${systemInfo.os}` +
  62. `&cline-version=${systemInfo.clineVersion}` +
  63. `&system-info=${
  64. `Node: ${systemInfo.nodeVersion}\n` +
  65. `npm: ${systemInfo.npmVersion}\n` +
  66. `CPU Info: ${systemInfo.cpuInfo}\n` +
  67. `Free RAM: ${systemInfo.memoryInfo}`
  68. }`
  69. )
  70. }
  71. const openUrl = (url) => {
  72. try {
  73. switch (process.platform) {
  74. case "darwin":
  75. execSync(`open "${url}"`)
  76. break
  77. case "win32":
  78. execSync(`start "" "${url}"`)
  79. break
  80. case "linux":
  81. execSync(`xdg-open "${url}"`)
  82. break
  83. default:
  84. console.log("\nPlease open this URL in your browser:")
  85. console.log(url)
  86. }
  87. } catch (_err) {
  88. console.log("\nFailed to open URL automatically. Please open this URL in your browser:")
  89. console.log(url)
  90. }
  91. }
  92. const submitIssue = async (issueTitle, systemInfo) => {
  93. try {
  94. const issueUrl = createIssueUrl(systemInfo, issueTitle)
  95. console.log("\nOpening GitHub issue creation page in your browser...")
  96. openUrl(issueUrl)
  97. } catch (err) {
  98. console.error("\nFailed to create issue URL:", err.message)
  99. }
  100. }
  101. async function main() {
  102. const consent = await ask("Do you consent to collect system data and submit a GitHub issue? (y/n): ")
  103. if (consent.trim().toLowerCase() !== "y") {
  104. console.log("\nAborted.")
  105. rl.close()
  106. return
  107. }
  108. console.log("Collecting system data...")
  109. const systemInfo = collectSystemInfo()
  110. const isAuthenticated = await checkGitHubAuth()
  111. if (!isAuthenticated) {
  112. rl.close()
  113. return
  114. }
  115. const issueTitle = await ask("Enter the title for your issue: ")
  116. await submitIssue(issueTitle, systemInfo)
  117. rl.close()
  118. }
  119. main().catch((err) => {
  120. console.error("\nAn error occurred:", err)
  121. rl.close()
  122. })