added command param parsing

This commit is contained in:
MaxRobinsonTheGreat 2024-01-11 15:59:52 -06:00
parent 7d35ef1bfc
commit 0decd272f3
5 changed files with 100 additions and 42 deletions

View file

@ -2,7 +2,7 @@ import { initBot } from '../utils/mcdata.js';
import { sendRequest } from '../utils/gpt.js'; import { sendRequest } from '../utils/gpt.js';
import { History } from './history.js'; import { History } from './history.js';
import { Coder } from './coder.js'; import { Coder } from './coder.js';
import { getCommand, containsCommand } from './commands.js'; import { containsCommand, executeCommand } from './commands.js';
import { Events } from './events.js'; import { Events } from './events.js';
@ -56,7 +56,7 @@ export class Agent {
const user_command_name = containsCommand(message); const user_command_name = containsCommand(message);
if (user_command_name) { if (user_command_name) {
this.bot.chat(`*${source} used ${user_command_name.substring(1)}*`); this.bot.chat(`*${source} used ${user_command_name.substring(1)}*`);
let execute_res = await getCommand(user_command_name).perform(this); let execute_res = await executeCommand(this, message);
if (execute_res) if (execute_res)
this.bot.chat(execute_res); this.bot.chat(execute_res);
else else
@ -73,10 +73,10 @@ export class Agent {
if (command_name) { // contains query or command if (command_name) { // contains query or command
console.log('Query/Command response:', res); console.log('Query/Command response:', res);
let message = res.substring(0, res.indexOf(command_name)).trim(); let pre_message = res.substring(0, res.indexOf(command_name)).trim();
this.bot.chat(`${message} *used ${command_name.substring(1)}*`); this.bot.chat(`${pre_message} *used ${command_name.substring(1)}*`);
let execute_res = await getCommand(command_name).perform(this); let execute_res = await executeCommand(this, res);
console.log('Agent executed:', command_name, 'and got:', execute_res); console.log('Agent executed:', command_name, 'and got:', execute_res);

View file

@ -12,21 +12,84 @@ export function getCommand(name) {
return commandMap[name]; return commandMap[name];
} }
const commandRegex = /!(\w+)(?:\(((?:[^)(]+|'[^']*'|"[^"]*")*)\))?/
const argRegex = /(?:"[^"]*"|'[^']*'|[^,])+/g;
export function containsCommand(message) { export function containsCommand(message) {
for (let command of commandList) { const commandMatch = message.match(commandRegex);
if (message.includes(command.name)) { if (commandMatch) {
return command.name; const commandName = "!"+commandMatch[1];
} if (commandList.some((command) => command.name === commandName))
return commandName;
} }
return null; return null;
} }
function parseCommandMessage(message) {
const commandMatch = message.match(commandRegex);
if (commandMatch) {
const commandName = "!"+commandMatch[1];
if (!commandMatch[2])
return { commandName, args: [] };
let args = commandMatch[2].match(argRegex);
if (args) {
for (let i = 0; i < args.length; i++) {
args[i] = args[i].trim();
}
for (let i = 0; i < args.length; i++) {
let arg = args[i];
if ((arg.startsWith('"') && arg.endsWith('"')) || (arg.startsWith("'") && arg.endsWith("'"))) {
args[i] = arg.substring(1, arg.length-1);
} else if (!isNaN(arg)) {
args[i] = Number(arg);
}
}
}
else
args = [];
return { commandName, args };
}
return null;
}
function numParams(command) {
if (!command.params)
return 0;
return Object.keys(command.params).length;
}
export async function executeCommand(agent, message) {
let parsed = parseCommandMessage(message);
if (parsed) {
const command = getCommand(parsed.commandName);
let numArgs = 0;
if (parsed.args) {
numArgs = parsed.args.length;
}
console.log('parsed command:', parsed);
if (numArgs !== numParams(command))
return `Command ${command.name} was given incorrect number of arguments`;
else
return await command.perform(agent, ...parsed.args);
}
else
return `Command is incorrectly formatted`;
}
export function getCommandDocs() { export function getCommandDocs() {
let docs = `\n*Command DOCS\n You can use the following commands to perform actions and get information about the world. let docs = `\n*COMMAND DOCS\n You can use the following commands to perform actions and get information about the world.
Use the commands with the syntax: !commandName \n Use the commands with the syntax: !commandName or !commandName("arg1", 1.2, ...) if the command takes arguments.\n
Don't use codeblocks. Only use one command in each response, trailing commands will be ignored. Use these commands frequently in your responses!\n`; Do not use codeblocks. Only use one command in each response, trailing commands will be ignored. Use these commands frequently in your responses!\n`;
for (let command of commandList) { for (let command of commandList) {
docs += command.name + ': ' + command.description + '\n'; docs += command.name + ': ' + command.description + '\n';
if (command.params) {
docs += 'Params:\n';
for (let param in command.params) {
docs += param + ': ' + command.params[param] + '\n';
}
}
} }
return docs + '*\n'; return docs + '*\n';
} }

View file

@ -2,10 +2,10 @@ import * as skills from '../skills.js';
import * as world from '../world.js'; import * as world from '../world.js';
function wrapExecution(func) { function wrapExecution(func) {
return async function (agent) { return async function (agent, ...args) {
agent.bot.output = ''; agent.bot.output = '';
agent.coder.executing = true; agent.coder.executing = true;
let res = await func(agent); let res = await func(agent, ...args);
if (res) if (res)
agent.bot.output += '\n' + res; agent.bot.output += '\n' + res;
agent.coder.executing = false; agent.coder.executing = false;
@ -16,8 +16,8 @@ function wrapExecution(func) {
// const actionsList = [ // const actionsList = [
export const actionsList = [ export const actionsList = [
{ {
name: '!execute_action', name: '!newAction',
description: 'Write and execute code to perform custom behaviors not available as a command.', description: 'Perform new and unknown custom behaviors that are not available as a command by writing code.',
perform: async function (agent) { perform: async function (agent) {
let res = await agent.coder.generateCode(agent.history); let res = await agent.coder.generateCode(agent.history);
if (res) if (res)
@ -32,24 +32,19 @@ export const actionsList = [
return 'Agent stopped.'; return 'Agent stopped.';
} }
}, },
{
name: '!goToPlayer',
description: 'Go to the nearest player. Ex: !goToPlayer("steve")',
params: {'player_name': '(string) The name of the player to go to.'},
perform: wrapExecution(async (agent, player_name) => {
return await skills.goToPlayer(agent.bot, player_name);
})
},
// { // {
// name: '!gotoplayer', // name: '!followPlayer',
// description: 'Go to the nearest player.',
// perform: wrapExecution(async (agent) => {
// let player_name = world.getNearbyPlayerNames(agent.bot);
// if (player_name.length == 0)
// return 'No players nearby.';
// await skills.goToPlayer(agent.bot, player_name[0]);
// })
// },
// {
// name: '!followplayer',
// description: 'Follow the nearest player.', // description: 'Follow the nearest player.',
// perform: wrapExecution(async (agent) => { // perform: wrapExecution(async (agent, player_name) => {
// let player_name = world.getNearbyPlayerNames(agent.bot); // await skills.followPlayer(agent.bot, player_name);
// if (player_name.length == 0)
// return 'No players nearby.';
// await skills.followPlayer(agent.bot, player_name[0]);
// }) // })
// }, // },
// { // {

View file

@ -96,7 +96,7 @@ export const queryList = [
} }
}, },
{ {
name: "!action", name: "!currentAction",
description: "Get the currently executing code.", description: "Get the currently executing code.",
perform: function (agent) { perform: function (agent) {
return pad("Current code:\n`" + agent.coder.current_code +"`"); return pad("Current code:\n`" + agent.coder.current_code +"`");

View file

@ -15,56 +15,56 @@
{"role": "user", "content": "greg: Collect 10 wood"}, {"role": "user", "content": "greg: Collect 10 wood"},
{"role": "assistant", "content": "Let me see what's nearby... !blocks"}, {"role": "assistant", "content": "Let me see what's nearby... !blocks"},
{"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"}, {"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"},
{"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !execute_action"} {"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !newAction"}
], ],
[ [
{"role": "user", "content": "bobby: Craft a plank"}, {"role": "user", "content": "bobby: Craft a plank"},
{"role": "assistant", "content": "Okay! !craftable"}, {"role": "assistant", "content": "Okay! !craftable"},
{"role": "system", "content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"}, {"role": "system", "content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"},
{"role": "assistant", "content": "!execute_action"} {"role": "assistant", "content": "!newAction"}
], ],
[ [
{"role": "user", "content": "zZZn98: come here"}, {"role": "user", "content": "zZZn98: come here"},
{"role": "assistant", "content": "!execute_action"}, {"role": "assistant", "content": "!goToPlayer('sumixam0')"},
{"role": "system", "content": "Code execution finished successfully."}, {"role": "system", "content": "Code execution finished successfully."},
{"role": "assistant", "content": "Here!"} {"role": "assistant", "content": "Here!"}
], ],
[ [
{"role": "user", "content": "hanky: collect some sand and give it to me please"}, {"role": "user", "content": "hanky: collect some sand and give it to me please"},
{"role": "assistant", "content": "Collecting sand... !execute_action"}, {"role": "assistant", "content": "Collecting sand... !newAction"},
{"role": "system", "content": "Code Output:\nYou have reached player hanky.\nCode execution finished successfully."}, {"role": "system", "content": "Code Output:\nYou have reached player hanky.\nCode execution finished successfully."},
{"role": "assistant", "content": "Here!"} {"role": "assistant", "content": "Here!"}
], ],
[ [
{"role": "user", "content": "joe: Follow me!"}, {"role": "user", "content": "joe: Follow me!"},
{"role": "assistant", "content": "Sure! !execute_action"} {"role": "assistant", "content": "Sure! !newAction"}
], ],
[ [
{"role": "user", "content": "hanky: kill that zombie!"}, {"role": "user", "content": "hanky: kill that zombie!"},
{"role": "assistant", "content": "I'm attacking! !execute_action"}, {"role": "assistant", "content": "I'm attacking! !newAction"},
{"role": "system", "content": "Code Output:\nNo zombie nearby"}, {"role": "system", "content": "Code Output:\nNo zombie nearby"},
{"role": "assistant", "content": "I could not find a zombie nearby."} {"role": "assistant", "content": "I could not find a zombie nearby."}
], ],
[ [
{"role": "user", "content": "billybob: stop"}, {"role": "user", "content": "billybob: stop"},
{"role": "assistant", "content": "!execute_action"} {"role": "assistant", "content": "!newAction"}
], ],
[ [
{"role": "user", "content": "maya: go to the nearest oak log"}, {"role": "user", "content": "maya: go to the nearest oak log"},
{"role": "assistant", "content": "!execute_action`"}, {"role": "assistant", "content": "!newAction`"},
{"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."}, {"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."},
{"role": "assistant", "content": "Apologies, I made an error. Would you like me to try again?"} {"role": "assistant", "content": "Apologies, I made an error. Would you like me to try again?"}
], ],
[ [
{"role": "user", "content": "trixy88: craft some sticks"}, {"role": "user", "content": "trixy88: craft some sticks"},
{"role": "assistant", "content": "!execute_action"} {"role": "assistant", "content": "!newAction"}
] ]
] ]