import { ipcMain, dialog, type BrowserWindow } from "electron"; import * as projects from "../db/projects"; import * as sessions from "../db/sessions"; import * as claude from "../claude"; import { createSessionBranch, ensureGitIgnore } from "../git"; import type { UserPermissionMode } from "../claude/phases"; export function registerIpcHandlers(mainWindow: BrowserWindow): void { // Projects ipcMain.handle("projects:list", () => projects.listProjects()); ipcMain.handle("projects:create", (_, name: string, path: string) => projects.createProject(name, path) ); ipcMain.handle("projects:delete", (_, id: string) => projects.deleteProject(id) ); // Sessions ipcMain.handle("sessions:list", (_, projectId: string) => sessions.listSessions(projectId) ); ipcMain.handle("sessions:create", (_, projectId: string, name: string) => { const project = projects.getProject(projectId); if (!project) throw new Error("Project not found"); const session = sessions.createSession(projectId, name); // Ensure .claude-flow/ is gitignored from day one. // Branch creation is deferred until the session advances to implement. try { ensureGitIgnore(project.path); } catch { /* non-fatal */ } return session; }); ipcMain.handle("sessions:delete", (_, id: string) => { const session = sessions.getSession(id); if (session) { // Clean up session artifacts from global storage claude.clearSessionArtifacts(session.project_id, id); } sessions.deleteSession(id); }); ipcMain.handle("sessions:rename", (_, id: string, name: string) => { sessions.updateSession(id, { name }); }); ipcMain.handle("sessions:get", (_, id: string) => sessions.getSession(id)); // Messages ipcMain.handle("messages:list", (_, sessionId: string) => sessions.listMessages(sessionId) ); // Chat ipcMain.handle( "chat:send", async (_, sessionId: string, message: string) => { const session = sessions.getSession(sessionId); if (!session) throw new Error("Session not found"); // Store user message sessions.addMessage(sessionId, "user", message); await claude.sendMessage({ session, message, onMessage: (msg) => { // Forward all messages to renderer mainWindow.webContents.send("claude:message", sessionId, msg); // Store assistant text messages if (msg.type === "assistant") { const content = (msg.message.content as Array<{ type: string; text?: string }>) .filter((c) => c.type === "text" && c.text) .map((c) => c.text!) .join("\n"); if (content) { sessions.addMessage(sessionId, "assistant", content); } } }, }); } ); ipcMain.handle("chat:interrupt", (_, sessionId: string) => { claude.interruptSession(sessionId); }); // Workflow ipcMain.handle("workflow:review", async (_, sessionId: string) => { const session = sessions.getSession(sessionId); if (!session) throw new Error("Session not found"); await claude.triggerReview(session, (msg) => { mainWindow.webContents.send("claude:message", sessionId, msg); }); }); ipcMain.handle("workflow:advance", (_, sessionId: string) => { const session = sessions.getSession(sessionId); if (!session) throw new Error("Session not found"); const nextPhase = claude.advancePhase(session); if (!nextPhase) return null; let git_branch = session.git_branch; if (nextPhase === "implement") { const project = projects.getProject(session.project_id); if (project) { const branchName = createSessionBranch(project.path, session.name, session.id); if (branchName) { sessions.updateSession(sessionId, { git_branch: branchName }); git_branch = branchName; } } } return { phase: nextPhase, git_branch }; }); ipcMain.handle( "workflow:setPermissionMode", (_, sessionId: string, mode: string) => { sessions.updateSession(sessionId, { permission_mode: mode as UserPermissionMode, }); } ); // Session Artifacts (stored in ~/.claude-flow/) ipcMain.handle( "artifact:readSession", (_, projectId: string, sessionId: string, filename: string) => { return claude.readSessionArtifact(projectId, sessionId, filename); } ); ipcMain.handle( "artifact:writeSession", (_, projectId: string, sessionId: string, filename: string, content: string) => { claude.writeSessionArtifact(projectId, sessionId, filename, content); } ); // CLAUDE.md (stored in project) ipcMain.handle("claudemd:read", (_, projectPath: string) => { return claude.readClaudeMd(projectPath); }); ipcMain.handle("claudemd:write", (_, projectPath: string, content: string) => { claude.writeClaudeMd(projectPath, content); }); // Dialogs ipcMain.handle("dialog:selectDirectory", async () => { const result = await dialog.showOpenDialog(mainWindow, { properties: ["openDirectory"], }); return result.canceled ? null : result.filePaths[0]; }); }