fix
This commit is contained in:
parent
ddb88268da
commit
d46ffd5086
@ -14,7 +14,7 @@ const groqClient = new Groq({
|
|||||||
apiKey: GROQ_API_KEY,
|
apiKey: GROQ_API_KEY,
|
||||||
});
|
});
|
||||||
|
|
||||||
// A small helper for nice verbose logging:
|
// Logging helpers
|
||||||
function logHeader(message) {
|
function logHeader(message) {
|
||||||
console.log('\n' + '═'.repeat(80));
|
console.log('\n' + '═'.repeat(80));
|
||||||
console.log('═ ' + message);
|
console.log('═ ' + message);
|
||||||
@ -53,7 +53,7 @@ function indentMultiline(text) {
|
|||||||
return text.split('\n').map(line => ' ' + line).join('\n');
|
return text.split('\n').map(line => ' ' + line).join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to execute a command in the container:
|
// Execute a command in the container
|
||||||
async function execCommandInContainer(cmd, pwd = '/home') {
|
async function execCommandInContainer(cmd, pwd = '/home') {
|
||||||
const response = await unirest
|
const response = await unirest
|
||||||
.post(`${DISCORD_LINUX_API_URL}/exec`)
|
.post(`${DISCORD_LINUX_API_URL}/exec`)
|
||||||
@ -67,22 +67,22 @@ async function execCommandInContainer(cmd, pwd = '/home') {
|
|||||||
return response.body;
|
return response.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function queries the AI for instructions to achieve a goal.
|
// Ask AI for instructions
|
||||||
async function askAIForInstructions(context, goal) {
|
async function askAIForInstructions(context, goal) {
|
||||||
const systemPrompt = `You are a world-class Linux system administration assistant, given the ability to access and run commands on a remote Debian/Ubuntu-based Linux container. Your mission is to help achieve the following goal: ${goal}.
|
const systemPrompt = `You are a highly skilled Linux system administration assistant with direct command-line access to a Debian/Ubuntu-based Linux container.
|
||||||
Rules:
|
Your mission is to achieve the following goal: "${goal}"
|
||||||
1. Return only shell commands needed, line-by-line, no explanation.
|
|
||||||
2. If previous attempts failed, refine your approach and fix the issues based on the provided errors and output.
|
|
||||||
3. If you need to run multiple commands, separate them by new lines.
|
|
||||||
4. Consider common steps: updating package lists, installing packages, verifying installation.
|
|
||||||
5. The container might be minimal, so consider installing or fixing repositories if needed.
|
|
||||||
6. Always ensure commands are non-interactive.
|
|
||||||
7. Do not use markdown formatting at all ever.
|
|
||||||
8. All commands are non-interactive
|
|
||||||
9. If installing packages, always use -y to allow for non-interactive commands
|
|
||||||
`;
|
|
||||||
|
|
||||||
const userPrompt = `CONTEXT:\n${context}\n\nPlease provide the exact shell commands to achieve the goal above.`;
|
Follow these rules:
|
||||||
|
1. Return only shell commands needed to achieve this exact goal, line-by-line, no explanations.
|
||||||
|
2. The commands must be directly related to accomplishing the goal. Do not run unrelated commands.
|
||||||
|
3. If previous attempts failed, adjust the commands based on the context and errors.
|
||||||
|
4. Consider common steps if needed (e.g., update packages before installing).
|
||||||
|
5. Always ensure non-interactive operation (use -y for apt, etc.).
|
||||||
|
6. No markdown formatting. Just commands, one per line. No extra text.
|
||||||
|
7. Only include necessary commands. Avoid irrelevant repository additions or unrelated installations.
|
||||||
|
8. Do not forget the exact goal. All commands must focus on achieving the requested goal.`;
|
||||||
|
|
||||||
|
const userPrompt = `CONTEXT:\n${context}\n\nPlease provide the exact shell commands to achieve the goal: "${goal}"`;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
messages: [
|
messages: [
|
||||||
@ -97,19 +97,10 @@ Rules:
|
|||||||
return aiResponse;
|
return aiResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is used for chatting with the AI like a chatbot. It can answer questions,
|
// Chat with the AI in interactive mode
|
||||||
// give advice, or provide commands about the container or any tasks you want to do next.
|
|
||||||
async function chatWithAI(context, userMessage) {
|
async function chatWithAI(context, userMessage) {
|
||||||
const systemPrompt = `You are a helpful Linux system administration assistant with the ability to access and run commands on a remote Debian/Ubuntu-based Linux container.
|
const systemPrompt = `You are a helpful Linux system administration assistant with direct command-line access to a Debian/Ubuntu-based Linux container.
|
||||||
You can help answer questions about the container state, suggest commands, or assist with Linux-related tasks.
|
You can answer questions, suggest commands, or help with Linux tasks related to the current context. Stay on topic.`;
|
||||||
Rules:
|
|
||||||
1. You can provide explanations, instructions, and command suggestions.
|
|
||||||
2. If giving commands, list them clearly line-by-line.
|
|
||||||
3. For explanations or answers, you can use normal text.
|
|
||||||
4. Do not use markdown formatting.
|
|
||||||
5. Keep answers concise and clear.
|
|
||||||
6. The user may then choose to run commands you suggest.
|
|
||||||
`;
|
|
||||||
|
|
||||||
const userPrompt = `Context:\n${context}\n\nUser says: ${userMessage}`;
|
const userPrompt = `Context:\n${context}\n\nUser says: ${userMessage}`;
|
||||||
|
|
||||||
@ -131,16 +122,16 @@ function parseCommandsFromAIResponse(aiResponse) {
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function attempts to automatically achieve a given goal using the AI instructions up to MAX_ITERATIONS
|
// Automate the given goal using up to MAX_ITERATIONS
|
||||||
async function automateGoal(context, goal) {
|
async function automateGoal(context, goal) {
|
||||||
|
context += `\n\n[NEW AUTOMATION ATTEMPT FOR GOAL: "${goal}"]\n`;
|
||||||
logHeader(`ATTEMPTING TO AUTOMATE GOAL: ${goal}`);
|
logHeader(`ATTEMPTING TO AUTOMATE GOAL: ${goal}`);
|
||||||
let iteration = 0;
|
let iteration = 0;
|
||||||
let success = false;
|
let success = false;
|
||||||
|
|
||||||
while (iteration < MAX_ITERATIONS && !success) {
|
while (iteration < MAX_ITERATIONS && !success) {
|
||||||
iteration++;
|
iteration++;
|
||||||
logHeader(`ITERATION ${iteration} OF ${MAX_ITERATIONS}`);
|
logHeader(`ITERATION ${iteration} OF ${MAX_ITERATIONS}`);
|
||||||
|
|
||||||
logSubHeader('Asking AI for instructions');
|
logSubHeader('Asking AI for instructions');
|
||||||
const instructions = await askAIForInstructions(context, goal);
|
const instructions = await askAIForInstructions(context, goal);
|
||||||
console.log("AI PROVIDED COMMANDS:\n" + indentMultiline(instructions));
|
console.log("AI PROVIDED COMMANDS:\n" + indentMultiline(instructions));
|
||||||
@ -158,7 +149,6 @@ async function automateGoal(context, goal) {
|
|||||||
|
|
||||||
attemptLog += `\n> ${cmd}\nstdout:\n${stdout}\nstderr:\n${stderr}\n`;
|
attemptLog += `\n> ${cmd}\nstdout:\n${stdout}\nstderr:\n${stderr}\n`;
|
||||||
|
|
||||||
// If we find a non-empty stderr, we consider it a failure signal
|
|
||||||
if (stderr && stderr.trim().length > 0) {
|
if (stderr && stderr.trim().length > 0) {
|
||||||
logInfo(`Command failed with error. Will request refined instructions next iteration.`);
|
logInfo(`Command failed with error. Will request refined instructions next iteration.`);
|
||||||
allCommandsSucceeded = false;
|
allCommandsSucceeded = false;
|
||||||
@ -170,11 +160,9 @@ async function automateGoal(context, goal) {
|
|||||||
|
|
||||||
context += `\n\n${attemptLog}`;
|
context += `\n\n${attemptLog}`;
|
||||||
|
|
||||||
|
// If no commands failed, assume success for now.
|
||||||
if (allCommandsSucceeded) {
|
if (allCommandsSucceeded) {
|
||||||
logInfo("All commands executed successfully.");
|
|
||||||
success = true;
|
success = true;
|
||||||
} else {
|
|
||||||
logInfo("At least one command failed. The AI will refine approach in next iteration.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,8 +176,7 @@ async function automateGoal(context, goal) {
|
|||||||
return {context, success};
|
return {context, success};
|
||||||
}
|
}
|
||||||
|
|
||||||
// After achieving or attempting the goal, we start an interactive chat loop.
|
// Start interactive chat loop
|
||||||
// Added the ability to run "automate \"Your new goal\"" from the chat mode.
|
|
||||||
async function startChatLoop(context) {
|
async function startChatLoop(context) {
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
@ -197,10 +184,11 @@ async function startChatLoop(context) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
logHeader("Entering Interactive Chat Mode");
|
logHeader("Entering Interactive Chat Mode");
|
||||||
console.log("You can now ask the AI about the container or request additional tasks.");
|
console.log("You can ask the AI about the container or request tasks.");
|
||||||
console.log("Type 'exit' to quit.");
|
console.log("Type 'exit' to quit.");
|
||||||
console.log("If the AI suggests commands, you can run them by typing 'run <line_number>'.");
|
console.log("If the AI suggests commands, run them with 'run <line_number>'.");
|
||||||
console.log("To re-enter automated mode with a new goal, type: automate \"Your new goal\"\n");
|
console.log('To automate a new goal, type: automate "Your new goal"');
|
||||||
|
console.log();
|
||||||
|
|
||||||
let lastAIResponse = "";
|
let lastAIResponse = "";
|
||||||
|
|
||||||
@ -211,7 +199,7 @@ async function startChatLoop(context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants to run a command from the last AI response:
|
// Run a command from AI suggestion:
|
||||||
if (input.startsWith('run ')) {
|
if (input.startsWith('run ')) {
|
||||||
const lineNum = parseInt(input.replace('run ', '').trim(), 10);
|
const lineNum = parseInt(input.replace('run ', '').trim(), 10);
|
||||||
const commands = parseCommandsFromAIResponse(lastAIResponse);
|
const commands = parseCommandsFromAIResponse(lastAIResponse);
|
||||||
@ -229,15 +217,13 @@ async function startChatLoop(context) {
|
|||||||
return promptUser();
|
return promptUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user wants to automate a new goal:
|
// Automate a new goal:
|
||||||
if (input.trim().toLowerCase().startsWith('automate ')) {
|
if (input.trim().toLowerCase().startsWith('automate ')) {
|
||||||
const goalMatch = input.match(/^automate\s+["'](.+)["']$/i);
|
const goalMatch = input.match(/^automate\s+["'](.+)["']$/i);
|
||||||
if (goalMatch && goalMatch[1]) {
|
if (goalMatch && goalMatch[1]) {
|
||||||
const newGoal = goalMatch[1];
|
const newGoal = goalMatch[1];
|
||||||
// Run automated attempts on the new goal
|
|
||||||
const result = await automateGoal(context, newGoal);
|
const result = await automateGoal(context, newGoal);
|
||||||
context = result.context;
|
context = result.context;
|
||||||
// After finishing automated attempts, return to chat mode
|
|
||||||
return promptUser();
|
return promptUser();
|
||||||
} else {
|
} else {
|
||||||
console.log("To automate a new goal, use: automate \"Your new goal\"");
|
console.log("To automate a new goal, use: automate \"Your new goal\"");
|
||||||
@ -245,7 +231,7 @@ async function startChatLoop(context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, treat input as a question to the AI
|
// Otherwise, treat as a normal chat message
|
||||||
lastAIResponse = await chatWithAI(context, input);
|
lastAIResponse = await chatWithAI(context, input);
|
||||||
console.log("AI:", lastAIResponse);
|
console.log("AI:", lastAIResponse);
|
||||||
promptUser();
|
promptUser();
|
||||||
@ -256,7 +242,6 @@ async function startChatLoop(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// Retrieve the initial goal from command-line arguments
|
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
const initialGoal = args.join(' ').trim();
|
const initialGoal = args.join(' ').trim();
|
||||||
|
|
||||||
@ -265,15 +250,12 @@ async function main() {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let context = "Initial attempt. No commands have been run yet.\n" +
|
let context = "Initial attempt. We have a Debian/Ubuntu container.\n";
|
||||||
"We are working with a Debian/Ubuntu container.\n" +
|
context += "Initial Goal: " + initialGoal;
|
||||||
"Goal: " + initialGoal;
|
|
||||||
|
|
||||||
// Attempt to achieve the initial goal:
|
|
||||||
const result = await automateGoal(context, initialGoal);
|
const result = await automateGoal(context, initialGoal);
|
||||||
context = result.context;
|
context = result.context;
|
||||||
|
|
||||||
// After finishing attempts, start chat mode:
|
|
||||||
await startChatLoop(context);
|
await startChatLoop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user