mirror of
https://github.com/jlengrand/Maestro.git
synced 2026-03-10 08:31:19 +00:00
# CHANGES
- Added file system write capability for saving content directly 🚀 - Introduced unified API to fetch all named sessions across providers 🎯 - Enhanced session management with cross-provider named session support 📋 - Exposed writeFile method in preload for renderer process access ✍️ - Added getAllNamedSessions handler for aggregating session data 🔄 - Updated TabSwitcherModal to use new unified session API 🔧 - Extended type definitions for better TypeScript support 📝 - Improved session discovery across multiple storage providers 🔍 - Added error handling for multi-provider session aggregation 🛡️ - Streamlined named session retrieval for better performance ⚡
This commit is contained in:
@@ -885,6 +885,15 @@ function setupIpcHandlers() {
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('fs:writeFile', async (_, filePath: string, content: string) => {
|
||||
try {
|
||||
await fs.writeFile(filePath, content, 'utf-8');
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to write file: ${error}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Live session management - toggle sessions as live/offline in web interface
|
||||
ipcMain.handle('live:toggle', async (_, sessionId: string, agentSessionId?: string) => {
|
||||
if (!webServer) {
|
||||
|
||||
@@ -478,6 +478,51 @@ export function registerAgentSessionsHandlers(deps?: AgentSessionsHandlerDepende
|
||||
})
|
||||
);
|
||||
|
||||
// ============ Get All Named Sessions ============
|
||||
|
||||
ipcMain.handle(
|
||||
'agentSessions:getAllNamedSessions',
|
||||
withIpcErrorLogging(
|
||||
handlerOpts('getAllNamedSessions'),
|
||||
async (): Promise<
|
||||
Array<{
|
||||
agentSessionId: string;
|
||||
projectPath: string;
|
||||
sessionName: string;
|
||||
starred?: boolean;
|
||||
lastActivityAt?: number;
|
||||
}>
|
||||
> => {
|
||||
// Aggregate named sessions from all providers that support it
|
||||
const allNamedSessions: Array<{
|
||||
agentSessionId: string;
|
||||
projectPath: string;
|
||||
sessionName: string;
|
||||
starred?: boolean;
|
||||
lastActivityAt?: number;
|
||||
}> = [];
|
||||
|
||||
const storages = getAllSessionStorages();
|
||||
for (const storage of storages) {
|
||||
if ('getAllNamedSessions' in storage && typeof storage.getAllNamedSessions === 'function') {
|
||||
try {
|
||||
const sessions = await storage.getAllNamedSessions();
|
||||
allNamedSessions.push(...sessions);
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Failed to get named sessions from ${storage.agentId}: ${error}`,
|
||||
LOG_CONTEXT
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Found ${allNamedSessions.length} named sessions across all providers`, LOG_CONTEXT);
|
||||
return allNamedSessions;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// ============ Get Global Stats (All Providers) ============
|
||||
|
||||
ipcMain.handle(
|
||||
|
||||
@@ -353,6 +353,8 @@ contextBridge.exposeInMainWorld('maestro', {
|
||||
homeDir: () => ipcRenderer.invoke('fs:homeDir') as Promise<string>,
|
||||
readDir: (dirPath: string) => ipcRenderer.invoke('fs:readDir', dirPath),
|
||||
readFile: (filePath: string) => ipcRenderer.invoke('fs:readFile', filePath),
|
||||
writeFile: (filePath: string, content: string) =>
|
||||
ipcRenderer.invoke('fs:writeFile', filePath, content) as Promise<{ success: boolean }>,
|
||||
stat: (filePath: string) => ipcRenderer.invoke('fs:stat', filePath),
|
||||
},
|
||||
|
||||
@@ -637,6 +639,15 @@ contextBridge.exposeInMainWorld('maestro', {
|
||||
// Get global stats aggregated from all providers
|
||||
getGlobalStats: () =>
|
||||
ipcRenderer.invoke('agentSessions:getGlobalStats'),
|
||||
// Get all named sessions across all providers
|
||||
getAllNamedSessions: () =>
|
||||
ipcRenderer.invoke('agentSessions:getAllNamedSessions') as Promise<Array<{
|
||||
agentSessionId: string;
|
||||
projectPath: string;
|
||||
sessionName: string;
|
||||
starred?: boolean;
|
||||
lastActivityAt?: number;
|
||||
}>>,
|
||||
// Subscribe to global stats updates (streaming)
|
||||
onGlobalStatsUpdate: (callback: (stats: {
|
||||
totalSessions: number;
|
||||
@@ -1027,6 +1038,7 @@ export interface MaestroAPI {
|
||||
homeDir: () => Promise<string>;
|
||||
readDir: (dirPath: string) => Promise<DirectoryEntry[]>;
|
||||
readFile: (filePath: string) => Promise<string>;
|
||||
writeFile: (filePath: string, content: string) => Promise<{ success: boolean }>;
|
||||
stat: (filePath: string) => Promise<{
|
||||
size: number;
|
||||
createdAt: string;
|
||||
@@ -1297,6 +1309,13 @@ export interface MaestroAPI {
|
||||
deleteMessagePair: (agentId: string, projectPath: string, sessionId: string, userMessageUuid: string, fallbackContent?: string) => Promise<{ success: boolean; linesRemoved?: number; error?: string }>;
|
||||
hasStorage: (agentId: string) => Promise<boolean>;
|
||||
getAvailableStorages: () => Promise<string[]>;
|
||||
getAllNamedSessions: () => Promise<Array<{
|
||||
agentSessionId: string;
|
||||
projectPath: string;
|
||||
sessionName: string;
|
||||
starred?: boolean;
|
||||
lastActivityAt?: number;
|
||||
}>>;
|
||||
registerSessionOrigin: (projectPath: string, agentSessionId: string, origin: 'user' | 'auto', sessionName?: string) => Promise<boolean>;
|
||||
updateSessionName: (projectPath: string, agentSessionId: string, sessionName: string) => Promise<boolean>;
|
||||
};
|
||||
|
||||
@@ -208,7 +208,7 @@ export function TabSwitcherModal({
|
||||
)
|
||||
);
|
||||
// Then load all named sessions (including the ones we just synced)
|
||||
const sessions = await window.maestro.claude.getAllNamedSessions();
|
||||
const sessions = await window.maestro.agentSessions.getAllNamedSessions();
|
||||
setNamedSessions(sessions);
|
||||
setNamedSessionsLoaded(true);
|
||||
};
|
||||
|
||||
10
src/renderer/global.d.ts
vendored
10
src/renderer/global.d.ts
vendored
@@ -201,6 +201,7 @@ interface MaestroAPI {
|
||||
fs: {
|
||||
readDir: (dirPath: string) => Promise<DirectoryEntry[]>;
|
||||
readFile: (filePath: string) => Promise<string>;
|
||||
writeFile: (filePath: string, content: string) => Promise<{ success: boolean }>;
|
||||
};
|
||||
webserver: {
|
||||
getUrl: () => Promise<string>;
|
||||
@@ -328,6 +329,15 @@ interface MaestroAPI {
|
||||
hasCostData: boolean;
|
||||
}>;
|
||||
}) => void) => () => void;
|
||||
getAllNamedSessions: () => Promise<Array<{
|
||||
agentSessionId: string;
|
||||
projectPath: string;
|
||||
sessionName: string;
|
||||
starred?: boolean;
|
||||
lastActivityAt?: number;
|
||||
}>>;
|
||||
registerSessionOrigin: (projectPath: string, agentSessionId: string, origin: 'user' | 'auto', sessionName?: string) => Promise<boolean>;
|
||||
updateSessionName: (projectPath: string, agentSessionId: string, sessionName: string) => Promise<boolean>;
|
||||
};
|
||||
dialog: {
|
||||
selectFolder: () => Promise<string | null>;
|
||||
|
||||
Reference in New Issue
Block a user