fix: check window focus before summarization to avoid wasted Zen API calls
When notificationMode is 'hidden-only', the isWindowFocused check now happens before summarization and template resolution, not after. This prevents costly Zen API calls for notifications that would be skipped anyway, and eliminates stale notifications arriving after the user has already read the response and switched away.
This commit is contained in:
@@ -785,6 +785,7 @@ const spawnLocalServer = async () => {
|
||||
attachSignals: false,
|
||||
exitOnShutdown: false,
|
||||
onDesktopNotification: (payload) => maybeShowNativeNotification(payload),
|
||||
getIsWindowFocused: isAnyWindowFocused,
|
||||
});
|
||||
|
||||
const port = handle.getPort();
|
||||
|
||||
@@ -1073,6 +1073,9 @@ async function main(options = {}) {
|
||||
if (typeof options.onDesktopNotification === 'function') {
|
||||
notificationEmitterRuntime.setOnDesktopNotification(options.onDesktopNotification);
|
||||
}
|
||||
if (typeof options.getIsWindowFocused === 'function') {
|
||||
notificationTriggerRuntime.setGetIsWindowFocused(options.getIsWindowFocused);
|
||||
}
|
||||
|
||||
console.log(`Starting OpenChamber on port ${port === 0 ? 'auto' : port}`);
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
getOpenCodeAuthHeaders,
|
||||
} = deps;
|
||||
|
||||
let getIsWindowFocused = typeof deps.getIsWindowFocused === 'function'
|
||||
? deps.getIsWindowFocused
|
||||
: null;
|
||||
|
||||
const setGetIsWindowFocused = (cb) => {
|
||||
getIsWindowFocused = typeof cb === 'function' ? cb : null;
|
||||
};
|
||||
|
||||
const PUSH_READY_COOLDOWN_MS = 5000;
|
||||
const PUSH_QUESTION_DEBOUNCE_MS = 500;
|
||||
const PUSH_PERMISSION_DEBOUNCE_MS = 500;
|
||||
@@ -211,6 +219,10 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.notificationMode !== 'always' && getIsWindowFocused?.()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const lastAt = lastReadyNotificationAt.get(sessionId) ?? 0;
|
||||
if (now - lastAt < PUSH_READY_COOLDOWN_MS) {
|
||||
@@ -283,6 +295,10 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
const settings = await readSettingsFromDisk();
|
||||
if (settings.notifyOnError === false) return;
|
||||
|
||||
if (settings.notificationMode !== 'always' && getIsWindowFocused?.()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let title = 'Tool error';
|
||||
let body = 'An error occurred';
|
||||
|
||||
@@ -355,6 +371,10 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.notificationMode !== 'always' && getIsWindowFocused?.()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstQuestion = payload.properties?.questions?.[0];
|
||||
const header = typeof firstQuestion?.header === 'string' ? firstQuestion.header.trim() : '';
|
||||
const questionText = typeof firstQuestion?.question === 'string' ? firstQuestion.question.trim() : '';
|
||||
@@ -473,6 +493,10 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.notificationMode !== 'always' && getIsWindowFocused?.()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sessionTitle = payload.properties?.sessionTitle;
|
||||
const permissionText = typeof permission === 'string' && permission.length > 0 ? permission : '';
|
||||
const fallbackMessage = typeof sessionTitle === 'string' && sessionTitle.trim().length > 0
|
||||
@@ -543,5 +567,6 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
return {
|
||||
maybeSendPushForTrigger,
|
||||
setAutoAcceptSession,
|
||||
setGetIsWindowFocused,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user