refactor(scheduler): move manual runs to console controls

This commit is contained in:
AaronZ345
2026-07-17 16:44:30 +08:00
parent f7a0184ea2
commit 209f1f0a6f
10 changed files with 199 additions and 53 deletions

View File

@@ -4,7 +4,8 @@ import json
import sys
import types
from datetime import datetime, timedelta
from unittest.mock import patch
from pathlib import Path
from unittest.mock import Mock, patch
from agent.tools.scheduler.task_store import TaskStore
@@ -28,7 +29,9 @@ if "web" not in sys.modules:
)
sys.modules["web"] = web_stub
from channel.web.web_channel import SchedulerUpdateHandler
from channel.web import web_channel
SchedulerUpdateHandler = web_channel.SchedulerUpdateHandler
def _store_task(tmp_path, action):
@@ -54,6 +57,57 @@ def _post_update(tmp_path, payload):
return json.loads(SchedulerUpdateHandler().POST())
def test_web_manual_run_is_authenticated_and_delegates_to_scheduler():
assert hasattr(web_channel, "SchedulerRunHandler")
service = Mock()
with patch("channel.web.web_channel._require_auth") as require_auth, \
patch("channel.web.web_channel.web.header"), \
patch("channel.web.web_channel.web.data", return_value=b'{"task_id":"task-1"}'), \
patch("agent.tools.scheduler.integration.get_scheduler_service", return_value=service):
response = json.loads(web_channel.SchedulerRunHandler().POST())
require_auth.assert_called_once_with()
service.run_task_now.assert_called_once_with("task-1")
assert response == {
"status": "success",
"message": "Task 'task-1' queued for immediate execution",
}
def test_web_manual_run_rejects_unavailable_scheduler():
assert hasattr(web_channel, "SchedulerRunHandler")
with patch("channel.web.web_channel._require_auth"), \
patch("channel.web.web_channel.web.header"), \
patch("channel.web.web_channel.web.data", return_value=b'{"task_id":"task-1"}'), \
patch("agent.tools.scheduler.integration.get_scheduler_service", return_value=None):
response = json.loads(web_channel.SchedulerRunHandler().POST())
assert response == {
"status": "error",
"message": "Scheduler service is not running",
}
def test_manual_run_is_exposed_by_explicit_web_and_desktop_controls():
root = Path(__file__).parents[1]
web_source = (root / "channel/web/web_channel.py").read_text(encoding="utf-8")
web_console = (root / "channel/web/static/js/console.js").read_text(encoding="utf-8")
desktop_client = (root / "desktop/src/renderer/src/api/client.ts").read_text(encoding="utf-8")
desktop_page = (root / "desktop/src/renderer/src/pages/TasksPage.tsx").read_text(encoding="utf-8")
assert "'/api/scheduler/run', 'SchedulerRunHandler'" in web_source
assert "function runTaskNow(task, button)" in web_console
assert "fetch('/api/scheduler/run'" in web_console
web_run = web_console[web_console.index("function runTaskNow(task, button)"):]
assert "showConfirmDialog({" in web_run[:2500]
assert "async runTask(taskId: string)" in desktop_client
assert "'/api/scheduler/run'" in desktop_client
assert "const runNow = async ()" in desktop_page
assert "window.confirm(t('task_run_confirm'))" in desktop_page
def test_web_edit_preserves_hidden_agent_action_fields(tmp_path):
store = _store_task(tmp_path, {
"type": "agent_task",