feat(core): implement session isolation for agent and claude executions

- Add run_id/session_id based event isolation for concurrent executions
- Enhance process registry with graceful shutdown and fallback kill methods
- Implement session-specific event listeners in React components
- Add proper process cleanup with timeout handling
- Support both isolated and backward-compatible event emissions
- Improve error handling and logging for process management

This change prevents event crosstalk between multiple concurrent agent/claude sessions
running simultaneously, ensuring proper isolation and user experience.
This commit is contained in:
Mufeed VH
2025-06-25 02:14:18 +05:30
parent f73d21e09f
commit 97290e5665
8 changed files with 352 additions and 148 deletions

View File

@@ -268,6 +268,8 @@ export const AgentExecution: React.FC<AgentExecutionProps> = ({
const handleExecute = async () => {
if (!projectPath || !task.trim()) return;
let runId: number | null = null;
try {
setIsRunning(true);
setError(null);
@@ -277,8 +279,11 @@ export const AgentExecution: React.FC<AgentExecutionProps> = ({
setElapsedTime(0);
setTotalTokens(0);
// Set up event listeners
const outputUnlisten = await listen<string>("agent-output", (event) => {
// Execute the agent with model override and get run ID
runId = await api.executeAgent(agent.id!, projectPath, task, model);
// Set up event listeners with run ID isolation
const outputUnlisten = await listen<string>(`agent-output:${runId}`, (event) => {
try {
// Store raw JSONL
setRawJsonlOutput(prev => [...prev, event.payload]);
@@ -291,12 +296,12 @@ export const AgentExecution: React.FC<AgentExecutionProps> = ({
}
});
const errorUnlisten = await listen<string>("agent-error", (event) => {
const errorUnlisten = await listen<string>(`agent-error:${runId}`, (event) => {
console.error("Agent error:", event.payload);
setError(event.payload);
});
const completeUnlisten = await listen<boolean>("agent-complete", (event) => {
const completeUnlisten = await listen<boolean>(`agent-complete:${runId}`, (event) => {
setIsRunning(false);
setExecutionStartTime(null);
if (!event.payload) {
@@ -304,10 +309,13 @@ export const AgentExecution: React.FC<AgentExecutionProps> = ({
}
});
unlistenRefs.current = [outputUnlisten, errorUnlisten, completeUnlisten];
const cancelUnlisten = await listen<boolean>(`agent-cancelled:${runId}`, () => {
setIsRunning(false);
setExecutionStartTime(null);
setError("Agent execution was cancelled");
});
// Execute the agent with model override
await api.executeAgent(agent.id!, projectPath, task, model);
unlistenRefs.current = [outputUnlisten, errorUnlisten, completeUnlisten, cancelUnlisten];
} catch (err) {
console.error("Failed to execute agent:", err);
setError("Failed to execute agent");