fix: Glow-Bug + focusWorkingTab-Option
Glow-Fix (3 Ursachen behoben): - notifyGlow: schickt jetzt an targetTabId statt an den aktiven Tab des Nutzers. Vorher: Agent arbeitet in Tab B, Glow geht an Tab A (den der Nutzer gerade sieht) — Tab B leuchtet nie. - executeForBroker: notifyGlow(true) beim ersten Tool-Call, nicht erst bei 'round'. Vorher: targetTabId war bei 'round' noch null, currentTabId() gab undefined zurück, Glow wurde nie gesendet. - notifyTargetTab: Glow auf neuen Tab übertragen wenn Agent Tab wechselt. focusWorkingTab (neue Config-Option): - ExtensionConfig.focusWorkingTab: boolean (Default false) - notifyTargetTab: bringt Tab in Vordergrund wenn focusWorkingTab=true - Checkbox 'Tab live mitverfolgen' in Einstellungen > Anzeige & Sicherheit - false = Agent arbeitet im Hintergrund (bisheriges Verhalten) - true = Tab wird bei jedem Wechsel sichtbar
This commit is contained in:
+16
-2
@@ -183,6 +183,10 @@ async function executeForBroker(callId: string, name: string, input: Record<stri
|
||||
const start = performance.now();
|
||||
let method: InteractionMethod = 'synthetic';
|
||||
|
||||
// Glow beim ersten Tool-Call einschalten — zu diesem Zeitpunkt ist targetTabId
|
||||
// noch null (wird erst in getActiveTab gesetzt), daher aktiven Tab nehmen.
|
||||
notifyGlow(true);
|
||||
|
||||
try {
|
||||
sendToPanel({ type: 'tool_executing', callId, name, input });
|
||||
const result = await runTool(name, input);
|
||||
@@ -214,7 +218,7 @@ function reportToolDone(
|
||||
sendToPanel({ type: 'tool_done', callId, name, result, error, durationMs, method });
|
||||
}
|
||||
|
||||
/** Sendet den aktuellen Target-Tab ans Panel. */
|
||||
/** Sendet den aktuellen Target-Tab ans Panel und überträgt den Glow auf den neuen Tab. */
|
||||
async function notifyTargetTab(): Promise<void> {
|
||||
if (targetTabId === null) {
|
||||
sendToPanel({ type: 'target_tab', tabId: null });
|
||||
@@ -223,6 +227,13 @@ async function notifyTargetTab(): Promise<void> {
|
||||
try {
|
||||
const tab = await chrome.tabs.get(targetTabId);
|
||||
sendToPanel({ type: 'target_tab', tabId: targetTabId, title: tab.title, url: tab.url });
|
||||
// Glow auf den neuen Arbeits-Tab übertragen (falls Agent gerade läuft)
|
||||
notifyGlow(true);
|
||||
// Tab in den Vordergrund bringen wenn focusWorkingTab aktiv
|
||||
const cfg = await loadConfig();
|
||||
if (cfg.focusWorkingTab) {
|
||||
await chrome.tabs.update(targetTabId, { active: true }).catch(() => {});
|
||||
}
|
||||
} catch {
|
||||
sendToPanel({ type: 'target_tab', tabId: null });
|
||||
}
|
||||
@@ -724,7 +735,10 @@ function notifyCursor(tabId: number, x: number, y: number, click?: 'left' | 'rig
|
||||
async function notifyGlow(on: boolean): Promise<void> {
|
||||
const cfg = await loadConfig();
|
||||
if (cfg.pageOverlay !== 'glow' && cfg.pageOverlay !== 'both') return;
|
||||
const id = await currentTabId().catch(() => undefined);
|
||||
|
||||
// Glow an den Arbeits-Tab schicken, nicht an den aktiven Tab des Nutzers.
|
||||
// targetTabId ist null wenn noch kein Tool gelaufen ist — dann aktiven Tab nehmen.
|
||||
const id = targetTabId ?? await currentTabId().catch(() => undefined);
|
||||
if (typeof id !== 'number') return;
|
||||
chrome.tabs.sendMessage(id, { type: 'NEXUS_GLOW', on }).catch(() => {});
|
||||
}
|
||||
|
||||
@@ -159,6 +159,13 @@ export interface ExtensionConfig {
|
||||
* zurückholen. Dieser Riegel greift unabhängig vom Risikomodus.
|
||||
*/
|
||||
blockMailSend: boolean;
|
||||
|
||||
/**
|
||||
* Arbeits-Tab in den Vordergrund bringen wenn der Agent ihn wechselt.
|
||||
* false (Standard) = Agent arbeitet im Hintergrund, Nutzer kann anderen Tab nutzen.
|
||||
* true = Tab wird bei jedem Wechsel sichtbar — gut zum Live-Zuschauen.
|
||||
*/
|
||||
focusWorkingTab: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_SYSTEM_PROMPT = `Du steuerst einen echten Browser wie ein Mensch: mit Mauszeiger und Tastatur.
|
||||
@@ -328,6 +335,7 @@ export const DEFAULT_CONFIG: ExtensionConfig = {
|
||||
memoryToken: '',
|
||||
memoryEnabled: false,
|
||||
blockMailSend: true,
|
||||
focusWorkingTab: false,
|
||||
};
|
||||
|
||||
const STORAGE_KEY = 'nexus_ext_config';
|
||||
|
||||
@@ -88,6 +88,7 @@ const paceMsInput = need<HTMLInputElement>('paceMs');
|
||||
const showCursorInput = need<HTMLInputElement>('showCursor');
|
||||
const pageOverlaySelect = need<HTMLSelectElement>('pageOverlay');
|
||||
const blockMailSendInput = need<HTMLInputElement>('blockMailSend');
|
||||
const focusWorkingTabInput = need<HTMLInputElement>('focusWorkingTab');
|
||||
const providerSelect = need<HTMLSelectElement>('provider');
|
||||
const baseUrlInput = need<HTMLInputElement>('baseUrl');
|
||||
const apiKeyInput = need<HTMLInputElement>('apiKey');
|
||||
@@ -379,6 +380,7 @@ function applyConfigToFields(cfg: ExtensionConfig): void {
|
||||
setFieldValue(paceMsInput, String(cfg.paceMs));
|
||||
if (document.activeElement !== showCursorInput) showCursorInput.checked = cfg.showCursor;
|
||||
if (document.activeElement !== blockMailSendInput) blockMailSendInput.checked = cfg.blockMailSend;
|
||||
if (document.activeElement !== focusWorkingTabInput) focusWorkingTabInput.checked = cfg.focusWorkingTab ?? false;
|
||||
|
||||
setFieldValue(providerSelect, cfg.provider);
|
||||
setFieldValue(baseUrlInput, cfg.baseUrl);
|
||||
@@ -685,6 +687,10 @@ function wireSettings(): void {
|
||||
patchConfigValue({ showCursor: showCursorInput.checked });
|
||||
});
|
||||
|
||||
focusWorkingTabInput.addEventListener('change', () => {
|
||||
patchConfigValue({ focusWorkingTab: focusWorkingTabInput.checked });
|
||||
});
|
||||
|
||||
blockMailSendInput.addEventListener('change', () => {
|
||||
patchConfigValue({ blockMailSend: blockMailSendInput.checked });
|
||||
if (!blockMailSendInput.checked) {
|
||||
|
||||
@@ -1099,6 +1099,10 @@
|
||||
<input type="checkbox" id="showCursor">
|
||||
<label for="showCursor">Mauszeiger sichtbar einblenden</label>
|
||||
</div>
|
||||
<div class="row check">
|
||||
<input type="checkbox" id="focusWorkingTab">
|
||||
<label for="focusWorkingTab" title="Tab bei jedem Wechsel in den Vordergrund bringen — gut zum Live-Zuschauen. Aus = Agent arbeitet im Hintergrund.">Tab live mitverfolgen (Vordergrund)</label>
|
||||
</div>
|
||||
<div class="row check">
|
||||
<input type="checkbox" id="blockMailSend">
|
||||
<label for="blockMailSend" title="Klicks auf Senden-Schaltflächen in Mail-Oberflächen werden abgelehnt. Der Agent legt nur Entwürfe an.">Senden in Mails blockieren (nur Entwürfe)</label>
|
||||
|
||||
Reference in New Issue
Block a user