fix: sessionId durchreichen bei target_tab/sync/risk_request
Ereignisse ohne sessionId passierten den Panel-Filter ungehindert, wodurch ein frisch geoeffneter Chat den Arbeits-Tab oder Verlauf eines parallel laufenden Chats angezeigt bekam.
This commit is contained in:
+39
-22
@@ -386,15 +386,19 @@ function reportToolDone(
|
||||
}
|
||||
|
||||
/** Sendet den aktuellen Target-Tab ans Panel und überträgt den Glow auf den neuen Tab. */
|
||||
async function notifyTargetTab(): Promise<void> {
|
||||
const targetTabId = getTargetTabId();
|
||||
async function notifyTargetTab(sessionId?: string): Promise<void> {
|
||||
// sessionId mitstempeln: ohne sie zeigte ein frisch geöffneter Chat den
|
||||
// Arbeits-Tab eines ANDEREN, parallel laufenden Chats an — Ereignisse ohne
|
||||
// sessionId passieren den Filter im Panel ungehindert.
|
||||
const sid = sessionId ?? activeSessionId;
|
||||
const targetTabId = getTargetTabId(sid);
|
||||
if (targetTabId === null) {
|
||||
sendToPanel({ type: 'target_tab', tabId: null });
|
||||
sendToPanel({ type: 'target_tab', tabId: null, sessionId: sid });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const tab = await chrome.tabs.get(targetTabId);
|
||||
sendToPanel({ type: 'target_tab', tabId: targetTabId, title: tab.title, url: tab.url });
|
||||
sendToPanel({ type: 'target_tab', tabId: targetTabId, title: tab.title, url: tab.url, sessionId: sid });
|
||||
// Nur während eines echten Laufs anzeigen.
|
||||
if (agentRunActive) notifyGlow(true);
|
||||
// Tab in den Vordergrund bringen wenn focusWorkingTab aktiv
|
||||
@@ -403,7 +407,7 @@ async function notifyTargetTab(): Promise<void> {
|
||||
await chrome.tabs.update(targetTabId, { active: true }).catch(() => {});
|
||||
}
|
||||
} catch {
|
||||
sendToPanel({ type: 'target_tab', tabId: null });
|
||||
sendToPanel({ type: 'target_tab', tabId: null, sessionId: sid });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,7 +438,7 @@ async function runTool(name: string, input: Record<string, unknown>, sessionId?:
|
||||
}
|
||||
|
||||
const tabId = await currentTabId(sessionId);
|
||||
const { allowed, verdict } = await gate(tabId, name, input, (v) => askUser(v, name));
|
||||
const { allowed, verdict } = await gate(tabId, name, input, (v) => askUser(v, name, sessionId));
|
||||
|
||||
if (!allowed) {
|
||||
return {
|
||||
@@ -464,11 +468,14 @@ async function runTool(name: string, input: Record<string, unknown>, sessionId?:
|
||||
}
|
||||
|
||||
/** Fragt den Nutzer. Ohne offenes Panel wird gehandelt — Autonomie hat Vorrang. */
|
||||
function askUser(verdict: RiskVerdict, toolName: string): Promise<boolean> {
|
||||
function askUser(verdict: RiskVerdict, toolName: string, sessionId?: string): Promise<boolean> {
|
||||
if (!panelPort) return Promise.resolve(true);
|
||||
|
||||
const requestId = crypto.randomUUID();
|
||||
sendToPanel({ type: 'risk_request', requestId, name: toolName, verdict, timeoutMs: RISK_TIMEOUT_MS });
|
||||
sendToPanel({
|
||||
type: 'risk_request', requestId, name: toolName, verdict,
|
||||
timeoutMs: RISK_TIMEOUT_MS, sessionId: sessionId ?? activeSessionId,
|
||||
});
|
||||
|
||||
return new Promise<boolean>((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
@@ -505,7 +512,7 @@ async function getActiveTab(sessionId?: string): Promise<chrome.tabs.Tab> {
|
||||
const [candidate] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
if (candidate?.id != null && await tabOwner(candidate.id, sessionId) === 'own') {
|
||||
setTargetTabId(candidate.id, sessionId);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return candidate;
|
||||
}
|
||||
|
||||
@@ -516,14 +523,14 @@ async function getActiveTab(sessionId?: string): Promise<chrome.tabs.Tab> {
|
||||
if (!hasOwnGroup && candidate?.id != null
|
||||
&& await tabOwner(candidate.id, sessionId) === 'user') {
|
||||
setTargetTabId(candidate.id, sessionId);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return candidate;
|
||||
}
|
||||
|
||||
const fresh = await chrome.tabs.create({ url: 'about:blank', active: false });
|
||||
if (!fresh.id) throw new ToolError('NO_ACTIVE_TAB', 'Kein Tab verfügbar', false);
|
||||
setTargetTabId(fresh.id, sessionId);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return fresh;
|
||||
}
|
||||
|
||||
@@ -970,11 +977,11 @@ async function dispatchTool(name: string, input: Record<string, unknown>, sessio
|
||||
if (input.newTab) {
|
||||
const newTab = await chrome.tabs.create({ url, active: false });
|
||||
setTargetTabId(newTab.id!);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return { tabId: newTab.id, url, loading: true, hint: 'Seite lädt — browser_wait oder screenshot nach kurzer Pause.', _method: 'synthetic' };
|
||||
}
|
||||
await chrome.tabs.update(tabId!, { url });
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return { tabId, url, loading: true, hint: 'Seite lädt — browser_wait oder screenshot nach kurzer Pause.', _method: 'synthetic' };
|
||||
}
|
||||
|
||||
@@ -1019,7 +1026,7 @@ async function dispatchTool(name: string, input: Record<string, unknown>, sessio
|
||||
// sessionId mitgeben: sonst landet der neue Tab in der Gruppe der gerade
|
||||
// SICHTBAREN Konversation statt in der des aufrufenden Chats.
|
||||
setTargetTabId(newTab.id!, sessionId);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return { tabId: newTab.id, url, redirectedFrom: url !== requestedUrl ? requestedUrl : undefined, _method: 'synthetic' };
|
||||
}
|
||||
|
||||
@@ -1037,7 +1044,7 @@ async function dispatchTool(name: string, input: Record<string, unknown>, sessio
|
||||
await chrome.windows.update(t.windowId!, { focused: true });
|
||||
}
|
||||
setTargetTabId(tid, sessionId);
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sessionId);
|
||||
return { ok: true, tabId: tid, _method: 'synthetic' };
|
||||
}
|
||||
|
||||
@@ -1912,7 +1919,7 @@ chrome.runtime.onConnect.addListener((port) => {
|
||||
} else {
|
||||
// Der Broker-Kanal kennt keine Bilder — lieber sagen als still schlucken.
|
||||
if (msg.images?.length) {
|
||||
sendToPanel({ type: 'log', level: 'warn',
|
||||
sendToPanel({ type: 'log', level: 'warn', sessionId,
|
||||
text: `${msg.images.length} Bild(er) ignoriert: Bildanhänge gehen nur im Antrieb "direct".` });
|
||||
}
|
||||
// Aktuelle Tab-URL mitschicken — der Broker baut daraus den Kontext (z.B. Mercedes-Wissen).
|
||||
@@ -1929,12 +1936,22 @@ chrome.runtime.onConnect.addListener((port) => {
|
||||
}
|
||||
case 'sync': {
|
||||
// Nachliefern statt neu erzeugen: der Puffer ist die Wahrheit.
|
||||
// ABER nur die Ereignisse DIESER Konversation: der Puffer ist global,
|
||||
// ein frisch geöffneter Chat bekam sonst den kompletten Verlauf aller
|
||||
// parallel laufenden Chats nachgespielt ("es fühlt sich wie eine an").
|
||||
// Ereignisse ohne sessionId sind global (connection_status u.ä.) und
|
||||
// bleiben drin.
|
||||
const from = typeof msg.from === 'number' ? msg.from : 0;
|
||||
const missed = eventBuffer.filter(e => e.seq > from);
|
||||
const sid = (msg as any).sessionId || activeSessionId;
|
||||
const missed = eventBuffer.filter(e => {
|
||||
if (e.seq <= from) return false;
|
||||
const evSid = (e.msg as any).sessionId;
|
||||
return !evSid || evSid === sid;
|
||||
});
|
||||
if (panelPort) {
|
||||
try {
|
||||
panelPort.postMessage({
|
||||
type: 'sync_start', count: missed.length, running: isAgentRunning(),
|
||||
type: 'sync_start', count: missed.length, running: isAgentRunning(sid),
|
||||
latest: eventSeq, startedAt: runStartedAt || undefined,
|
||||
});
|
||||
// Direkt posten, nicht ueber sendToPanel — sonst landet alles erneut im Puffer.
|
||||
@@ -1962,17 +1979,17 @@ chrome.runtime.onConnect.addListener((port) => {
|
||||
case 'set_config': {
|
||||
const next = await patchConfig(msg.patch);
|
||||
if (msg.patch.brokerUrl) { ws?.close(); setTimeout(connect, 300); }
|
||||
sendToPanel({ type: 'state', config: next, connected: ws?.readyState === WebSocket.OPEN, running: isAgentRunning(), version: EXTENSION_VERSION, runningSessions: getRunningSessions() });
|
||||
sendToPanel({ type: 'state', config: next, connected: ws?.readyState === WebSocket.OPEN, running: isAgentRunning(activeSessionId), version: EXTENSION_VERSION, sessionId: activeSessionId, runningSessions: getRunningSessions() });
|
||||
break;
|
||||
}
|
||||
case 'get_state': {
|
||||
const cfg = await loadConfig();
|
||||
sendToPanel({ type: 'state', config: cfg, connected: ws?.readyState === WebSocket.OPEN, running: isAgentRunning(), version: EXTENSION_VERSION, runningSessions: getRunningSessions() });
|
||||
sendToPanel({ type: 'state', config: cfg, connected: ws?.readyState === WebSocket.OPEN, running: isAgentRunning(activeSessionId), version: EXTENSION_VERSION, sessionId: activeSessionId, runningSessions: getRunningSessions() });
|
||||
break;
|
||||
}
|
||||
case 'run_tool': {
|
||||
const callId = crypto.randomUUID();
|
||||
sendToPanel({ type: 'tool_executing', callId, name: msg.name, input: msg.input });
|
||||
sendToPanel({ type: 'tool_executing', callId, name: msg.name, input: msg.input, sessionId: activeSessionId });
|
||||
const started = performance.now();
|
||||
try {
|
||||
const result = await runTool(msg.name, msg.input);
|
||||
@@ -1996,7 +2013,7 @@ chrome.runtime.onConnect.addListener((port) => {
|
||||
const sid = (msg as any).sessionId;
|
||||
if (sid) {
|
||||
activeSessionId = sid;
|
||||
notifyTargetTab();
|
||||
notifyTargetTab(sid);
|
||||
sendToPanel({
|
||||
type: 'state',
|
||||
config: await loadConfig(),
|
||||
|
||||
@@ -212,7 +212,7 @@ function openPort(): void {
|
||||
}
|
||||
port = p;
|
||||
// Alles nachfordern, was waehrend geschlossenem Panel aufgelaufen ist.
|
||||
try { p.postMessage({ type: 'sync', from: lastSeq }); } catch { /* Reconnect greift */ }
|
||||
try { p.postMessage({ type: 'sync', from: lastSeq, sessionId: activeConvId }); } catch { /* Reconnect greift */ }
|
||||
|
||||
p.onMessage.addListener((msg) => {
|
||||
// Sequenznummer merken: nach einem Abriss wird genau ab hier nachgeliefert.
|
||||
@@ -2263,7 +2263,7 @@ function showRunningBanner(startedAt?: number): void {
|
||||
bar.remove();
|
||||
// Alles ab Null nachfordern: der Puffer im Worker hat den vollen Lauf.
|
||||
lastSeq = 0;
|
||||
try { port?.postMessage({ type: 'sync', from: 0 }); } catch { /* egal */ }
|
||||
try { port?.postMessage({ type: 'sync', from: 0, sessionId: activeConvId }); } catch { /* egal */ }
|
||||
});
|
||||
bar.append(btn);
|
||||
appendToChat(bar);
|
||||
|
||||
Reference in New Issue
Block a user