Improve power save blocker mechanism (#3698)
This commit is contained in:
@@ -49,6 +49,7 @@ export const useChatEngine = ({
|
|||||||
const [sessionOutputTokens, setSessionOutputTokens] = useState<number>(0);
|
const [sessionOutputTokens, setSessionOutputTokens] = useState<number>(0);
|
||||||
const [localInputTokens, setLocalInputTokens] = useState<number>(0);
|
const [localInputTokens, setLocalInputTokens] = useState<number>(0);
|
||||||
const [localOutputTokens, setLocalOutputTokens] = useState<number>(0);
|
const [localOutputTokens, setLocalOutputTokens] = useState<number>(0);
|
||||||
|
const [powerSaveTimeoutId, setPowerSaveTimeoutId] = useState<number | null>(null);
|
||||||
|
|
||||||
// Store message in global history when it's added (if enabled)
|
// Store message in global history when it's added (if enabled)
|
||||||
const storeMessageInHistory = useCallback(
|
const storeMessageInHistory = useCallback(
|
||||||
@@ -63,6 +64,20 @@ export const useChatEngine = ({
|
|||||||
[enableLocalStorage]
|
[enableLocalStorage]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const stopPowerSaveBlocker = useCallback(() => {
|
||||||
|
try {
|
||||||
|
window.electron.stopPowerSaveBlocker();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to stop power save blocker:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear timeout if it exists
|
||||||
|
if (powerSaveTimeoutId) {
|
||||||
|
window.clearTimeout(powerSaveTimeoutId);
|
||||||
|
setPowerSaveTimeoutId(null);
|
||||||
|
}
|
||||||
|
}, [powerSaveTimeoutId]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
messages,
|
messages,
|
||||||
append: originalAppend,
|
append: originalAppend,
|
||||||
@@ -84,7 +99,7 @@ export const useChatEngine = ({
|
|||||||
initialMessages: chat.messages,
|
initialMessages: chat.messages,
|
||||||
body: { session_id: chat.id, session_working_dir: window.appConfig.get('GOOSE_WORKING_DIR') },
|
body: { session_id: chat.id, session_working_dir: window.appConfig.get('GOOSE_WORKING_DIR') },
|
||||||
onFinish: async (_message, _reason) => {
|
onFinish: async (_message, _reason) => {
|
||||||
window.electron.stopPowerSaveBlocker();
|
stopPowerSaveBlocker();
|
||||||
|
|
||||||
const timeSinceLastInteraction = Date.now() - lastInteractionTime;
|
const timeSinceLastInteraction = Date.now() - lastInteractionTime;
|
||||||
window.electron.logInfo('last interaction:' + lastInteractionTime);
|
window.electron.logInfo('last interaction:' + lastInteractionTime);
|
||||||
@@ -110,6 +125,8 @@ export const useChatEngine = ({
|
|||||||
onMessageStreamFinish?.();
|
onMessageStreamFinish?.();
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
|
stopPowerSaveBlocker();
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'CHAT ENGINE RECEIVED ERROR FROM MESSAGE STREAM:',
|
'CHAT ENGINE RECEIVED ERROR FROM MESSAGE STREAM:',
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
@@ -206,40 +223,67 @@ export const useChatEngine = ({
|
|||||||
}
|
}
|
||||||
}, [sessionMetadata]);
|
}, [sessionMetadata]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (powerSaveTimeoutId) {
|
||||||
|
window.clearTimeout(powerSaveTimeoutId);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
window.electron.stopPowerSaveBlocker();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to stop power save blocker during cleanup:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [powerSaveTimeoutId]);
|
||||||
|
|
||||||
// Handle submit
|
// Handle submit
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(combinedTextFromInput: string, onSummaryReset?: () => void) => {
|
(combinedTextFromInput: string, onSummaryReset?: () => void) => {
|
||||||
if (combinedTextFromInput.trim()) {
|
if (combinedTextFromInput.trim()) {
|
||||||
window.electron.startPowerSaveBlocker();
|
try {
|
||||||
|
window.electron.startPowerSaveBlocker();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to start power save blocker:', error);
|
||||||
|
}
|
||||||
|
|
||||||
setLastInteractionTime(Date.now());
|
setLastInteractionTime(Date.now());
|
||||||
|
|
||||||
|
// Set a timeout to automatically stop the power save blocker after 15 minutes
|
||||||
|
const timeoutId = window.setTimeout(
|
||||||
|
() => {
|
||||||
|
console.warn('Power save blocker timeout - stopping automatically after 15 minutes');
|
||||||
|
stopPowerSaveBlocker();
|
||||||
|
},
|
||||||
|
15 * 60 * 1000
|
||||||
|
);
|
||||||
|
|
||||||
|
setPowerSaveTimeoutId(timeoutId);
|
||||||
|
|
||||||
const userMessage = createUserMessage(combinedTextFromInput.trim());
|
const userMessage = createUserMessage(combinedTextFromInput.trim());
|
||||||
|
|
||||||
if (onSummaryReset) {
|
if (onSummaryReset) {
|
||||||
onSummaryReset();
|
onSummaryReset();
|
||||||
setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
append(userMessage);
|
append(userMessage);
|
||||||
// Call onMessageSent after the message is sent
|
|
||||||
onMessageSent?.();
|
onMessageSent?.();
|
||||||
}, 150);
|
}, 150);
|
||||||
} else {
|
} else {
|
||||||
append(userMessage);
|
append(userMessage);
|
||||||
// Call onMessageSent after the message is sent
|
|
||||||
onMessageSent?.();
|
onMessageSent?.();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If nothing was actually submitted (e.g. empty input and no images pasted)
|
// If nothing was actually submitted (e.g. empty input and no images pasted)
|
||||||
window.electron.stopPowerSaveBlocker();
|
stopPowerSaveBlocker();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[append, onMessageSent]
|
[append, onMessageSent, stopPowerSaveBlocker]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle stopping the message stream
|
// Handle stopping the message stream
|
||||||
const onStopGoose = useCallback(() => {
|
const onStopGoose = useCallback(() => {
|
||||||
stop();
|
stop();
|
||||||
setLastInteractionTime(Date.now());
|
setLastInteractionTime(Date.now());
|
||||||
window.electron.stopPowerSaveBlocker();
|
stopPowerSaveBlocker();
|
||||||
|
|
||||||
// Handle stopping the message stream
|
// Handle stopping the message stream
|
||||||
const lastMessage = messages[messages.length - 1];
|
const lastMessage = messages[messages.length - 1];
|
||||||
@@ -330,7 +374,7 @@ export const useChatEngine = ({
|
|||||||
setMessages([...messages, responseMessage]);
|
setMessages([...messages, responseMessage]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [stop, messages, _setInput, setMessages, enableLocalStorage]);
|
}, [stop, messages, _setInput, setMessages, stopPowerSaveBlocker, enableLocalStorage]);
|
||||||
|
|
||||||
const filteredMessages = useMemo(() => {
|
const filteredMessages = useMemo(() => {
|
||||||
return [...ancestorMessages, ...messages].filter((message) => message.display ?? true);
|
return [...ancestorMessages, ...messages].filter((message) => message.display ?? true);
|
||||||
|
|||||||
+72
-15
@@ -503,8 +503,8 @@ let appConfig = {
|
|||||||
let windowCounter = 0;
|
let windowCounter = 0;
|
||||||
const windowMap = new Map<number, BrowserWindow>();
|
const windowMap = new Map<number, BrowserWindow>();
|
||||||
|
|
||||||
// Track power save blocker ID globally
|
// Track power save blockers per window
|
||||||
let powerSaveBlockerId: number | null = null;
|
const windowPowerSaveBlockers = new Map<number, number>(); // windowId -> blockerId
|
||||||
|
|
||||||
const createChat = async (
|
const createChat = async (
|
||||||
app: App,
|
app: App,
|
||||||
@@ -838,6 +838,23 @@ const createChat = async (
|
|||||||
// Handle window closure
|
// Handle window closure
|
||||||
mainWindow.on('closed', () => {
|
mainWindow.on('closed', () => {
|
||||||
windowMap.delete(windowId);
|
windowMap.delete(windowId);
|
||||||
|
|
||||||
|
if (windowPowerSaveBlockers.has(windowId)) {
|
||||||
|
const blockerId = windowPowerSaveBlockers.get(windowId)!;
|
||||||
|
try {
|
||||||
|
powerSaveBlocker.stop(blockerId);
|
||||||
|
console.log(
|
||||||
|
`[Main] Stopped power save blocker ${blockerId} for closing window ${windowId}`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`[Main] Failed to stop power save blocker ${blockerId} for window ${windowId}:`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
windowPowerSaveBlockers.delete(windowId);
|
||||||
|
}
|
||||||
|
|
||||||
if (goosedProcess && typeof goosedProcess === 'object' && 'kill' in goosedProcess) {
|
if (goosedProcess && typeof goosedProcess === 'object' && 'kill' in goosedProcess) {
|
||||||
goosedProcess.kill();
|
goosedProcess.kill();
|
||||||
}
|
}
|
||||||
@@ -1220,10 +1237,22 @@ ipcMain.handle('set-wakelock', async (_event, enable: boolean) => {
|
|||||||
settings.enableWakelock = enable;
|
settings.enableWakelock = enable;
|
||||||
saveSettings(settings);
|
saveSettings(settings);
|
||||||
|
|
||||||
// Stop any existing power save blocker when disabling the setting
|
// Stop all existing power save blockers when disabling the setting
|
||||||
if (!enable && powerSaveBlockerId !== null) {
|
if (!enable) {
|
||||||
powerSaveBlocker.stop(powerSaveBlockerId);
|
for (const [windowId, blockerId] of windowPowerSaveBlockers.entries()) {
|
||||||
powerSaveBlockerId = null;
|
try {
|
||||||
|
powerSaveBlocker.stop(blockerId);
|
||||||
|
console.log(
|
||||||
|
`[Main] Stopped power save blocker ${blockerId} for window ${windowId} due to wakelock setting disabled`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`[Main] Failed to stop power save blocker ${blockerId} for window ${windowId}:`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
windowPowerSaveBlockers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2026,21 +2055,36 @@ app.whenReady().then(async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('start-power-save-blocker', () => {
|
ipcMain.handle('start-power-save-blocker', (event) => {
|
||||||
if (powerSaveBlockerId === null) {
|
const window = BrowserWindow.fromWebContents(event.sender);
|
||||||
powerSaveBlockerId = powerSaveBlocker.start('prevent-app-suspension');
|
const windowId = window?.id;
|
||||||
|
|
||||||
|
if (windowId && !windowPowerSaveBlockers.has(windowId)) {
|
||||||
|
const blockerId = powerSaveBlocker.start('prevent-app-suspension');
|
||||||
|
windowPowerSaveBlockers.set(windowId, blockerId);
|
||||||
|
console.log(`[Main] Started power save blocker ${blockerId} for window ${windowId}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (windowId && windowPowerSaveBlockers.has(windowId)) {
|
||||||
|
console.log(`[Main] Power save blocker already active for window ${windowId}`);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('stop-power-save-blocker', () => {
|
ipcMain.handle('stop-power-save-blocker', (event) => {
|
||||||
if (powerSaveBlockerId !== null) {
|
const window = BrowserWindow.fromWebContents(event.sender);
|
||||||
powerSaveBlocker.stop(powerSaveBlockerId);
|
const windowId = window?.id;
|
||||||
powerSaveBlockerId = null;
|
|
||||||
|
if (windowId && windowPowerSaveBlockers.has(windowId)) {
|
||||||
|
const blockerId = windowPowerSaveBlockers.get(windowId)!;
|
||||||
|
powerSaveBlocker.stop(blockerId);
|
||||||
|
windowPowerSaveBlockers.delete(windowId);
|
||||||
|
console.log(`[Main] Stopped power save blocker ${blockerId} for window ${windowId}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2153,11 +2197,24 @@ async function getAllowList(): Promise<string[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.on('will-quit', async () => {
|
app.on('will-quit', async () => {
|
||||||
|
for (const [windowId, blockerId] of windowPowerSaveBlockers.entries()) {
|
||||||
|
try {
|
||||||
|
powerSaveBlocker.stop(blockerId);
|
||||||
|
console.log(
|
||||||
|
`[Main] Stopped power save blocker ${blockerId} for window ${windowId} during app quit`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`[Main] Failed to stop power save blocker ${blockerId} for window ${windowId}:`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
windowPowerSaveBlockers.clear();
|
||||||
|
|
||||||
// Unregister all shortcuts when quitting
|
// Unregister all shortcuts when quitting
|
||||||
globalShortcut.unregisterAll();
|
globalShortcut.unregisterAll();
|
||||||
|
|
||||||
// Clean up the temp directory on app quit
|
|
||||||
console.log('[Main] App "will-quit". Cleaning up temporary image directory...');
|
|
||||||
try {
|
try {
|
||||||
await fs.access(gooseTempDir); // Check if directory exists to avoid error on fs.rm if it doesn't
|
await fs.access(gooseTempDir); // Check if directory exists to avoid error on fs.rm if it doesn't
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user