Forge / src /errorHealer.js
ausername-12345
Initial commit - Forge: self-improving AI assistant with filesystem access for self-editing
4381a41
Raw
History Blame Contribute Delete
2.07 kB
const inferenceClient = require('./inferenceClient');
const toolManager = require('./toolManager');
function stripCodeFences(text) {
return text
.trim()
.replace(/^```[a-zA-Z]*\n?/, '')
.replace(/```$/, '')
.trim();
}
// Given a broken tool and the error it threw, ask the model for a corrected
// version and file it as a pending fix. Returns the new pending entry, or
// null if the model failed to produce a usable patch.
async function attemptFix(tool, error) {
const prompt = [
`The tool "${tool.name}" threw an error when it ran.`,
'',
`Description: ${tool.description}`,
'',
'Current code:',
'---',
tool.code,
'---',
'',
`Error message: ${error.message}`,
error.stack ? `Stack: ${error.stack}` : '',
error.logs && error.logs.length ? `Console output before the error: ${error.logs.join(' | ')}` : '',
'',
'Write a corrected full replacement for the tool code, using the exact same convention:',
'an async function named run(args) that returns a JSON-serializable result.',
'Reply with ONLY the corrected JavaScript code. No explanation, no markdown fences.',
]
.filter(Boolean)
.join('\n');
let message;
try {
message = await inferenceClient.chat([
{
role: 'system',
content:
'You are a careful senior JavaScript engineer patching a broken tool for a self-improving assistant. ' +
'You fix root causes, keep the same run(args) function signature, and never add explanations outside the code.',
},
{ role: 'user', content: prompt },
]);
} catch (e) {
console.error('[errorHealer] fix request failed:', e.message);
return null;
}
const code = stripCodeFences(message.content || '');
if (!code || !/async\s+function\s+run\s*\(/.test(code)) {
console.error('[errorHealer] model did not return a usable run(args) function');
return null;
}
return toolManager.proposeFix(tool.id, code, `Auto-fix attempt for error: ${error.message}`);
}
module.exports = { attemptFix };