From d46ffd508629a7c3f61451efb31ca3100c7e0270 Mon Sep 17 00:00:00 2001 From: Raven Scott Date: Tue, 10 Dec 2024 04:53:24 -0500 Subject: [PATCH] fix --- agent-chat.mjs | 84 ++++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/agent-chat.mjs b/agent-chat.mjs index 584cb28..2485b4f 100644 --- a/agent-chat.mjs +++ b/agent-chat.mjs @@ -14,7 +14,7 @@ const groqClient = new Groq({ apiKey: GROQ_API_KEY, }); -// A small helper for nice verbose logging: +// Logging helpers function logHeader(message) { console.log('\n' + '═'.repeat(80)); console.log('═ ' + message); @@ -53,7 +53,7 @@ function indentMultiline(text) { 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') { const response = await unirest .post(`${DISCORD_LINUX_API_URL}/exec`) @@ -67,22 +67,22 @@ async function execCommandInContainer(cmd, pwd = '/home') { return response.body; } -// This function queries the AI for instructions to achieve a goal. +// Ask AI for instructions 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}. -Rules: -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 systemPrompt = `You are a highly skilled Linux system administration assistant with direct command-line access to a Debian/Ubuntu-based Linux container. +Your mission is to achieve the following goal: "${goal}" - 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 = { messages: [ @@ -97,19 +97,10 @@ Rules: return aiResponse; } -// This function is used for chatting with the AI like a chatbot. It can answer questions, -// give advice, or provide commands about the container or any tasks you want to do next. +// Chat with the AI in interactive mode 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. -You can help answer questions about the container state, suggest commands, or assist with Linux-related tasks. -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 systemPrompt = `You are a helpful Linux system administration assistant with direct command-line access to a Debian/Ubuntu-based Linux container. +You can answer questions, suggest commands, or help with Linux tasks related to the current context. Stay on topic.`; const userPrompt = `Context:\n${context}\n\nUser says: ${userMessage}`; @@ -131,16 +122,16 @@ function parseCommandsFromAIResponse(aiResponse) { 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) { + context += `\n\n[NEW AUTOMATION ATTEMPT FOR GOAL: "${goal}"]\n`; logHeader(`ATTEMPTING TO AUTOMATE GOAL: ${goal}`); let iteration = 0; let success = false; - + while (iteration < MAX_ITERATIONS && !success) { iteration++; logHeader(`ITERATION ${iteration} OF ${MAX_ITERATIONS}`); - logSubHeader('Asking AI for instructions'); const instructions = await askAIForInstructions(context, goal); 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`; - // If we find a non-empty stderr, we consider it a failure signal if (stderr && stderr.trim().length > 0) { logInfo(`Command failed with error. Will request refined instructions next iteration.`); allCommandsSucceeded = false; @@ -170,11 +160,9 @@ async function automateGoal(context, goal) { context += `\n\n${attemptLog}`; + // If no commands failed, assume success for now. if (allCommandsSucceeded) { - logInfo("All commands executed successfully."); 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}; } -// After achieving or attempting the goal, we start an interactive chat loop. -// Added the ability to run "automate \"Your new goal\"" from the chat mode. +// Start interactive chat loop async function startChatLoop(context) { const rl = readline.createInterface({ input: process.stdin, @@ -197,10 +184,11 @@ async function startChatLoop(context) { }); 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("If the AI suggests commands, you can run them by typing 'run '."); - console.log("To re-enter automated mode with a new goal, type: automate \"Your new goal\"\n"); + console.log("If the AI suggests commands, run them with 'run '."); + console.log('To automate a new goal, type: automate "Your new goal"'); + console.log(); let lastAIResponse = ""; @@ -211,7 +199,7 @@ async function startChatLoop(context) { return; } - // If the user wants to run a command from the last AI response: + // Run a command from AI suggestion: if (input.startsWith('run ')) { const lineNum = parseInt(input.replace('run ', '').trim(), 10); const commands = parseCommandsFromAIResponse(lastAIResponse); @@ -229,15 +217,13 @@ async function startChatLoop(context) { return promptUser(); } - // If the user wants to automate a new goal: + // Automate a new goal: if (input.trim().toLowerCase().startsWith('automate ')) { const goalMatch = input.match(/^automate\s+["'](.+)["']$/i); if (goalMatch && goalMatch[1]) { const newGoal = goalMatch[1]; - // Run automated attempts on the new goal const result = await automateGoal(context, newGoal); context = result.context; - // After finishing automated attempts, return to chat mode return promptUser(); } else { 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); console.log("AI:", lastAIResponse); promptUser(); @@ -256,7 +242,6 @@ async function startChatLoop(context) { } async function main() { - // Retrieve the initial goal from command-line arguments const args = process.argv.slice(2); const initialGoal = args.join(' ').trim(); @@ -265,15 +250,12 @@ async function main() { process.exit(1); } - let context = "Initial attempt. No commands have been run yet.\n" + - "We are working with a Debian/Ubuntu container.\n" + - "Goal: " + initialGoal; + let context = "Initial attempt. We have a Debian/Ubuntu container.\n"; + context += "Initial Goal: " + initialGoal; - // Attempt to achieve the initial goal: const result = await automateGoal(context, initialGoal); context = result.context; - // After finishing attempts, start chat mode: await startChatLoop(context); }