scheduler contexts fix

frdel committed May 3, 2025 at 19:01 UTC 660eee209ff256a66cf228e38e5e1ff09059998f
4 files changed +42 -29
python/api/scheduler_task_create.py
+6 -5
@@ -24,7 +24,7 @@ class SchedulerTaskCreate(ApiHandler):
24
25 # Get common fields from input
26 name = input.get("name")
27 - system_prompt = input.get("system_prompt")
27 + system_prompt = input.get("system_prompt", "")
28 prompt = input.get("prompt")
29 attachments = input.get("attachments", [])
30 context_id = input.get("context_id", None)
@@ -44,8 +44,9 @@ class SchedulerTaskCreate(ApiHandler):
44 plan = input.get("plan", {})
45
46 # Validate required fields
47 - if not name or not system_prompt or not prompt:
48 - return {"error": "Missing required fields: name, system_prompt, prompt"}
47 + if not name or not prompt:
48 + # return {"error": "Missing required fields: name, system_prompt, prompt"}
49 + raise ValueError("Missing required fields: name, system_prompt, prompt")
50
51 task = None
52 if schedule:
@@ -66,9 +67,9 @@ class SchedulerTaskCreate(ApiHandler):
67 try:
68 task_schedule = parse_task_schedule(schedule)
69 except ValueError as e:
69 - return {"error": str(e)}
70 + raise ValueError(str(e))
71 else:
71 - return {"error": "Invalid schedule format. Must be string or object."}
72 + raise ValueError("Invalid schedule format. Must be string or object.")
73
74 task = ScheduledTask.create(
75 name=name,
python/helpers/task_scheduler.py
+4 -4
@@ -706,10 +706,10 @@ class TaskScheduler:
706 raise ValueError(f"Task {task.name} has no context ID")
707
708 config = initialize()
709 - context: AgentContext = AgentContext(config)
710 - context.id = task.context_id
709 + context: AgentContext = AgentContext(config, id=task.context_id, name=task.name)
710 + # context.id = task.context_id
711 # initial name before renaming is same as task name
712 - context.name = task.name
712 + # context.name = task.name
713
714 # Save the context
715 save_tmp_chat(context)
@@ -772,7 +772,7 @@ class TaskScheduler:
772 # Ensure the context is properly registered in the AgentContext._contexts
773 # This is critical for the polling mechanism to find and stream logs
774 # Dict operations are atomic
775 - AgentContext._contexts[context.id] = context
775 + # AgentContext._contexts[context.id] = context
776 agent = context.streaming_agent or context.agent0
777
778 # Prepare attachment filenames for logging
webui/index.js
+25 -18
@@ -562,24 +562,8 @@ window.killChat = async function (id) {
562 const chatsAD = Alpine.$data(chatsSection);
563 console.log("Current contexts before deletion:", JSON.stringify(chatsAD.contexts.map(c => ({ id: c.id, name: c.name }))));
564
565 - // Find an alternate chat to switch to if we're deleting the current one
566 - let alternateChat = null;
567 - for (let i = 0; i < chatsAD.contexts.length; i++) {
568 - if (chatsAD.contexts[i].id !== id) {
569 - alternateChat = chatsAD.contexts[i];
570 - break;
571 - }
572 - }
573 -
574 - // If we're deleting the currently selected chat, switch to another one first
575 - if (context === id) {
576 - if (alternateChat) {
577 - setContext(alternateChat.id);
578 - } else {
579 - // If no other chats, create a new empty context
580 - setContext(generateGUID());
581 - }
582 - }
565 + // switch to another context if deleting current
566 + switchFromContext(id);
567
568 // Delete the chat on the server
569 await sendJsonData("/chat_remove", { context: id });
@@ -601,6 +585,29 @@ window.killChat = async function (id) {
585 }
586 }
587
588 +export function switchFromContext(id){
589 + // If we're deleting the currently selected chat, switch to another one first
590 + if (context === id) {
591 + const chatsAD = Alpine.$data(chatsSection);
592 +
593 + // Find an alternate chat to switch to if we're deleting the current one
594 + let alternateChat = null;
595 + for (let i = 0; i < chatsAD.contexts.length; i++) {
596 + if (chatsAD.contexts[i].id !== id) {
597 + alternateChat = chatsAD.contexts[i];
598 + break;
599 + }
600 + }
601 +
602 + if (alternateChat) {
603 + setContext(alternateChat.id);
604 + } else {
605 + // If no other chats, create a new empty context
606 + setContext(generateGUID());
607 + }
608 + }
609 +}
610 +
611 // Function to ensure proper UI state when switching contexts
612 function ensureProperTabSelection(contextId) {
613 // Get current active tab
webui/js/scheduler.js
+7 -2
@@ -4,6 +4,7 @@
4 */
5
6 import { formatDateTime, getUserTimezone } from './time-utils.js';
7 +import { switchFromContext } from '../index.js';
8
9 // Ensure the showToast function is available
10 // if (typeof window.showToast !== 'function') {
@@ -652,8 +653,9 @@ const fullComponentImplementation = function() {
653 // Save task (create new or update existing)
654 async saveTask() {
655 // Validate task data
655 - if (!this.editingTask.name.trim()) {
656 - showToast('Task name is required', 'error');
656 + if (!this.editingTask.name.trim() || !this.editingTask.prompt.trim()) {
657 + // showToast('Task name and prompt are required', 'error');
658 + alert('Task name and prompt are required');
659 return;
660 }
661
@@ -971,6 +973,9 @@ const fullComponentImplementation = function() {
973
974 showToast('Task deleted successfully', 'success');
975
976 + // if we deleted selected context, switch to another
977 + switchFromContext(taskId);
978 +
979 // If we were viewing the detail of the deleted task, close the detail view
980 if (this.selectedTaskForDetail && this.selectedTaskForDetail.uuid === taskId) {
981 this.closeTaskDetail();