Skip to content

Instantly share code, notes, and snippets.

@laiso
Last active April 21, 2024 05:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laiso/baa0763cee4e9b0534a72c8ab0cf6c97 to your computer and use it in GitHub Desktop.
Save laiso/baa0763cee4e9b0534a72c8ab0cf6c97 to your computer and use it in GitHub Desktop.
send repo to Google Gemini API
const fs = require('fs');
const https = require('https');
const { execSync } = require('child_process');
const model = 'gemini-1.5-pro-latest';
function getGitTrackedFiles(basePath) {
const command = `git ls-files ${basePath}`;
try {
const stdout = execSync(command, { encoding: 'utf8' });
return stdout.split(/\r?\n/).filter(line => line);
} catch (err) {
console.error(`Error executing git ls-files: ${err}`);
return [];
}
}
/**
* TODO: It checks each byte in the file and if it contains more than 128 bytes (non-ASCII characters), the file is considered a binary file.
* However, this method is not perfect. Some text files may contain non-ASCII characters, and some binary files may contain only ASCII characters.
*/
function isTextFile(file) {
try {
const buffer = fs.readFileSync(file);
const isBinary = buffer.some(byte => byte > 127);
return !isBinary;
} catch (err) {
console.warn(`Error reading file: ${err}`);
return false;
}
}
function getFilesContent(basePath) {
const files = getGitTrackedFiles(basePath);
const filesContent = [];
files.forEach(file => {
// Exclude binary files
if (isTextFile(file)) {
try {
const data = fs.readFileSync(file, 'utf8').replace(/\\n/g, '');
filesContent.push(`${file}=${data}`); // Format as CSV
} catch (err) {
console.error(`Error reading file: ${err}`);
}
}
});
return filesContent.join('&');
}
function generateComment(filesContent, prompt) {
return new Promise((resolve, reject) => {
const data = JSON.stringify({
"contents": [
{
"role": "user",
"parts": {
"text": `Background:
The following is information read from a list of source codes.
Files:
${encodeURIComponent(filesContent)}
Question:
${prompt}
Please answer the question by referencing the specific filenames and source code from the files provided above.`
}
}
]
});
const options = {
hostname: 'generativelanguage.googleapis.com',
path: `/v1beta/models/${model}:generateContent`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
'x-goog-api-key': process.env.GOOGLE_API_KEY
}
};
const req = https.request(options, (res) => {
console.log('HTTP Status Code:', res.statusCode);
let responseBody = '';
res.on('data', (d) => {
responseBody += d;
});
res.on('end', () => {
if (res.statusCode >= 400) {
console.log('Response Body:', responseBody);
reject(new Error('API request failed'));
} else {
const responseJson = JSON.parse(responseBody);
const content = responseJson.candidates[0].content.parts[0].text;
resolve(content);
}
});
});
req.on('error', (e) => {
console.error('Error accessing the website:', e);
reject(e);
});
req.write(data);
req.end();
});
}
async function generateCommentForPath(prompt, path) {
const filesContent = getFilesContent(path);
try {
const comment = await generateComment(filesContent, prompt);
return comment;
} catch (error) {
console.error('Error generating comment:', error);
return 'Error generating comment';
}
}
if (require.main === module) {
const prompt = process.argv[2];
const path = process.argv[3] ?? '.';
generateCommentForPath(prompt, path)
.then(comment => console.log(comment))
.catch(error => console.error(error));
}
module.exports = generateCommentForPath;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment