#!/usr/bin/env node import fs from "fs" import path from "path" import https from "https" import { fileURLToPath } from "url" // Configuration const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const README_FILE = path.join(__dirname, "../README.md") const CONTRIBUTORS_JSON_URL = "https://kilocode.ai/contributors.json" const MAX_CONTRIBUTORS_DISPLAY = 9 const CONTRIBUTORS_PAGE_URL = "https://kilocode.ai/#contributors" // Function to make HTTP requests function makeRequest(url) { return new Promise((resolve, reject) => { https .get(url, (res) => { let data = "" res.on("data", (chunk) => { data += chunk }) res.on("end", () => { try { const jsonData = JSON.parse(data) resolve(jsonData) } catch (error) { reject(error) } }) }) .on("error", (error) => { reject(error) }) }) } // Function to generate Markdown contributor list function generateContributorMarkdown(contributors) { let markdown = "## Contributors\n\n" markdown += "Thanks to all the contributors who help make Kilo Code better!\n\n" // Map the kilocode.ai format to expected format const validContributors = contributors.map((contributor) => { // Convert kilocode.ai format to GitHub-like format return { login: contributor.username, html_url: `https://github.com/${contributor.username}`, avatar_url: `https://avatars.githubusercontent.com/u/${contributor.avatarId}`, } }) // Limit to MAX_CONTRIBUTORS_DISPLAY contributors const displayContributors = validContributors.slice(0, MAX_CONTRIBUTORS_DISPLAY) const hasMore = validContributors.length > MAX_CONTRIBUTORS_DISPLAY // Create a grid of contributor avatars in rows of 5 let contributorGrid = "\n" for (let i = 0; i < displayContributors.length; i++) { const contributor = displayContributors[i] // Start a new row every 5 contributors if (i % 5 === 0) { if (i > 0) { contributorGrid += "\n \n" } contributorGrid += " \n" } const contributorCell = ` ` contributorGrid += contributorCell } // Add "more..." cell if there are more contributors if (hasMore) { // Check if we need to add it to current row or start new row const lastRowCount = displayContributors.length % 5 if (lastRowCount === 0) { // Start a new row for "more..." contributorGrid += "\n \n \n" } const moreCell = ` ` contributorGrid += moreCell } // Close the last row contributorGrid += "\n \n
${contributor.login}
more ...
\n" markdown += contributorGrid return markdown } // Function to update the contributors section in the README async function updateContributorsSection() { try { console.log("Fetching contributors from kilocode.ai...") // Fetch contributors from external JSON const contributors = await makeRequest(CONTRIBUTORS_JSON_URL) if (!Array.isArray(contributors)) { throw new Error("Failed to fetch contributors data") } console.log(`Found ${contributors.length} contributors`) // Generate Markdown content const contributorMarkdown = generateContributorMarkdown(contributors) // Read the existing README let readmeContent = fs.readFileSync(README_FILE, "utf8") // Find the contributors section markers or add at the end const contributorsStartMarker = "## Contributors" const contributorsEndMarker = "" let newContent if (readmeContent.includes(contributorsStartMarker)) { // Replace existing contributors section const startIndex = readmeContent.indexOf(contributorsStartMarker) const endIndex = readmeContent.indexOf(contributorsEndMarker) if (endIndex === -1) { // No end marker, look for any existing table or content after the header // and replace everything from the header to the end of file const afterHeaderIndex = startIndex + contributorsStartMarker.length const beforeContent = readmeContent.substring(0, startIndex) newContent = beforeContent + contributorMarkdown + "\n\n" } else { // Replace between markers - clean replacement between the header and end marker const beforeContent = readmeContent.substring(0, startIndex) const afterContent = readmeContent.substring(endIndex + contributorsEndMarker.length) newContent = beforeContent + contributorMarkdown + "\n" + contributorsEndMarker + afterContent } } else { // Add contributors section at the end newContent = readmeContent.trim() + "\n\n" + contributorMarkdown + "\n\n" } // Write the updated content back to the README fs.writeFileSync(README_FILE, newContent) console.log("Contributors section updated successfully!") } catch (error) { console.error("Error updating contributors section:", error.message) console.error("Stack trace:", error.stack) process.exit(1) } } // Run the script updateContributorsSection()