tasks are now a class. fix various bugs

This commit is contained in:
ouoertheo
2023-06-05 23:52:45 -05:00
parent 8ac368e2ef
commit 9891d0c936

View File

@ -61,28 +61,27 @@ async function generateQuietPrompt(quiet_prompt) {
function addTask(description, index = null) { function addTask(description, index = null) {
index = index != null ? index: index = globalTasks.length index = index != null ? index: index = globalTasks.length
globalTasks.splice(index, 0, new ObjectiveTask( globalTasks.splice(index, 0, new ObjectiveTask(
index, {description: description}
description,
)) ))
saveState() saveState()
} }
// Get a task either by index or task description. Return current task if none specified
function getTask(index = null, taskDescription = null) { // Return the task and index or throw an error
let task = {} function getTaskById(taskId){
if (index == null && taskDescription == null) { if (taskId == null) {
task = currentTask throw `Null task id`
} else if (index != null) { }
task = globalTasks[index] const index = globalTasks.findIndex((task) => task.id === taskId);
} else if (taskDescription != null) { if (index !== -1) {
task = globalTasks.find(task => { return { task: globalTasks[index], index: index };
return task.description == description ? true: false } else {
}) throw `Cannot find task with ${taskId}`
} }
return task
} }
function deleteTask(index){ function deleteTask(taskId){
const { task, index } = getTaskById(taskId)
globalTasks.splice(index, 1) globalTasks.splice(index, 1)
setCurrentTask() setCurrentTask()
updateUiTaskList() updateUiTaskList()
@ -102,18 +101,18 @@ async function generateTasks() {
// Create tasks from generated task list // Create tasks from generated task list
for (const task of taskResponse.split('\n').map(x => x.trim())) { for (const task of taskResponse.split('\n').map(x => x.trim())) {
if (task.match(numberedListPattern) != null) { if (task.match(numberedListPattern) != null) {
addTask(task.replace(numberedListPattern).trim()) addTask(task.replace(numberedListPattern,"").trim())
} }
} }
updateUiTaskList() updateUiTaskList()
console.info(`Response for Objective: '${globalObjective}' was \n'${taskResponse}', \nwhich created tasks \n${JSON.stringify(globalTasks, null, 2)} `) console.info(`Response for Objective: '${globalObjective}' was \n'${taskResponse}', \nwhich created tasks \n${JSON.stringify(globalTasks.map(v => {return v.toSaveState()}), null, 2)} `)
toastr.success(`Generated ${globalTasks.length} tasks`, 'Done!'); toastr.success(`Generated ${globalTasks.length} tasks`, 'Done!');
} }
// Call Quiet Generate to check if a task is completed // Call Quiet Generate to check if a task is completed
async function checkTaskCompleted() { async function checkTaskCompleted() {
// Make sure there are tasks // Make sure there are tasks
if (currentTask == null) { if (jQuery.isEmptyObject(currentTask)) {
return return
} }
checkCounter = $('#objective-check-frequency').val() checkCounter = $('#objective-check-frequency').val()
@ -123,7 +122,7 @@ async function checkTaskCompleted() {
// Check response if task complete // Check response if task complete
if (taskResponse.includes("true")) { if (taskResponse.includes("true")) {
console.info(`Character determined task '${JSON.stringify(currentTask)} is completed.`) console.info(`Character determined task '${JSON.stringify(currentTask.toSaveState())} is completed.`)
currentTask.completeTask() currentTask.completeTask()
} else if (!(taskResponse.includes("false"))) { } else if (!(taskResponse.includes("false"))) {
console.warn(`checkTaskCompleted response did not contain true or false. taskResponse: ${taskResponse}`) console.warn(`checkTaskCompleted response did not contain true or false. taskResponse: ${taskResponse}`)
@ -134,23 +133,22 @@ async function checkTaskCompleted() {
// Set a task in extensionPrompt context. Defaults to first incomplete // Set a task in extensionPrompt context. Defaults to first incomplete
function setCurrentTask(index = null) { function setCurrentTask(taskId = null) {
const context = getContext(); const context = getContext();
currentTask = {}; currentTask = {};
// Set current task to either the next incomplete task, or the index if valid value is specified // Set current task to either the next incomplete task, or the index
if (index === null) { if (taskId === null) {
currentTask = globalTasks.find(task => !task.completed) || {}; currentTask = globalTasks.find(task => !task.completed) || {};
} else { } else {
if (index >= 0 && index < globalTasks.length){ const { _, index } = getTaskById(taskId)
toastr.error(`Invalide task index ${index} specified. Must be between 0 and ${globalTasks.length}`)
return
}
currentTask = globalTasks[index]; currentTask = globalTasks[index];
} }
// Get the task description and add to extension prompt // Get the task description and add to extension prompt
const { description } = currentTask.description; const description = currentTask.description || null;
// Now update the extension prompt
if (description) { if (description) {
const extensionPromptText = extensionPrompt.replace(/{{task}}/gi, description); const extensionPromptText = extensionPrompt.replace(/{{task}}/gi, description);
@ -164,9 +162,19 @@ function setCurrentTask(index = null) {
saveState(); saveState();
} }
let taskIdCounter = 0
function getNextTaskId(){
// Make sure id does not exist
while (globalTasks.find(task => task.id == taskIdCounter) != undefined) {
taskIdCounter += 1
}
const nextId = taskIdCounter
console.log(`TaskID assigned: ${nextId}`)
taskIdCounter += 1
return nextId
}
class ObjectiveTask { class ObjectiveTask {
// Task State id
index
description description
completed completed
parent parent
@ -179,10 +187,18 @@ class ObjectiveTask {
deleteTaskButton deleteTaskButton
addTaskButton addTaskButton
constructor (index, description, parent=null) { constructor ({id=undefined, description, completed=false, parent=null}) {
this.index = index
this.description = description this.description = description
this.parent = parent this.parent = parent
this.children = []
this.completed = completed
// Generate a new ID if none specified
if (id==undefined){
this.id = getNextTaskId()
} else {
this.id=id
}
} }
@ -197,72 +213,64 @@ class ObjectiveTask {
// Add a single task to the UI and attach event listeners for user edits // Add a single task to the UI and attach event listeners for user edits
addUiElement() { addUiElement() {
const template = ` const template = `
<div id="objective-task-label-${this.index}" class="flex1 checkbox_label"> <div id="objective-task-label-${this.id}" class="flex1 checkbox_label">
<span>${this.index}</span> <input id="objective-task-complete-${this.id}" type="checkbox">
<input id="objective-task-complete-${this.index}" type="checkbox"> <span class="text_pole" style="display: block" id="objective-task-description-${this.id}" contenteditable>${this.description}</span>
<span class="text_pole" style="display: block" id="objective-task-description-${this.index}" contenteditable>${this.description}</span> <div id="objective-task-delete-${this.id}" class="objective-task-button fa-solid fa-xmark fa-2x" title="Delete Task"></div>
<div id="objective-task-delete-${this.index}" class="objective-task-button fa-solid fa-xmark fa-2x" title="Delete Task"></div> <div id="objective-task-add-${this.id}" class="objective-task-button fa-solid fa-plus fa-2x" title="Add Task"></div>
<div id="objective-task-add-${this.index}" class="objective-task-button fa-solid fa-plus fa-2x" title="Add Task"></div>
</div><br> </div><br>
`; `;
// Add the filled out template // Add the filled out template
$('#objective-tasks').append(template); $('#objective-tasks').append(template);
this.completedCheckbox = $(`#objective-task-complete-${this.index}`); this.completedCheckbox = $(`#objective-task-complete-${this.id}`);
this.descriptionSpan = $(`#objective-task-description-${this.index}`); this.descriptionSpan = $(`#objective-task-description-${this.id}`);
this.addButton = $(`#objective-task-add-${this.index}`); this.addButton = $(`#objective-task-add-${this.id}`);
this.deleteButton = $(`#objective-task-delete-${this.index}`); this.deleteButton = $(`#objective-task-delete-${this.id}`);
// Add event listeners and set properties // Add event listeners and set properties
$(`#objective-task-complete-${this.index}`).prop('checked', this.completed); $(`#objective-task-complete-${this.id}`).prop('checked', this.completed);
$(`#objective-task-complete-${this.index}`).on('click', () => (this.onCompleteClick())); $(`#objective-task-complete-${this.id}`).on('click', () => (this.onCompleteClick()));
$(`#objective-task-description-${this.index}`).on('keyup', () => (this.onDescriptionUpdate())); $(`#objective-task-description-${this.id}`).on('keyup', () => (this.onDescriptionUpdate()));
$(`#objective-task-delete-${this.index}`).on('click', () => (this.onDeleteClick())); $(`#objective-task-description-${this.id}`).on('focusout', () => (this.onDescriptionFocusout()));
$(`#objective-task-add-${this.index}`).on('click', () => (this.onAddClick())); $(`#objective-task-delete-${this.id}`).on('click', () => (this.onDeleteClick()));
$(`#objective-task-add-${this.id}`).on('click', () => (this.onAddClick()));
} }
onCompleteClick(){ onCompleteClick(){
this.completed = this.completedCheckbox.val() this.completed = this.completedCheckbox.prop('checked')
setCurrentTask(); setCurrentTask();
} }
onDescriptionUpdate(){ onDescriptionUpdate(){
this.description = this.descriptionSpan.val(); this.description = this.descriptionSpan.text();
}
onDescriptionFocusout(){
setCurrentTask();
} }
onDeleteClick(){ onDeleteClick(){
deleteTask(this.index); deleteTask(this.id);
} }
onAddClick(){ onAddClick(){
addTask("", this.index + 1); const {_, index} = getTaskById(this.id)
addTask("", index + 1);
setCurrentTask(); setCurrentTask();
updateUiTaskList(); updateUiTaskList();
} }
toSaveState() { toSaveState() {
return { return {
"index":this.index, "id":this.id,
"description":this.description, "description":this.description,
"completed":this.completed, "completed":this.completed,
"parent": this.parent,
} }
} }
} }
class TaskManager {
tasks = {}
constructor (){
}
addTask (description, index, parent) {
if (this.tasks){}
}
deleteTask (index) {}
}
//###############################// //###############################//
//# UI AND Settings #// //# UI AND Settings #//
//###############################// //###############################//
@ -306,11 +314,11 @@ function saveState() {
// Dump core state // Dump core state
function debugObjectiveExtension() { function debugObjectiveExtension() {
console.log(JSON.stringify({ console.log(JSON.stringify({
"currentTask": currentTask, "currentTask": currentTask.toSaveState(),
"currentChatId": currentChatId, "currentChatId": currentChatId,
"checkCounter": checkCounter, "checkCounter": checkCounter,
"globalObjective": globalObjective, "globalObjective": globalObjective,
"globalTasks": globalTasks, "globalTasks": globalTasks.map(v => {return v.toSaveState()}),
"extension_settings": chat_metadata['objective'], "extension_settings": chat_metadata['objective'],
}, null, 2)) }, null, 2))
} }
@ -338,14 +346,6 @@ function updateUiTaskList() {
} }
} }
function addManualTaskCheckUi() {
$('#extensionsMenu').prepend(`
<div id="objective-task-manual-check-menu-item" class="list-group-item flex-container flexGap5">
<div id="objective-task-manual-check" class="extensionsMenuExtensionButton fa-regular fa-square-check"/></div>
Manual Task Check
</div>`)
$('#objective-task-manual-check-menu-item').attr('title', 'Trigger AI check of completed tasks').on('click', checkTaskCompleted)
}
// Trigger creation of new tasks with given objective. // Trigger creation of new tasks with given objective.
async function onGenerateObjectiveClick() { async function onGenerateObjectiveClick() {
@ -393,7 +393,14 @@ function loadSettings() {
// Update globals // Update globals
globalObjective = chat_metadata['objective'].objective globalObjective = chat_metadata['objective'].objective
globalTasks = chat_metadata['objective'].tasks.map((task, index) => {return new ObjectiveTask(index, task.description)}) globalTasks = chat_metadata['objective'].tasks.map(task => {
return new ObjectiveTask({
id: task.id,
description: task.description,
completed: task.completed,
parent: task.parent,
})
});
checkCounter = chat_metadata['objective'].checkFrequency checkCounter = chat_metadata['objective'].checkFrequency
// Update UI elements // Update UI elements
@ -407,6 +414,15 @@ function loadSettings() {
setCurrentTask() setCurrentTask()
} }
function addManualTaskCheckUi() {
$('#extensionsMenu').prepend(`
<div id="objective-task-manual-check-menu-item" class="list-group-item flex-container flexGap5">
<div id="objective-task-manual-check" class="extensionsMenuExtensionButton fa-regular fa-square-check"/></div>
Manual Task Check
</div>`)
$('#objective-task-manual-check-menu-item').attr('title', 'Trigger AI check of completed tasks').on('click', checkTaskCompleted)
}
jQuery(() => { jQuery(() => {
const settingsHtml = ` const settingsHtml = `
<div class="objective-settings"> <div class="objective-settings">
@ -430,6 +446,7 @@ jQuery(() => {
<label for="objective-chat-depth">In-chat @ Depth</label> <label for="objective-chat-depth">In-chat @ Depth</label>
<input id="objective-chat-depth" class="text_pole widthUnset" type="number" min="0" max="99" /> <input id="objective-chat-depth" class="text_pole widthUnset" type="number" min="0" max="99" />
</div> </div>
<br>
<div class="objective_block objective_block_control flex1"> <div class="objective_block objective_block_control flex1">
<label for="objective-check-frequency">Task Check Frequency</label> <label for="objective-check-frequency">Task Check Frequency</label>
<input id="objective-check-frequency" class="text_pole widthUnset" type="number" min="0" max="99" /> <input id="objective-check-frequency" class="text_pole widthUnset" type="number" min="0" max="99" />