Ereignisse landeten im falschen Chat: der Broker markiert jedes Ereignis mit
chatId, das Panel filtert aber auf sessionId — handleBrokerMessage reichte die
Nachricht unverändert weiter, der Filter griff also nie und alles landete im
gerade sichtbaren Chat. chatId wird jetzt beim Weiterreichen übersetzt.
Tab-Isolation war reine Optik — die Gruppen wurden nirgends durchgesetzt:
- getActiveTab() nahm sich den gerade sichtbaren Tab (auch den eines anderen
Chats oder einen losen Tab des Nutzers) und zog ihn in die eigene Gruppe.
Fremde Tabs werden jetzt nie adoptiert; der Chat öffnet sich einen eigenen.
- browser_tabs_create legte den neuen Tab in die Gruppe der SICHTBAREN statt
der aufrufenden Konversation (sessionId fehlte).
- browser_tabs_select/close prüften den Besitz gar nicht — der Agent konnte
jeden Tab übernehmen oder schließen, auch die des Nutzers.
- browser_tabs_list zeigte jeden offenen Tab; Tabs anderer Chats sind jetzt
unsichtbar, Nutzer-Tabs klar als "nicht anfassen" markiert.
Besitz wird über Chromes Tab-Gruppen bestimmt — überlebt einen Neustart des
Service Workers, anders als reiner Speicher.
Session wird explizit durch runTool/dispatchTool/getActiveTab gereicht. Der
bisherige Trick, activeSessionId kurz umzubiegen, hielt nur ohne Parallelität:
zwischen Setzen und Zurücksetzen liegt ein await.
Einstellungen und Verlauf nehmen dem Chat keinen Platz mehr weg: Einstellungen
sind eine eigene Seite (vorher ausklappbar bis 45vh), der Verlauf ein Overlay
über dem Header-Knopf. Abschnitte als eigene Module mit Icon und Akzentkante.
Nebenbei repariert: nach der Umbenennung .settings -> .settings-panel zeigten
mehrere Regeln ins Leere.
Kimi K2.5, GLM-5 und Gemini 3.1 Flash Lite im Nexus-Katalog; Kimi/GLM laufen
über /moonshot bzw. /zai statt über den Azure-Deployment-Pfad. Ollama als
lokaler Anbieter wählbar (kein Key nötig).
Enthält außerdem ältere, noch nicht committete Arbeit, die nicht von diesem
Durchgang stammt und sich nicht sauber abtrennen ließ: kräftigerer Glow mit
Farbverlauf (spotlight.ts), Raster-Overlay für Screenshots (computer.ts) und
ein Ein/Aus-Schalter für CDP (cdp.ts).
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
- MERCEDES_CONTEXT komplett neu: explizite Regel 'Social Intranet ist
immer der erste Anlaufpunkt' ganz oben, vor allem anderen.
- Vorgehen bei unbekannten Abkürzungen (AFM, CBS, ESS, ...): erst
Intranet-Suche, dann lesen, dann erklären — nicht googeln, nicht raten.
- Struktur: klare Abschnitte statt Fließtext-Wurst.
- handleBrokerMessage: 'round' schaltet notifyGlow(true), 'done'/'error'
schalten notifyGlow(false). Vorher wurde Glow nur im direct-Modus
(agent.ts) gesteuert — im Broker-Modus blieb er immer aus.
- ExtUserMessage: url?-Feld ergänzt.
- user_message an Broker: aktuelle Tab-URL wird mitgeschickt, damit
der Broker kontextspezifische Prompts einbauen kann.
- browser_computer left_click: afterState (url, urlChanged, readyState,
activeTag, activeLabel, dialogText) direkt im Ergebnis — kein sleep,
kein Polling, kein Blockieren.
- browser_computer screenshot: page (url, title, readyState, activeTag)
im Ergebnis — ein einziger evaluateInMainWorld-Call.
- browser_click (semantisch): snapshotAfterClick() nach Klick — gleiche
Felder, gleiche Logik, kein extra Warten.
- browser_navigate: gibt loading:true + hint zurück statt zu blockieren.
Die KI entscheidet selbst ob sie wartet.
- Keine adaptive Pace, kein waitForTabLoad, kein Polling — das war der
Grund warum alles eingefroren ist.
Split out of the agent repository into its own project. The two commits
that introduced and reworked the extension are preserved.
The extension could not build on its own: prebuild called
`python ../../tools/generate_tool_defs.py`, and the 31 tool schemas lived
outside the tree — in a directory that was under no version control at all.
- tools/schema/*.json and tools/generate_tool_defs.py now live here. They
describe browser tools, so they belong with the extension.
- The generator writes TypeScript into this repo and, when the agent repo is
checked out next to it, the Python tool definitions there as well. The
presence check looks for agent/tools.py: checking only for the directory
was useless — it is almost always true, and the generator then wrote into an
arbitrary neighbouring folder (verified, then fixed).
- Added .gitignore: dist/, node_modules/, and *.token — the MCP bridge token
is a runtime secret.
Verified: `npm run build` from a clean checkout with and without the agent
repo present; tsc reports no errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The settings were 18 rows on one level: the broker URL, the pace in
milliseconds and the model all shouted equally loud, although one is set
once and the other is changed daily.
- Model picker moved into the header. It is the switch you touch every day
and it sat at the end of the settings list. Source depends on driveMode:
the verified gateway models in direct mode, the broker's list otherwise;
hidden when there is nothing to choose.
- Settings grouped into five collapsible sections (Verbindung & Antrieb,
Verhalten, Anzeige & Sicherheit, Modell & Zugang, Memory). Only "Modell &
Zugang" starts open — that is what first-time setup needs.
- Existing rows were wrapped in place, not moved, so every element id and
every binding stays intact.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nexus gateway (measured 2026-08-07, not assumed):
- Gemini speaks Google-GenAI (/v1beta/models/{id}:streamGenerateContent, header
api-key), NOT the Azure-OpenAI path — that returned 404 "no Route matched" and
was the cause of the reported failures. New agent/gemini_bridge.py translates
Bedrock Converse <-> Gemini in both directions.
- Only gemini-3.6-flash is subscribed; 2.5-flash/2.5-pro/3.1-flash-lite give 403,
every other name 404. Catalog corrected.
- Four Gemini rules, each previously an HTTP 400, now covered by tests:
thought signatures are mandatory, they belong to the TURN (not the individual
call), functionResponse turns must be homogeneous, arrays need `items`.
- Prompt caching is NOT available: cachePoint is accepted and ignored.
System prompt:
- Was an f-string; a code sample containing braces broke build_system_prompt at
request time (CLI and web both 500, import stayed green). Now a plain template
with __TOKEN__ placeholders. Regression guards in tests/test_system_prompt.py.
CLI:
- `agent resume` now prints the stored transcript. The history was always loaded
into the model context, only the terminal stayed empty.
Memory (new, all three surfaces):
- agent/memory.py stores notes about the user in one local file, written
atomically; memory.cnull.net remains an optional mirror that can never fail a
write. Tools memory_save/search/forget, injected into the prompt with a budget.
HTTP surface /api/memory for the extension.
Browser extension (agent/extension, first commit of the source):
- driveMode 'direct' talks to Nexus without the Python broker: Claude via
Bedrock converse, GPT via Azure-OpenAI, Gemini via Google-GenAI.
- browser_type no longer guesses the focused element — that wrote whole mails
into Outlook's subject line. Read-back now reports where the text actually
landed, so a mis-target is visible instead of silent.
- aria-labelledby is resolved across all ids (it is a list); contenteditable is
interactive and marked editable. Without this, subject and message body look
identical to the model.
- Hard block against sending mail, independent of riskMode.
- Runs survive the panel: events are buffered and replayed by sequence number.
- Image input (paste, file, drag&drop), on-page glow/spotlight, memory tools.
Cost: fixed tokens per round 11434 -> 6540 (-43%) by trimming tool schemas,
dropping gateway docs from the browser prompt and sending site knowledge only
where it applies.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>