add in objective tree

This commit is contained in:
ouoertheo
2023-07-28 23:21:55 -05:00
parent d4e05c99e3
commit ee81a8d88c

View File

@ -1,4 +1,4 @@
import { chat_metadata, callPopup, saveSettingsDebounced } from "../../../script.js"; import { chat_metadata, callPopup, saveSettingsDebounced, getCurrentChatId } from "../../../script.js";
import { getContext, extension_settings, saveMetadataDebounced } from "../../extensions.js"; import { getContext, extension_settings, saveMetadataDebounced } from "../../extensions.js";
import { import {
substituteParams, substituteParams,
@ -11,9 +11,10 @@ import { registerSlashCommand } from "../../slash-commands.js";
const MODULE_NAME = "Objective" const MODULE_NAME = "Objective"
let globalObjective = "" let taskTree = null
let globalTasks = [] let globalTasks = []
let currentChatId = "" let currentChatId = ""
let currentObjective = null
let currentTask = null let currentTask = null
let checkCounter = 0 let checkCounter = 0
@ -47,56 +48,48 @@ let objectivePrompts = defaultPrompts
//# Task Management #// //# Task Management #//
//###############################// //###############################//
// Accepts optional index. Defaults to adding to end of list.
function addTask(description, index = null) {
index = index != null ? index: index = globalTasks.length
globalTasks.splice(index, 0, new ObjectiveTask(
{description: description}
))
saveState()
}
// Return the task and index or throw an error // Return the task and index or throw an error
function getTaskById(taskId){ function getTaskById(taskId){
if (taskId == null) { if (taskId == null) {
throw `Null task id` throw `Null task id`
} }
const index = globalTasks.findIndex((task) => task.id === taskId); return getTaskByIdRecurse(taskId, taskTree)
if (index !== -1) {
return { task: globalTasks[index], index: index };
} else {
throw `Cannot find task with ${taskId}`
}
} }
function deleteTask(taskId){ function getTaskByIdRecurse(taskId, task) {
const { task, index } = getTaskById(taskId) if (task.id == taskId){
return task
globalTasks.splice(index, 1) }
setCurrentTask() for (const childTask of task.children) {
updateUiTaskList() const foundTask = getTaskByIdRecurse(taskId, childTask);
if (foundTask != null) {
return foundTask;
}
}
return null;
} }
// Call Quiet Generate to create task list using character context, then convert to tasks. Should not be called much. // Call Quiet Generate to create task list using character context, then convert to tasks. Should not be called much.
async function generateTasks() { async function generateTasks() {
const prompt = substituteParams(objectivePrompts.createTask.replace(/{{objective}}/gi, globalObjective));
const prompt = substituteParams(objectivePrompts.createTask.replace(/{{objective}}/gi, currentObjective.description));
console.log(`Generating tasks for objective with prompt`) console.log(`Generating tasks for objective with prompt`)
toastr.info('Generating tasks for objective', 'Please wait...'); toastr.info('Generating tasks for objective', 'Please wait...');
const taskResponse = await generateQuietPrompt(prompt) const taskResponse = await generateQuietPrompt(prompt)
// Clear all existing global tasks when generating // Clear all existing objective tasks when generating
globalTasks = [] currentObjective.children = []
const numberedListPattern = /^\d+\./ const numberedListPattern = /^\d+\./
// 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()) currentObjective.addTask(task.replace(numberedListPattern,"").trim())
} }
} }
updateUiTaskList() updateUiTaskList();
console.info(`Response for Objective: '${globalObjective}' was \n'${taskResponse}', \nwhich created tasks \n${JSON.stringify(globalTasks.map(v => {return v.toSaveState()}), null, 2)} `) setCurrentTask();
console.info(`Response for Objective: '${taskTree.description}' 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!');
} }
@ -113,7 +106,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.toSaveState())} is completed.`) console.info(`Character determined task '${currentTask.description} 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}`)
@ -122,29 +115,56 @@ async function checkTaskCompleted() {
} }
} }
function getNextIncompleteTaskRecurse(task){
// Skip tasks with children, as they will have subtasks to determine completeness
if (task.completed === false && task.children.length === 0){
return task
}
for (const childTask of task.children) {
if (childTask.completed === true){ // Don't recurse into completed tasks
continue
}
const foundTask = getNextIncompleteTaskRecurse(childTask);
if (foundTask != null) {
return foundTask;
}
}
return null;
}
// Set a task in extensionPrompt context. Defaults to first incomplete // Set a task in extensionPrompt context. Defaults to first incomplete
function setCurrentTask(taskId = null) { function setCurrentTask(taskId = null) {
const context = getContext(); const context = getContext();
// TODO: Should probably null this rather than set empty object
currentTask = {}; currentTask = {};
// Set current task to either the next incomplete task, or the index // Find the task, either next incomplete, or by provided taskId
if (taskId === null) { if (taskId === null) {
currentTask = globalTasks.find(task => !task.completed) || {}; currentTask = getNextIncompleteTaskRecurse(taskTree) || {};
} else { } else {
const { _, index } = getTaskById(taskId) currentTask = getTaskById(taskId);
currentTask = globalTasks[index];
} }
// Get the task description and add to extension prompt // Don't just check for a current task, check if it has data
const description = currentTask.description || null; const description = currentTask.description || null;
// Now update the extension prompt
if (description) { if (description) {
const extensionPromptText = objectivePrompts.currentTask.replace(/{{task}}/gi, description); const extensionPromptText = objectivePrompts.currentTask.replace(/{{task}}/gi, description);
$('.objective-task').css({'border-color':'','border-width':''}) // Clear highlights
currentTask.descriptionSpan.css({'border-color':'yellow','border-width':'2px'}); // Highlight current task // Remove highlights
$('.objective-task').css({'border-color':'','border-width':''})
// Highlight current task
let highlightTask = currentTask
while (highlightTask.parentId !== ""){
if (highlightTask.descriptionSpan){
highlightTask.descriptionSpan.css({'border-color':'yellow','border-width':'2px'});
}
const parent = getTaskById(highlightTask.parentId)
highlightTask = parent
}
// Update the extension prompt
context.setExtensionPrompt(MODULE_NAME, extensionPromptText, 1, $('#objective-chat-depth').val()); context.setExtensionPrompt(MODULE_NAME, extensionPromptText, 1, $('#objective-chat-depth').val());
console.info(`Current task in context.extensionPrompts.Objective is ${JSON.stringify(context.extensionPrompts.Objective)}`); console.info(`Current task in context.extensionPrompts.Objective is ${JSON.stringify(context.extensionPrompts.Objective)}`);
} else { } else {
@ -155,22 +175,26 @@ function setCurrentTask(taskId = null) {
saveState(); saveState();
} }
let taskIdCounter = 0 function getHighestTaskIdRecurse(task) {
function getNextTaskId(){ let nextId = task.id;
// Make sure id does not exist
while (globalTasks.find(task => task.id == taskIdCounter) != undefined) { for (const childTask of task.children) {
taskIdCounter += 1 const childId = getHighestTaskIdRecurse(childTask);
if (childId > nextId) {
nextId = childId;
} }
const nextId = taskIdCounter }
console.log(`TaskID assigned: ${nextId}`) return nextId;
taskIdCounter += 1
return nextId
} }
//###############################//
//# Task Class #//
//###############################//
class ObjectiveTask { class ObjectiveTask {
id id
description description
completed completed
parent parentId
children children
// UI Elements // UI Elements
@ -180,25 +204,67 @@ class ObjectiveTask {
deleteTaskButton deleteTaskButton
addTaskButton addTaskButton
constructor ({id=undefined, description, completed=false, parent=null}) { constructor ({id=undefined, description, completed=false, parentId=""}) {
this.description = description this.description = description
this.parent = parent this.parentId = parentId
this.children = [] this.children = []
this.completed = completed this.completed = completed
// Generate a new ID if none specified // Generate a new ID if none specified
if (id==undefined){ if (id==undefined){
this.id = getNextTaskId() this.id = getHighestTaskIdRecurse(taskTree) + 1
} else { } else {
this.id=id this.id=id
} }
} }
// Accepts optional index. Defaults to adding to end of list.
addTask(description, index = null) {
index = index != null ? index: index = this.children.length
this.children.splice(index, 0, new ObjectiveTask(
{description: description, parentId: this.id}
))
saveState()
}
getIndex(){
if (this.parentId !== null) {
const parent = getTaskById(this.parentId)
const index = parent.children.findIndex(task => task.id === this.id)
if (index === -1){
throw `getIndex failed: Task '${this.description}' not found in parent task '${parent.description}'`
}
return index
} else {
throw `getIndex failed: Task '${this.description}' has no parent`
}
}
// Used to set parent to complete when all child tasks are completed
checkParentComplete() {
let all_completed = true;
if (this.parentId !== ""){
const parent = getTaskById(this.parentId);
for (const child of parent.children){
if (!child.completed){
all_completed = false;
break;
}
}
if (all_completed){
parent.completed = true;
console.info(`Parent task '${parent.description}' completed after all child tasks complated.`)
} else {
parent.completed = false;
}
}
}
// Complete the current task, setting next task to next incomplete task // Complete the current task, setting next task to next incomplete task
completeTask() { completeTask() {
this.completed = true this.completed = true
console.info(`Task successfully completed: ${JSON.stringify(this.description)}`) console.info(`Task successfully completed: ${JSON.stringify(this.description)}`)
this.checkParentComplete()
setCurrentTask() setCurrentTask()
updateUiTaskList() updateUiTaskList()
} }
@ -211,6 +277,7 @@ class ObjectiveTask {
<span class="text_pole objective-task" style="display: block" id="objective-task-description-${this.id}" contenteditable>${this.description}</span> <span class="text_pole objective-task" style="display: block" id="objective-task-description-${this.id}" 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.id}" 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.id}" class="objective-task-button fa-solid fa-plus fa-2x" title="Add Task"></div>
<div id="objective-task-add-branch-${this.id}" class="objective-task-button fa-solid fa-code-fork fa-2x" title="Branch Task"></div>
</div><br> </div><br>
`; `;
@ -221,6 +288,15 @@ class ObjectiveTask {
this.descriptionSpan = $(`#objective-task-description-${this.id}`); this.descriptionSpan = $(`#objective-task-description-${this.id}`);
this.addButton = $(`#objective-task-add-${this.id}`); this.addButton = $(`#objective-task-add-${this.id}`);
this.deleteButton = $(`#objective-task-delete-${this.id}`); this.deleteButton = $(`#objective-task-delete-${this.id}`);
this.taskHtml = $(`#objective-task-label-${this.id}`);
this.branchButton = $(`#objective-task-add-branch-${this.id}`)
// Handle sub-task forking style
if (this.children.length > 0){
this.branchButton.css({'color':'#33cc33'})
} else {
this.branchButton.css({'color':''})
}
// Add event listeners and set properties // Add event listeners and set properties
$(`#objective-task-complete-${this.id}`).prop('checked', this.completed); $(`#objective-task-complete-${this.id}`).prop('checked', this.completed);
@ -229,145 +305,66 @@ class ObjectiveTask {
$(`#objective-task-description-${this.id}`).on('focusout', () => (this.onDescriptionFocusout())); $(`#objective-task-description-${this.id}`).on('focusout', () => (this.onDescriptionFocusout()));
$(`#objective-task-delete-${this.id}`).on('click', () => (this.onDeleteClick())); $(`#objective-task-delete-${this.id}`).on('click', () => (this.onDeleteClick()));
$(`#objective-task-add-${this.id}`).on('click', () => (this.onAddClick())); $(`#objective-task-add-${this.id}`).on('click', () => (this.onAddClick()));
this.branchButton.on('click', () => (this.onBranchClick()))
}
onBranchClick() {
currentObjective = this
updateUiTaskList();
setCurrentTask();
} }
onCompleteClick(){ onCompleteClick(){
this.completed = this.completedCheckbox.prop('checked') this.completed = this.completedCheckbox.prop('checked')
this.checkParentComplete()
setCurrentTask(); setCurrentTask();
} }
onDescriptionUpdate(){ onDescriptionUpdate(){
this.description = this.descriptionSpan.text(); this.description = this.descriptionSpan.text();
} }
onDescriptionFocusout(){ onDescriptionFocusout(){
setCurrentTask(); setCurrentTask();
} }
onDeleteClick(){ onDeleteClick(){
deleteTask(this.id); const index = this.getIndex()
const parent = getTaskById(this.parentId)
parent.children.splice(index, 1)
updateUiTaskList()
setCurrentTask()
} }
onAddClick(){ onAddClick(){
const {_, index} = getTaskById(this.id) const index = this.getIndex()
addTask("", index + 1); const parent = getTaskById(this.parentId)
setCurrentTask(); parent.addTask("", index + 1);
updateUiTaskList(); updateUiTaskList();
setCurrentTask();
} }
toSaveState() { toSaveStateRecurse() {
let children = []
if (this.children.length > 0){
for (const child of this.children){
children.push(child.toSaveStateRecurse())
}
}
return { return {
"id":this.id, "id":this.id,
"description":this.description, "description":this.description,
"completed":this.completed, "completed":this.completed,
"parent": this.parent, "parentId": this.parentId,
"children": children,
} }
} }
} }
//###############################// //###############################//
//# UI AND Settings #// //# Custom Prompts #//
//###############################// //###############################//
const defaultSettings = {
objective: "",
tasks: [],
chatDepth: 2,
checkFrequency: 3,
hideTasks: false,
prompts: defaultPrompts,
}
// Convenient single call. Not much at the moment.
function resetState() {
loadSettings();
}
//
function saveState() {
const context = getContext();
if (currentChatId == "") {
currentChatId = context.chatId
}
// Convert globalTasks for saving
const tasks = globalTasks.map(task => {return task.toSaveState()})
chat_metadata['objective'] = {
objective: globalObjective,
tasks: tasks,
checkFrequency: $('#objective-check-frequency').val(),
chatDepth: $('#objective-chat-depth').val(),
hideTasks: $('#objective-hide-tasks').prop('checked'),
prompts: objectivePrompts,
}
saveMetadataDebounced();
}
// Dump core state
function debugObjectiveExtension() {
console.log(JSON.stringify({
"currentTask": currentTask.description,
"globalObjective": globalObjective,
"globalTasks": globalTasks.map(v => {return v.toSaveState()}),
"chat_metadata": chat_metadata['objective'],
"extension_settings": extension_settings['objective'],
"prompts": objectivePrompts
}, null, 2))
}
window.debugObjectiveExtension = debugObjectiveExtension
// Populate UI task list
function updateUiTaskList() {
$('#objective-tasks').empty()
// Show tasks if there are any
if (globalTasks.length > 0){
for (const task of globalTasks) {
task.addUiElement()
}
} else {
// Show button to add tasks if there are none
$('#objective-tasks').append(`
<input id="objective-task-add-first" type="button" class="menu_button" value="Add Task">
`)
$("#objective-task-add-first").on('click', () => {
addTask("")
setCurrentTask()
updateUiTaskList()
})
}
}
// Trigger creation of new tasks with given objective.
async function onGenerateObjectiveClick() {
globalObjective = $('#objective-text').val()
await generateTasks()
saveState()
}
// Update extension prompts
function onChatDepthInput() {
saveState()
setCurrentTask() // Ensure extension prompt is updated
}
// Update how often we check for task completion
function onCheckFrequencyInput() {
checkCounter = $("#objective-check-frequency").val()
$('#objective-counter').text(checkCounter)
saveState()
}
function onHideTasksInput() {
$('#objective-tasks').prop('hidden', $('#objective-hide-tasks').prop('checked'))
saveState()
}
function onEditPromptClick() { function onEditPromptClick() {
let popupText = '' let popupText = ''
popupText += ` popupText += `
@ -411,7 +408,7 @@ function onEditPromptClick() {
// Handle save // Handle save
$('#objective-custom-prompt-save').on('click', () => { $('#objective-custom-prompt-save').on('click', () => {
addCustomPrompt($('#objective-custom-prompt-name').val(), objectivePrompts) saveCustomPrompt($('#objective-custom-prompt-name').val(), objectivePrompts)
}) })
// Handle delete // Handle delete
@ -424,7 +421,7 @@ function onEditPromptClick() {
$('#objective-prompt-load').on('change', loadCustomPrompt) $('#objective-prompt-load').on('change', loadCustomPrompt)
} }
function addCustomPrompt(customPromptName, customPrompts) { function saveCustomPrompt(customPromptName, customPrompts) {
if (customPromptName == "") { if (customPromptName == "") {
toastr.warning("Please set custom prompt name to save.") toastr.warning("Please set custom prompt name to save.")
return return
@ -453,7 +450,7 @@ function deleteCustomPrompt(customPromptName){
function loadCustomPrompt(){ function loadCustomPrompt(){
const optionSelected = $("#objective-prompt-load").find(':selected').val() const optionSelected = $("#objective-prompt-load").find(':selected').val()
console.log(optionSelected) console.log(optionSelected)
objectivePrompts = extension_settings.objective.customPrompts[optionSelected] Object.assign(objectivePrompts, extension_settings.objective.customPrompts[optionSelected])
$('#objective-prompt-generate').val(objectivePrompts.createTask) $('#objective-prompt-generate').val(objectivePrompts.createTask)
$('#objective-prompt-check').val(objectivePrompts.checkTaskCompleted) $('#objective-prompt-check').val(objectivePrompts.checkTaskCompleted)
@ -472,6 +469,141 @@ function populateCustomPrompts(){
} }
} }
//###############################//
//# UI AND Settings #//
//###############################//
const defaultSettings = {
currentObjectiveId: null,
taskTree: null,
chatDepth: 2,
checkFrequency: 3,
hideTasks: false,
prompts: defaultPrompts,
}
// Convenient single call. Not much at the moment.
function resetState() {
loadSettings();
}
//
function saveState() {
const context = getContext();
if (currentChatId == "") {
currentChatId = context.chatId
}
chat_metadata['objective'] = {
currentObjectiveId: currentObjective.id,
taskTree: taskTree.toSaveStateRecurse(),
checkFrequency: $('#objective-check-frequency').val(),
chatDepth: $('#objective-chat-depth').val(),
hideTasks: $('#objective-hide-tasks').prop('checked'),
prompts: objectivePrompts,
}
saveMetadataDebounced();
}
// Dump core state
function debugObjectiveExtension() {
console.log(JSON.stringify({
"currentTask": currentTask,
"currentObjective": currentObjective,
"taskTree": taskTree.toSaveStateRecurse(),
"chat_metadata": chat_metadata['objective'],
"extension_settings": extension_settings['objective'],
"prompts": objectivePrompts
}, null, 2))
}
window.debugObjectiveExtension = debugObjectiveExtension
// Populate UI task list
function updateUiTaskList() {
$('#objective-tasks').empty()
// Show button to navigate back to parent objective if parent exists
if (currentObjective){
if (currentObjective.parentId !== "") {
$('#objective-parent').show()
} else {
$('#objective-parent').hide()
}
}
$('#objective-text').val(currentObjective.description)
if (currentObjective.children.length > 0){
// Show tasks if there are any to show
for (const task of currentObjective.children) {
task.addUiElement()
}
} else {
// Show button to add tasks if there are none
$('#objective-tasks').append(`
<input id="objective-task-add-first" type="button" class="menu_button" value="Add Task">
`)
$("#objective-task-add-first").on('click', () => {
currentObjective.addTask("")
setCurrentTask()
updateUiTaskList()
})
}
}
function onParentClick() {
currentObjective = getTaskById(currentObjective.parentId)
updateUiTaskList()
setCurrentTask()
}
// Trigger creation of new tasks with given objective.
async function onGenerateObjectiveClick() {
await generateTasks()
saveState()
}
// Update extension prompts
function onChatDepthInput() {
saveState()
setCurrentTask() // Ensure extension prompt is updated
}
function onObjectiveTextFocusOut(){
currentObjective.description = $('#objective-text').val()
saveState()
}
// Update how often we check for task completion
function onCheckFrequencyInput() {
checkCounter = $("#objective-check-frequency").val()
$('#objective-counter').text(checkCounter)
saveState()
}
function onHideTasksInput() {
$('#objective-tasks').prop('hidden', $('#objective-hide-tasks').prop('checked'))
saveState()
}
function loadTaskChildrenRecurse(savedTask) {
let tempTaskTree = new ObjectiveTask({
id: savedTask.id,
description: savedTask.description,
completed: savedTask.completed,
parentId: savedTask.parentId,
})
for (const task of savedTask.children){
const childTask = loadTaskChildrenRecurse(task)
tempTaskTree.children.push(childTask)
}
return tempTaskTree
}
function loadSettings() { function loadSettings() {
// Load/Init settings for chatId // Load/Init settings for chatId
currentChatId = getContext().chatId currentChatId = getContext().chatId
@ -488,6 +620,7 @@ function loadSettings() {
// Migrate existing settings // Migrate existing settings
if (currentChatId in extension_settings.objective) { if (currentChatId in extension_settings.objective) {
// TODO: Remove this soon
chat_metadata['objective'] = extension_settings.objective[currentChatId]; chat_metadata['objective'] = extension_settings.objective[currentChatId];
delete extension_settings.objective[currentChatId]; delete extension_settings.objective[currentChatId];
} }
@ -496,21 +629,46 @@ function loadSettings() {
Object.assign(chat_metadata, { objective: defaultSettings }); Object.assign(chat_metadata, { objective: defaultSettings });
} }
// Update globals // Migrate legacy flat objective to new objectiveTree and currentObjective
globalObjective = chat_metadata['objective'].objective // if ('objective' in chat_metadata.objective) {
globalTasks = chat_metadata['objective'].tasks.map(task => {
return new ObjectiveTask({ // // Create root objective from legacy objective
id: task.id, // globalTaskTree = new ObjectiveTask({description: chat_metadata.objective})
description: task.description, // currentObjective = globalTaskTree
completed: task.completed,
parent: task.parent, // // Populate root objective tree from legacy objective tasks
}) // if ('tasks' in chat_metadata.objective) {
}); // globalTaskTree.children = chat_metadata.objective.tasks.map(task => {
// return new ObjectiveTask({
// description: task.description,
// completed: task.completed,
// parent: globalTaskTree,
// })
// });
// }
// chat_metadata.objective['objectiveTree'] = tempObjective.toSaveStateRecurse()
// }
// Reset Objectives and Tasks
taskTree = null;
currentObjective = null;
// Load Objectives and Tasks
if (chat_metadata.objective.taskTree){
taskTree = loadTaskChildrenRecurse(chat_metadata.objective.taskTree)
}
// Make sure there's a root task
if (!taskTree) {
taskTree = new ObjectiveTask({id:0,description:$('#objective-text').val()})
}
currentObjective = taskTree
checkCounter = chat_metadata['objective'].checkFrequency checkCounter = chat_metadata['objective'].checkFrequency
// Update UI elements // Update UI elements
$('#objective-counter').text(checkCounter) $('#objective-counter').text(checkCounter)
$("#objective-text").text(globalObjective) $("#objective-text").text(taskTree.description)
updateUiTaskList() updateUiTaskList()
$('#objective-chat-depth').val(chat_metadata['objective'].chatDepth) $('#objective-chat-depth').val(chat_metadata['objective'].chatDepth)
$('#objective-check-frequency').val(chat_metadata['objective'].checkFrequency) $('#objective-check-frequency').val(chat_metadata['objective'].checkFrequency)
@ -543,6 +701,10 @@ jQuery(() => {
<input id="objective-generate" class="menu_button" type="submit" value="Auto-Generate Tasks" /> <input id="objective-generate" class="menu_button" type="submit" value="Auto-Generate Tasks" />
<label class="checkbox_label"><input id="objective-hide-tasks" type="checkbox"> Hide Tasks</label> <label class="checkbox_label"><input id="objective-hide-tasks" type="checkbox"> Hide Tasks</label>
</div> </div>
<div id="objective-parent" class="objective_block flex-container">
<i class="objective-task-button fa-solid fa-circle-left fa-2x" title="Go to Parent"></i>
<small>Go to parent task</small>
</div>
<div id="objective-tasks"> </div> <div id="objective-tasks"> </div>
<div class="objective_block margin-bot-10px"> <div class="objective_block margin-bot-10px">
@ -564,7 +726,9 @@ jQuery(() => {
</div> </div>
<hr class="sysHR"> <hr class="sysHR">
</div> </div>
</div>`; </div>
</div>
`;
addManualTaskCheckUi() addManualTaskCheckUi()
$('#extensions_settings').append(settingsHtml); $('#extensions_settings').append(settingsHtml);
@ -573,6 +737,9 @@ jQuery(() => {
$("#objective-check-frequency").on('input', onCheckFrequencyInput) $("#objective-check-frequency").on('input', onCheckFrequencyInput)
$('#objective-hide-tasks').on('click', onHideTasksInput) $('#objective-hide-tasks').on('click', onHideTasksInput)
$('#objective_prompt_edit').on('click', onEditPromptClick) $('#objective_prompt_edit').on('click', onEditPromptClick)
$('#objective-parent').hide()
$('#objective-parent').on('click',onParentClick)
$('#objective-text').on('focusout',onObjectiveTextFocusOut)
loadSettings() loadSettings()
eventSource.on(event_types.CHAT_CHANGED, () => { eventSource.on(event_types.CHAT_CHANGED, () => {