feat: 重构数据存储路径并优化任务通知机制

将审计日志、会话数据和定时任务文件移动到统一的data目录下
为后台任务添加完成回调功能,优化CC任务完成后的通知流程
更新README和ROADMAP文档,标记已完成的功能项
This commit is contained in:
Yuyao Huang (Sam)
2026-03-29 02:32:48 +08:00
parent 80e4953cf9
commit 52a9d085f7
10 changed files with 200 additions and 58 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ from typing import Optional
logger = logging.getLogger(__name__)
AUDIT_DIR = Path(__file__).parent.parent / "audit"
AUDIT_DIR = Path(__file__).parent.parent / "data" / "audit"
def _ensure_audit_dir() -> None:
+23 -3
View File
@@ -17,7 +17,7 @@ logger = logging.getLogger(__name__)
DEFAULT_IDLE_TIMEOUT = 30 * 60
DEFAULT_CC_TIMEOUT = 300.0
PERSISTENCE_FILE = Path(__file__).parent.parent / "sessions.json"
PERSISTENCE_FILE = Path(__file__).parent.parent / "data" / "sessions.json"
@dataclass
@@ -105,7 +105,7 @@ class SessionManager:
if cc_timeout > 60:
from agent.task_runner import task_runner
from orchestrator.tools import get_current_chat
from orchestrator.tools import get_current_chat, set_current_chat, set_current_user
chat_id = get_current_chat()
@@ -126,10 +126,29 @@ class SessionManager:
)
return output
async def on_task_complete(task) -> None:
if not chat_id or not user_id or not task.result:
return
set_current_user(user_id)
set_current_chat(chat_id)
from orchestrator.agent import agent
follow_up = (
f"CC task completed. Output:\n{task.result}\n\n"
f"Original request was: {message}\n\n"
"If the user asked you to send a file, use send_file now. "
"Otherwise just acknowledge completion."
)
reply = await agent.run(user_id, follow_up)
if reply:
from bot.feishu import send_text
await send_text(chat_id, "chat_id", reply)
task_id = await task_runner.submit(
run_task,
run_task(),
description=f"CC session {conv_id}: {message[:50]}",
notify_chat_id=chat_id,
user_id=user_id,
on_complete=on_task_complete,
)
return f"⏳ Task #{task_id} started (timeout: {int(cc_timeout)}s). I'll notify you when it's done."
@@ -183,6 +202,7 @@ class SessionManager:
def _save(self) -> None:
try:
data = {cid: s.to_dict() for cid, s in self._sessions.items()}
PERSISTENCE_FILE.parent.mkdir(parents=True, exist_ok=True)
with open(PERSISTENCE_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
logger.debug("Saved %d sessions to %s", len(data), PERSISTENCE_FILE)
+2 -1
View File
@@ -14,7 +14,7 @@ from typing import Any, Callable, Dict, Optional
logger = logging.getLogger(__name__)
PERSISTENCE_FILE = Path(__file__).parent.parent / "scheduled_jobs.json"
PERSISTENCE_FILE = Path(__file__).parent.parent / "data" / "scheduled_jobs.json"
class JobStatus(str, Enum):
@@ -98,6 +98,7 @@ class Scheduler:
"""Save jobs to persistence file."""
try:
data = {jid: job.to_dict() for jid, job in self._jobs.items()}
PERSISTENCE_FILE.parent.mkdir(parents=True, exist_ok=True)
with open(PERSISTENCE_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
except Exception:
+9 -2
View File
@@ -57,6 +57,7 @@ class TaskRunner:
description: str,
notify_chat_id: Optional[str] = None,
user_id: Optional[str] = None,
on_complete: Optional[Callable[[BackgroundTask], Awaitable[None]]] = None,
) -> str:
"""Submit a coroutine as a background task."""
task_id = str(uuid.uuid4())[:8]
@@ -72,11 +73,11 @@ class TaskRunner:
async with self._lock:
self._tasks[task_id] = task
asyncio.create_task(self._run_task(task_id, coro))
asyncio.create_task(self._run_task(task_id, coro, on_complete))
logger.info("Submitted background task %s: %s", task_id, description)
return task_id
async def _run_task(self, task_id: str, coro: Awaitable[Any]) -> None:
async def _run_task(self, task_id: str, coro: Awaitable[Any], on_complete: Optional[Callable[[BackgroundTask], Awaitable[None]]] = None) -> None:
"""Execute a task and send notification on completion."""
async with self._lock:
task = self._tasks.get(task_id)
@@ -107,6 +108,12 @@ class TaskRunner:
else:
await self._send_notification(task)
if on_complete and task.status == TaskStatus.COMPLETED:
try:
await on_complete(task)
except Exception:
logger.exception("on_complete callback failed for task %s", task_id)
async def _send_notification(self, task: BackgroundTask) -> None:
"""Send Feishu notification about task completion."""
from bot.feishu import send_text