mindcraft/src/agent/self_prompter.js
2024-12-01 22:28:21 -06:00

114 lines
No EOL
3.5 KiB
JavaScript

export class SelfPrompter {
constructor(agent) {
this.agent = agent;
this.on = false;
this.loop_active = false;
this.interrupt = false;
this.prompt = '';
this.idle_time = 0;
this.cooldown = 2000;
}
start(prompt) {
console.log('Self-prompting started.');
if (!prompt) {
if (!this.prompt)
return 'No prompt specified. Ignoring request.';
prompt = this.prompt;
}
if (this.on) {
this.prompt = prompt;
}
this.on = true;
this.prompt = prompt;
this.startLoop();
}
setPrompt(prompt) {
this.prompt = prompt;
}
async startLoop() {
if (this.loop_active) {
console.warn('Self-prompt loop is already active. Ignoring request.');
return;
}
console.log('starting self-prompt loop')
this.loop_active = true;
let no_command_count = 0;
const MAX_NO_COMMAND = 3;
while (!this.interrupt) {
const msg = `You are self-prompting with the goal: '${this.prompt}'. Your next response MUST contain a command !withThisSyntax. Respond:`;
let used_command = await this.agent.handleMessage('system', msg, -1);
if (!used_command) {
no_command_count++;
if (no_command_count >= MAX_NO_COMMAND) {
let out = `Agent did not use command in the last ${MAX_NO_COMMAND} auto-prompts. Stopping auto-prompting.`;
this.agent.openChat(out);
console.warn(out);
this.on = false;
break;
}
}
else {
no_command_count = 0;
await new Promise(r => setTimeout(r, this.cooldown));
}
}
console.log('self prompt loop stopped')
this.loop_active = false;
this.interrupt = false;
}
update(delta) {
// automatically restarts loop
if (this.on && !this.loop_active && !this.interrupt) {
if (this.agent.isIdle())
this.idle_time += delta;
else
this.idle_time = 0;
if (this.idle_time >= this.cooldown) {
console.log('Restarting self-prompting...');
this.startLoop();
this.idle_time = 0;
}
}
else {
this.idle_time = 0;
}
}
async stopLoop() {
// you can call this without await if you don't need to wait for it to finish
if (this.interrupt)
return;
console.log('stopping self-prompt loop')
this.interrupt = true;
while (this.loop_active) {
await new Promise(r => setTimeout(r, 500));
}
this.interrupt = false;
}
async stop(stop_action=true) {
this.interrupt = true;
if (stop_action)
await this.agent.actions.stop();
await this.stopLoop();
this.on = false;
}
shouldInterrupt(is_self_prompt) { // to be called from handleMessage
return is_self_prompt && this.on && this.interrupt;
}
handleUserPromptedCmd(is_self_prompt, is_action) {
// if a user messages and the bot responds with an action, stop the self-prompt loop
if (!is_self_prompt && is_action) {
this.stopLoop();
// this stops it from responding from the handlemessage loop and the self-prompt loop at the same time
}
}
}