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 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) => sessions.createSession(projectId, name) ); 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: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"); return claude.advancePhase(session); }); 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]; }); }