mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-02 14:18:43 +08:00
dev: update comment generator
This commit is contained in:
parent
67ee264239
commit
2dfeeeda27
@ -1,3 +1,4 @@
|
||||
// METADATA // {"ai-params":{"service":"xai"}}
|
||||
const enq = require('enquirer');
|
||||
const wrap = require('word-wrap');
|
||||
const dedent = require('dedent');
|
||||
@ -21,6 +22,33 @@ const FILE_EXCLUDES = [
|
||||
/^eslint\.config\.js$/,
|
||||
];
|
||||
|
||||
const models_to_try = [
|
||||
{
|
||||
service: 'openai-completion',
|
||||
model: 'gpt-4o-mini',
|
||||
},
|
||||
{
|
||||
service: 'openai-completion',
|
||||
model: 'gpt-4o',
|
||||
},
|
||||
{
|
||||
service: 'claude',
|
||||
},
|
||||
{
|
||||
service: 'xai',
|
||||
},
|
||||
// llama broke code - that's a "one strike you're out" situation
|
||||
// {
|
||||
// service: 'together-ai',
|
||||
// model: 'meta-llama/Meta-Llama-3-70B-Instruct-Turbo',
|
||||
// },
|
||||
{
|
||||
service: 'mistral',
|
||||
model: 'mistral-large-latest',
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
const axi = axios.create({
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
@ -39,10 +67,11 @@ class AI {
|
||||
//
|
||||
}
|
||||
|
||||
async complete ({ messages }) {
|
||||
async complete ({ messages, driver_params }) {
|
||||
const response = await axi.post(`${context.config.api_url}/drivers/call`, {
|
||||
interface: 'puter-chat-completion',
|
||||
method: 'complete',
|
||||
...driver_params,
|
||||
args: {
|
||||
messages,
|
||||
},
|
||||
@ -58,6 +87,19 @@ class AI {
|
||||
}
|
||||
}
|
||||
|
||||
const ai_message_to_lines = text => {
|
||||
while ( typeof text === 'object' ) {
|
||||
if ( Array.isArray(text) ) text = text[0];
|
||||
else if ( text.content ) text = text.content;
|
||||
else if ( text.text ) text = text.text;
|
||||
else {
|
||||
console.log('Invalid message object', text);
|
||||
throw new Error('Invalid message object');
|
||||
}
|
||||
}
|
||||
return text.split('\n');
|
||||
}
|
||||
|
||||
class CommentWriter {
|
||||
//
|
||||
}
|
||||
@ -159,7 +201,7 @@ const js_processor = new JavascriptFileProcessor(context, {
|
||||
type: 'function',
|
||||
scope: 'lexical',
|
||||
name,
|
||||
args: args.split(',').map(arg => arg.trim()),
|
||||
args: (args ?? '').split(',').map(arg => arg.trim()),
|
||||
};
|
||||
}
|
||||
},
|
||||
@ -305,6 +347,15 @@ const inject_comments = (lines, comments) => {
|
||||
console.log('????', comment.position, lines[comment.position], '|' + indentation + '|');
|
||||
const comment_lines = comment.lines.map(line => `${indentation}${line}`);
|
||||
lines.splice(comment.position, 0, ...comment_lines);
|
||||
|
||||
// If the first line of the comment lines starts with '/*`, ensure there is
|
||||
// a blank line above it.
|
||||
|
||||
if ( comment_lines[0].trim().startsWith('/*') ) {
|
||||
if ( comment.position > 0 && lines[comment.position - 1].trim() === '' ) {
|
||||
lines.splice(comment.position, 0, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +405,10 @@ const main = async () => {
|
||||
excludes: FILE_EXCLUDES,
|
||||
}, rootpath);
|
||||
|
||||
let i = 0;
|
||||
for await ( const value of walk_iter ) {
|
||||
i++;
|
||||
if ( i == 12 ) process.exit(0);
|
||||
if ( value.is_dir ) {
|
||||
console.log('directory:', value.path);
|
||||
continue;
|
||||
@ -365,14 +419,49 @@ const main = async () => {
|
||||
console.log('file:', value.path);
|
||||
const lines = fs.readFileSync(value.path, 'utf8').split('\n');
|
||||
|
||||
let metadata, has_metadata_line = false;
|
||||
if ( lines[0].startsWith('// METADATA // ') ) {
|
||||
const metadata = JSON.parse(lines[0].slice('// METADATA // '.length));
|
||||
has_metadata_line = true;
|
||||
metadata = JSON.parse(lines[0].slice('// METADATA // '.length));
|
||||
if ( metadata['ai-commented'] ) {
|
||||
console.log('File was already commented by AI; skipping...');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let refs = null;
|
||||
if ( metadata['ai-refs'] ) {
|
||||
const relative_file_paths = metadata['ai-refs'];
|
||||
// name of file is the key, value is the contents
|
||||
const references = {};
|
||||
|
||||
let n = 0;
|
||||
for ( const relative_file_path of relative_file_paths ) {
|
||||
n++;
|
||||
const full_path = path_.join(path_.dirname(value.path), relative_file_path);
|
||||
const ref_text = fs.readFileSync(full_path, 'utf8');
|
||||
references[relative_file_path] = ref_text;
|
||||
}
|
||||
|
||||
if ( n === 1 ) {
|
||||
refs = dedent(`
|
||||
The following documentation contains relevant information about the code.
|
||||
The code will follow after this documentation.
|
||||
`);
|
||||
|
||||
refs += '\n\n' + dedent(references[Object.keys(references)[0]]);
|
||||
} else if ( n > 2 ) {
|
||||
refs = dedent(`
|
||||
The following documentation contains relevant information about the code.
|
||||
The code will follow after a number of documentation files.
|
||||
`);
|
||||
|
||||
for ( const key of Object.keys(references) ) {
|
||||
refs += '\n\n' + dedent(references[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const action = await enq.prompt({
|
||||
type: 'select',
|
||||
name: 'action',
|
||||
@ -383,6 +472,7 @@ const main = async () => {
|
||||
'exit',
|
||||
]
|
||||
})
|
||||
// const action = 'generate';
|
||||
|
||||
if ( action.action === 'exit' ) {
|
||||
break;
|
||||
@ -490,6 +580,9 @@ const main = async () => {
|
||||
instruction: instruction,
|
||||
});
|
||||
}
|
||||
|
||||
const driver_params = metadata['ai-params'] ??
|
||||
models_to_try[Math.floor(Math.random() * models_to_try.length)];
|
||||
|
||||
for ( const comment of comments ) {
|
||||
// This doesn't work very well yet
|
||||
@ -534,24 +627,32 @@ const main = async () => {
|
||||
console.log(limited_view);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
const prompt =
|
||||
dedent(`
|
||||
Please write a comment to be added above line ${comment.position}.
|
||||
Do not write any surrounding text; just the comment itself.
|
||||
Please include comment markers. If the comment is on a class, function, or method, please use jsdoc style.
|
||||
The code is written in JavaScript.
|
||||
`).trim() +
|
||||
(refs ? '\n\n' + dedent(refs) : '') +
|
||||
(comment.instruction ? '\n\n' + dedent(comment.instruction) : '') +
|
||||
'\n\n' + limited_view
|
||||
;
|
||||
|
||||
// console.log('prompt:', prompt);
|
||||
|
||||
const message = await context.ai.complete({
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: dedent(`
|
||||
Please write a comment to be added above line ${comment.position}.
|
||||
Do not write any surrounding text; just the comment itself.
|
||||
Please include comment markers. If the comment is on a class, function, or method, please use jsdoc style.
|
||||
The code is written in JavaScript.
|
||||
`).trim() +
|
||||
(comment.instruction ? '\n\n' + dedent(comment.instruction) : '') +
|
||||
'\n\n' + limited_view
|
||||
content: prompt
|
||||
}
|
||||
]
|
||||
],
|
||||
driver_params,
|
||||
});
|
||||
console.log('message:', message);
|
||||
comment.lines = message.content.split('\n');
|
||||
comment.lines = ai_message_to_lines(message.content);
|
||||
|
||||
// Remove leading and trailing blank lines
|
||||
while ( comment.lines.length && ! comment.lines[0].trim() ) {
|
||||
@ -579,8 +680,13 @@ const main = async () => {
|
||||
console.log('--- lines ---');
|
||||
console.log(lines);
|
||||
|
||||
if ( has_metadata_line ) {
|
||||
lines.shift();
|
||||
}
|
||||
|
||||
lines.unshift('// METADATA // ' + JSON.stringify({
|
||||
'ai-commented': true,
|
||||
...metadata,
|
||||
'ai-commented': driver_params,
|
||||
}));
|
||||
|
||||
// Write the modified file
|
||||
|
Loading…
Reference in New Issue
Block a user