From 7ad771598f0557fc0e82dd4dd70d884ecb6cd0ef Mon Sep 17 00:00:00 2001 From: jimpablo <194239734+jimpablo@users.noreply.github.com> Date: Wed, 6 May 2026 22:49:32 +0800 Subject: [PATCH] fix(orchestrator): cancel queued sessions when agent is disabled Signed-off-by: jimpablo <194239734+jimpablo@users.noreply.github.com> --- loom/orchestrator/dispatcher.py | 2 ++ loom/orchestrator/session.py | 17 ++++++++++++++++- loom/webui/frontend/.gitignore | 1 + loom/webui/frontend/tsconfig.tsbuildinfo | 1 - 4 files changed, 19 insertions(+), 2 deletions(-) delete mode 100644 loom/webui/frontend/tsconfig.tsbuildinfo diff --git a/loom/orchestrator/dispatcher.py b/loom/orchestrator/dispatcher.py index 3fb3c64..97e4c51 100644 --- a/loom/orchestrator/dispatcher.py +++ b/loom/orchestrator/dispatcher.py @@ -76,6 +76,8 @@ def set_agent_enabled(self, enabled: bool) -> None: logger.info("Agent processing %s", state) if enabled: self._start_drain() + else: + self._sessions.cancel_queued() async def start(self) -> None: """Subscribe to event bus.""" diff --git a/loom/orchestrator/session.py b/loom/orchestrator/session.py index 2db73bc..b784d23 100644 --- a/loom/orchestrator/session.py +++ b/loom/orchestrator/session.py @@ -65,6 +65,7 @@ class Session: cli_session_id: str = "" cwd: str = "" _client: ClaudeSDKClient | None = field(default=None, repr=False) + _task: asyncio.Task[None] | None = field(default=None, repr=False) class SessionManager: @@ -154,6 +155,20 @@ def list_sessions(self, status: SessionStatus | None = None) -> list[Session]: sessions = [s for s in sessions if s.status == status] return sessions + def cancel_queued(self) -> int: + """Cancel all QUEUED sessions. Returns count cancelled.""" + queued = [s for s in self._sessions.values() if s.status == SessionStatus.QUEUED] + count = 0 + for session in queued: + if session._task and not session._task.done(): + session._task.cancel() + session.status = SessionStatus.FAILED + session.error = "Cancelled (agent disabled)" + count += 1 + if count: + logger.info("Cancelled %d queued sessions", count) + return count + # ------------------------------------------------------------------ # Interactive session (multi-turn via ClaudeSDKClient) # ------------------------------------------------------------------ @@ -223,7 +238,7 @@ async def _guarded_run() -> None: return await self._run_session(session, task_prompt) - asyncio.create_task(_guarded_run()) + session._task = asyncio.create_task(_guarded_run()) return session async def _run_session(self, session: Session, prompt: str) -> None: diff --git a/loom/webui/frontend/.gitignore b/loom/webui/frontend/.gitignore index 7535211..9c29b63 100644 --- a/loom/webui/frontend/.gitignore +++ b/loom/webui/frontend/.gitignore @@ -2,3 +2,4 @@ node_modules dist *.log .DS_Store +tsconfig.tsbuildinfo diff --git a/loom/webui/frontend/tsconfig.tsbuildinfo b/loom/webui/frontend/tsconfig.tsbuildinfo deleted file mode 100644 index 9bc8d34..0000000 --- a/loom/webui/frontend/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"root":["./src/app.tsx","./src/main.tsx","./src/components/actionspanel.tsx","./src/components/column.tsx","./src/components/detailpanel.tsx","./src/components/envelopecard.tsx","./src/components/envelopedetail.tsx","./src/components/kanbanboard.tsx","./src/components/label.tsx","./src/components/settingspopover.tsx","./src/components/sidebar.tsx","./src/components/statusbar.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/dialog.tsx","./src/components/ui/popover.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/separator.tsx","./src/components/ui/tooltip.tsx","./src/lib/api.ts","./src/lib/config.ts","./src/lib/policies.ts","./src/lib/prompts.ts","./src/lib/settings.ts","./src/lib/types.ts","./src/lib/utils.ts","./src/pages/settingspage.tsx","./src/pages/config/configeditor.tsx","./src/pages/config/configformeditor.tsx","./src/pages/config/configpanel.tsx","./src/pages/config/configyamleditor.tsx","./src/pages/policies/policiespanel.tsx","./src/pages/policies/policyeditor.tsx","./src/pages/policies/policyformeditor.tsx","./src/pages/policies/policyyamleditor.tsx","./src/pages/policies/rulecard.tsx","./src/pages/prompts/prompteditor.tsx","./src/pages/prompts/promptspanel.tsx"],"version":"5.9.3"}