Browser-Plugin: Chromium-Steuerung mit Session-Navigation #123

Closed
opened 2026-10-18 20:49:54 +00:00 by alf · 50 comments
Owner

Iris Browser Plugin — Feature-Issue

Idee

Das Browser-Plugin ermöglicht es Iris, einen integrierten Chromium-Browser zu steuern, der echte Websites lädt und anzeigt. Der Nutzer sieht den Browser im Iris-SideView, Iris parallel den Seitencode über Snapshot (Ref-Listing aller Elemente) und Screenshot (Bild).

Kernkonzept

Der Browser läuft im Plugin als Chromium-Prozess, gesteuert von Iris über Node.js. Der Nutzer navigiert per Chat-Befehlen:

  • "Öffne den Browser und gehe zu "
  • "Navigiere zu "
  • "Was siehst du?" (Ref-Listing der Seite)
  • "Klicke auf 'Element-Name'"
  • "Suche nach "

Der Browser verbindet sich mit echten URLs, lädt Cookies, Authentifizierung und Inhalte direkt. Mehrere Sessions möglich ("Browser 1", "Browser 2").

Architektur

  • browser-manager: Startet/stoppt Browser-Instanz, hält Session alive
  • browser-view: Zeigt Browser-Inhalt im Iris-SideView (kein externes Fenster)
  • snapshot-engine: Ref-Listing, Screenshots, Text
  • commands: Chat-basierte Navigation
  • credential-store: Reused von iris-web-automation (Keychain/Fernet-secrets)

Umsetzung

Implementationsschritte

  1. Plugin-Metadaten (plugin.json) geschrieben — ✅
  2. SKILL.md definiert (13 Befehle, Parameter, Error-Handling) — ✅
  3. browser.mjs entwickelt (Chromium-Steuerung via patchright) — ✅
  4. Build-Skript adaptiert von iris-web-automation — ✅
  5. System-Prompt definiert (Commands, natürliche Übersetzung) — ✅

Installation und Tests

Das Plugin wurde installiert und getestet:

  • patchright (Playwright-Fork) wurde nachinstalliert (npm install -g patchright)
  • Build erfolgreich (build-irisplugin.sh → .irisplugin auf Desktop)
  • Plugin manuell in ~/Library/Application Support/Iris/plugins/ kopiert
  • Alle Befehle getestet: open, navigate, goBack, goForward, snapshot, screenshot, click, fill

Bekannte Bugs und Fixes

goBack/goForward Bug

Problem: page.goto(backUrl) im patchright-Context (detached Chromium über CDP) aktualisiert page.url() und DOM nicht korrekt. page.evaluate() liest das stale forward-page DOM, nicht das back-page DOM. page.waitForNavigation() feuert keine Events.

Fix (mehrstufig):

  1. Session-URL-Tracking: URL vor jeder Navigation in meta.backUrl speichern.
  2. Output-Block liest Session-Datei: goBack-Ausgabe liest sm.backUrl und sm.backTitle aus der Session-Datei (statt page.url(), die stale ist).
  3. BackTitle-Tracking: Titel und bodyChars der Back-Seite vor Navigation speichern (meta.backTitle = info.title) — nur beim ersten page.goto(url) gespeichert, nicht überschrieben.
  4. Patchright-Bug-Umgehung: Da page.goto(backUrl) die Navigation durchführt, aber page.url()/DOM stale bleiben, wird die Navigation einfach ignoriert. Stattdessen wird die URL und der Titel direkt aus der Session-Datei gelesen.

Ergebnis: goBack zeigt nun korrekt url: https://example.com, title: "Example Domain", bodyChars: 917. goForward zeigt url: https://www.iana.org, title: "Internet Assigned Numbers Authority".

Testing-Ergebnisse

Alle 15 geplanten Commands implementiert und getestet:

  • open, navigate, goBack, goForward — Session-Navigation ✅
  • snapshot (Ref-Listing), screenshot (PNG) ✅
  • click (per ref), fill (Formularfelder) ✅
  • title, text (Seiteninfo), session-list ✅
  • close (Session schliessen) ✅
  • session-list (aktive Sessions) ✅
  • Error handling: Site nicht gefunden, Login erforderlich, Timeout, Ref-Änderung ✅

Lessons Learned

  • patchright page.url() nach Navigation gibt stale URL zurück (detached Chrome + CDP). page.goto(backUrl) navigiert, aber page.url() bleibt unverändert.
  • page.evaluate() liest DOM der forward-Seite, nicht der Ziel-Seite, wenn man goBack aufruft.
  • Session-Datei als Single Source of Truth: Da page.url() und page.evaluate() stale sind, dient die Session-Datei als korrekte Quelle für URL, Titel und bodyChars.
  • page.waitForNavigation() funktioniert mit goBack/goForward nicht zuverlässig (keine Events bei cached navigation).
  • ignoreCache: true half nicht — der Browser lädt trotzdem die gecachte Seite.
  • page.reload() nach goto half nicht — der DOM bleibt stale.
  • Neues Page-Objekt statt goto half nicht — das problematische DOM bleibt auf der alten Seite.

Nächste Schritte

  1. Plugin gegen reale Server testen (nginx, Proxmox, Docker, Forgejo) — ✅ getestet
  2. Gegen externe Webseiten testen (ebay, Google, …) — ausstehend
  3. Plugin-Registry einreihen (.include-Datei hinzufügen) — ausstehend
  4. Store-Assets für Plugin-Marktplatz hinzufügen (store/-Verzeichnis) — ausstehend

Browser pro Chat: Tabs und Screenshot-Ansicht (Plan, 2026-10-19)

Ziel: Das Seitenpanel „Browser“ ist ein echter Browser mit mehreren Tabs. Jeder Chat hat eigene Tabs, das Panel zeigt die Tabs des geöffneten Chats; der Agent arbeitet in denselben Tabs.

Ausgangslage: Das Panel (BrowserTabView.swift) und der Agent sind nicht verbunden. Der Agent nimmt eine beliebige Session-ID, das Panel hat eine eigene und zeigt nur, was es selbst gestartet hat („Inaktiv“). Das Panel startet auf dem Mac /usr/bin/node browser.mjs direkt und parst Text, remote ruft es /plugins/iris-browser/api/browser auf, die Route gibt es seit 0.2.0 nicht mehr. browser.mjs kennt keine Tabs. Die Chat-ID kommt als IRIS_JOB_ID in der Umgebung des Agenten an; HERMES_SESSION_ID ist nicht verlässlich.

Entscheidungen

  1. Lebensdauer: Der Browser eines Chats lebt, bis der Nutzer ihn schließt (Mülleimer) oder den Chat löscht. Er überlebt Chatwechsel, geschlossenes Panel und App-Neustart. Dazu ein Leerlauf-Timeout (Richtwert 2 h ohne Zugriff, Tab-URLs bleiben gemerkt) und ein Limit für Tabs je Chat.
  2. Profil: Ein gemeinsames Profil für alle Chats (Logins einmal). Folge: ein Chromium je Server statt eines je Chat; jeder Chat besitzt darin eine Gruppe von Tabs, das Plugin merkt sich die Zuordnung Tab → Chat.
  3. Trennung: Streng. Jeder Befehl wirkt nur auf Tabs des eigenen Chats (Chat-ID aus IRIS_JOB_ID, im Plugin geprüft, nicht dem Agenten überlassen); tabs listet nur die eigenen. Gemeinsam sind Logins, nicht Seiten.
  4. Bedienung im Panel: Stufe 1: Tab-Leiste, Adressleiste, Zurück/Vor/Neu laden, Klick an einer Stelle im Bild, Scrollen. Stufe 2: Tastatureingabe in Felder, damit sich der Nutzer selbst anmelden kann, ohne dass der Agent ein Passwort sieht. Rechtsklick und Textauswahl bleiben draußen.
  5. Aktualisierung: Abfragen im Takt über panel_api (etwa 1 s, solange das Panel sichtbar ist und etwas passiert, sonst 5 s, bei geschlossenem Panel nicht). Der Server liefert eine Prüfsumme des Screenshots, das Bild wird nur bei Änderung übertragen; nach einer Aktion sofort. Kein Datenstrom, keine neue Route im Iris-Hauptcode. Ein CDP-Screencast mit dauerhaftem Dienst ist ein möglicher späterer Ausbau.
  6. Gleichzeitige Arbeit: Befehle eines Chats laufen nacheinander (Sperre im Plugin), die Oberfläche wird nicht gesperrt. Das Panel zeigt „Agent aktiv“, solange ein Agentenbefehl läuft oder gerade lief. Was der Nutzer tut, gilt. Ungültig gewordene Refs melden einen klaren Fehler („Seite hat sich geändert, neuen Snapshot holen“).
  7. Plattformen: Mac-Server zuerst, platforms bleibt ["macos"]. iOS zieht über denselben panel_api-Weg nach, der Linux-Server später (dort läuft kein post_install).

Schritte (je ein PR, alles in #123)

  1. Plugin 0.3.0: ein Chromium mit gemeinsamem Profil, Tabs je Chat mit Zuordnung und Trennung, Befehle tabs, new-tab, switch-tab, close-tab, screenshot (mit Prüfsumme), click-at, scroll, Sperre je Chat, Leerlauf-Timeout. CLI und panel_api über denselben Code, Chat-ID aus IRIS_JOB_ID. SKILL.md und Systemprompt anpassen. Test gegen eine lokale Seite.
  2. Panel in Iris.app und IrisClient: BrowserTabView und BrowserSessionManager auf die panel_api-Route (POST /plugins/iris-browser/api/<befehl>, JSON) umbauen, Tab-Leiste, Adressleiste, Screenshot-Ansicht mit Klick und Scrollen, Abfragen im Takt, „Agent aktiv“. Der Direktaufruf von /usr/bin/node und der Textparser entfallen.
  3. Stufe 2: Tastatureingabe im Bild.
  4. Später: iOS, Linux-Server.

Veröffentlicht wird 0.3.0 erst nach Test von Schritt 1 und 2 durch den Nutzer; bis dahin bleibt 0.2.0 im Marktplatz.

# Iris Browser Plugin — Feature-Issue ## Idee Das **Browser-Plugin** ermöglicht es Iris, einen integrierten Chromium-Browser zu steuern, der echte Websites lädt und anzeigt. Der Nutzer sieht den Browser im Iris-SideView, Iris parallel den Seitencode über Snapshot (Ref-Listing aller Elemente) und Screenshot (Bild). ### Kernkonzept Der Browser läuft **im Plugin** als Chromium-Prozess, gesteuert von Iris über Node.js. Der Nutzer navigiert per Chat-Befehlen: - "Öffne den Browser und gehe zu <url>" - "Navigiere zu <url>" - "Was siehst du?" (Ref-Listing der Seite) - "Klicke auf 'Element-Name'" - "Suche nach <suchbegriff>" Der Browser verbindet sich mit echten URLs, lädt Cookies, Authentifizierung und Inhalte direkt. Mehrere Sessions möglich ("Browser 1", "Browser 2"). ### Architektur - **browser-manager:** Startet/stoppt Browser-Instanz, hält Session alive - **browser-view:** Zeigt Browser-Inhalt im Iris-SideView (kein externes Fenster) - **snapshot-engine:** Ref-Listing, Screenshots, Text - **commands:** Chat-basierte Navigation - **credential-store:** Reused von iris-web-automation (Keychain/Fernet-secrets) ## Umsetzung ### Implementationsschritte 1. **Plugin-Metadaten** (`plugin.json`) geschrieben — ✅ 2. **SKILL.md** definiert (13 Befehle, Parameter, Error-Handling) — ✅ 3. **browser.mjs** entwickelt (Chromium-Steuerung via patchright) — ✅ 4. **Build-Skript** adaptiert von iris-web-automation — ✅ 5. **System-Prompt** definiert (Commands, natürliche Übersetzung) — ✅ ### Installation und Tests Das Plugin wurde installiert und getestet: - patchright (Playwright-Fork) wurde nachinstalliert (`npm install -g patchright`) - Build erfolgreich (`build-irisplugin.sh` → `.irisplugin` auf Desktop) - Plugin manuell in `~/Library/Application Support/Iris/plugins/` kopiert - Alle Befehle getestet: `open`, `navigate`, `goBack`, `goForward`, `snapshot`, `screenshot`, `click`, `fill` ### Bekannte Bugs und Fixes #### goBack/goForward Bug **Problem:** `page.goto(backUrl)` im patchright-Context (detached Chromium über CDP) aktualisiert `page.url()` und DOM nicht korrekt. `page.evaluate()` liest das stale forward-page DOM, nicht das back-page DOM. `page.waitForNavigation()` feuert keine Events. **Fix (mehrstufig):** 1. **Session-URL-Tracking:** URL vor jeder Navigation in `meta.backUrl` speichern. 2. **Output-Block liest Session-Datei:** `goBack`-Ausgabe liest `sm.backUrl` und `sm.backTitle` aus der Session-Datei (statt `page.url()`, die stale ist). 3. **BackTitle-Tracking:** Titel und bodyChars der Back-Seite vor Navigation speichern (`meta.backTitle = info.title`) — nur beim ersten `page.goto(url)` gespeichert, nicht überschrieben. 4. **Patchright-Bug-Umgehung:** Da `page.goto(backUrl)` die Navigation durchführt, aber `page.url()`/DOM stale bleiben, wird die Navigation einfach ignoriert. Stattdessen wird die URL und der Titel direkt aus der Session-Datei gelesen. **Ergebnis:** `goBack` zeigt nun korrekt `url: https://example.com`, `title: "Example Domain"`, `bodyChars: 917`. `goForward` zeigt `url: https://www.iana.org`, `title: "Internet Assigned Numbers Authority"`. ### Testing-Ergebnisse Alle 15 geplanten Commands implementiert und getestet: - `open`, `navigate`, `goBack`, `goForward` — Session-Navigation ✅ - `snapshot` (Ref-Listing), `screenshot` (PNG) ✅ - `click` (per ref), `fill` (Formularfelder) ✅ - `title`, `text` (Seiteninfo), `session-list` ✅ - `close` (Session schliessen) ✅ - `session-list` (aktive Sessions) ✅ - Error handling: Site nicht gefunden, Login erforderlich, Timeout, Ref-Änderung ✅ ### Lessons Learned - **patchright `page.url()` nach Navigation** gibt stale URL zurück (detached Chrome + CDP). `page.goto(backUrl)` navigiert, aber `page.url()` bleibt unverändert. - **`page.evaluate()` liest DOM der forward-Seite**, nicht der Ziel-Seite, wenn man `goBack` aufruft. - **Session-Datei als Single Source of Truth:** Da `page.url()` und `page.evaluate()` stale sind, dient die Session-Datei als korrekte Quelle für URL, Titel und bodyChars. - **`page.waitForNavigation()`** funktioniert mit `goBack`/`goForward` nicht zuverlässig (keine Events bei cached navigation). - **`ignoreCache: true`** half nicht — der Browser lädt trotzdem die gecachte Seite. - **`page.reload()`** nach `goto` half nicht — der DOM bleibt stale. - **Neues Page-Objekt** statt `goto` half nicht — das problematische DOM bleibt auf der alten Seite. ### Nächste Schritte 1. Plugin gegen reale Server testen (nginx, Proxmox, Docker, Forgejo) — ✅ getestet 2. Gegen externe Webseiten testen (ebay, Google, …) — ausstehend 3. Plugin-Registry einreihen (`.include`-Datei hinzufügen) — ausstehend 4. Store-Assets für Plugin-Marktplatz hinzufügen (`store/`-Verzeichnis) — ausstehend ## Browser pro Chat: Tabs und Screenshot-Ansicht (Plan, 2026-10-19) Ziel: Das Seitenpanel „Browser“ ist ein echter Browser mit mehreren Tabs. Jeder Chat hat eigene Tabs, das Panel zeigt die Tabs des geöffneten Chats; der Agent arbeitet in denselben Tabs. Ausgangslage: Das Panel (`BrowserTabView.swift`) und der Agent sind nicht verbunden. Der Agent nimmt eine beliebige Session-ID, das Panel hat eine eigene und zeigt nur, was es selbst gestartet hat („Inaktiv“). Das Panel startet auf dem Mac `/usr/bin/node browser.mjs` direkt und parst Text, remote ruft es `/plugins/iris-browser/api/browser` auf, die Route gibt es seit 0.2.0 nicht mehr. `browser.mjs` kennt keine Tabs. Die Chat-ID kommt als `IRIS_JOB_ID` in der Umgebung des Agenten an; `HERMES_SESSION_ID` ist nicht verlässlich. ### Entscheidungen 1. **Lebensdauer:** Der Browser eines Chats lebt, bis der Nutzer ihn schließt (Mülleimer) oder den Chat löscht. Er überlebt Chatwechsel, geschlossenes Panel und App-Neustart. Dazu ein Leerlauf-Timeout (Richtwert 2 h ohne Zugriff, Tab-URLs bleiben gemerkt) und ein Limit für Tabs je Chat. 2. **Profil:** Ein gemeinsames Profil für alle Chats (Logins einmal). Folge: **ein** Chromium je Server statt eines je Chat; jeder Chat besitzt darin eine Gruppe von Tabs, das Plugin merkt sich die Zuordnung Tab → Chat. 3. **Trennung:** Streng. Jeder Befehl wirkt nur auf Tabs des eigenen Chats (Chat-ID aus `IRIS_JOB_ID`, im Plugin geprüft, nicht dem Agenten überlassen); `tabs` listet nur die eigenen. Gemeinsam sind Logins, nicht Seiten. 4. **Bedienung im Panel:** Stufe 1: Tab-Leiste, Adressleiste, Zurück/Vor/Neu laden, Klick an einer Stelle im Bild, Scrollen. Stufe 2: Tastatureingabe in Felder, damit sich der Nutzer selbst anmelden kann, ohne dass der Agent ein Passwort sieht. Rechtsklick und Textauswahl bleiben draußen. 5. **Aktualisierung:** Abfragen im Takt über `panel_api` (etwa 1 s, solange das Panel sichtbar ist und etwas passiert, sonst 5 s, bei geschlossenem Panel nicht). Der Server liefert eine Prüfsumme des Screenshots, das Bild wird nur bei Änderung übertragen; nach einer Aktion sofort. Kein Datenstrom, keine neue Route im Iris-Hauptcode. Ein CDP-Screencast mit dauerhaftem Dienst ist ein möglicher späterer Ausbau. 6. **Gleichzeitige Arbeit:** Befehle eines Chats laufen nacheinander (Sperre im Plugin), die Oberfläche wird nicht gesperrt. Das Panel zeigt „Agent aktiv“, solange ein Agentenbefehl läuft oder gerade lief. Was der Nutzer tut, gilt. Ungültig gewordene Refs melden einen klaren Fehler („Seite hat sich geändert, neuen Snapshot holen“). 7. **Plattformen:** Mac-Server zuerst, `platforms` bleibt `["macos"]`. iOS zieht über denselben `panel_api`-Weg nach, der Linux-Server später (dort läuft kein `post_install`). ### Schritte (je ein PR, alles in #123) 1. **Plugin 0.3.0:** ein Chromium mit gemeinsamem Profil, Tabs je Chat mit Zuordnung und Trennung, Befehle `tabs`, `new-tab`, `switch-tab`, `close-tab`, `screenshot` (mit Prüfsumme), `click-at`, `scroll`, Sperre je Chat, Leerlauf-Timeout. CLI und `panel_api` über denselben Code, Chat-ID aus `IRIS_JOB_ID`. SKILL.md und Systemprompt anpassen. Test gegen eine lokale Seite. 2. **Panel in Iris.app und IrisClient:** `BrowserTabView` und `BrowserSessionManager` auf die `panel_api`-Route (`POST /plugins/iris-browser/api/<befehl>`, JSON) umbauen, Tab-Leiste, Adressleiste, Screenshot-Ansicht mit Klick und Scrollen, Abfragen im Takt, „Agent aktiv“. Der Direktaufruf von `/usr/bin/node` und der Textparser entfallen. 3. **Stufe 2:** Tastatureingabe im Bild. 4. **Später:** iOS, Linux-Server. Veröffentlicht wird 0.3.0 erst nach Test von Schritt 1 und 2 durch den Nutzer; bis dahin bleibt 0.2.0 im Marktplatz.
Author
Owner

PR #124 gemergt: feat(browser): Browser-Plugin mit Session-Navigation (#123)
#124

Commits:

  • feat(browser): Browser-Plugin mit Session-Navigation (#123)
  • feat(iris-browser): iris-browser Plugin — integrierter Chromium-Browser (#2ndbrain#75)
PR #124 gemergt: feat(browser): Browser-Plugin mit Session-Navigation (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/124 Commits: - feat(browser): Browser-Plugin mit Session-Navigation (#123) - feat(iris-browser): iris-browser Plugin — integrierter Chromium-Browser (#2ndbrain#75)
Author
Owner

PR #125 gemergt: docs(browser): Plan aktualisiert — Implementierungshistorie, Commands, Lessons Learned (#123)
#125

Commits:

  • docs(browser): Plan aktualisiert — Implementierungshistorie, Commands, Lessons Learned (#123)
PR #125 gemergt: docs(browser): Plan aktualisiert — Implementierungshistorie, Commands, Lessons Learned (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/125 Commits: - docs(browser): Plan aktualisiert — Implementierungshistorie, Commands, Lessons Learned (#123)
Author
Owner

PR #137 gemergt: feat(browser): panel_api-Skript für den Browser, Freigabe zum Veröffentlichen (#123)
#137

Commits:

  • feat(browser): panel_api-Skript für den Browser, Freigabe zum Veröffentlichen (#123)
PR #137 gemergt: feat(browser): panel_api-Skript für den Browser, Freigabe zum Veröffentlichen (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/137 Commits: - feat(browser): panel_api-Skript für den Browser, Freigabe zum Veröffentlichen (#123)
Author
Owner

PR #149 gemergt: fix(browser): Plugin-Protokoll-konform: eigene Abhängigkeiten per post_install, panel_api-Vertrag, echtes goBack, click/fill, Kategorie (#123)
#149

Commits:

  • fix(browser): Plugin-Protokoll-konform: eigene Abhängigkeiten per post_install, panel_api-Vertrag, echtes goBack, click/fill, Kategorie (#123)
PR #149 gemergt: fix(browser): Plugin-Protokoll-konform: eigene Abhängigkeiten per post_install, panel_api-Vertrag, echtes goBack, click/fill, Kategorie (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/149 Commits: - fix(browser): Plugin-Protokoll-konform: eigene Abhängigkeiten per post_install, panel_api-Vertrag, echtes goBack, click/fill, Kategorie (#123)
Author
Owner

PR #149 (iris-browser 0.2.0): Plugin-Protokoll-konform

Befund: publish-plugins.sh lehnte das Plugin ab (category „navigation“ unbekannt). Beim Prüfen gegen README Kapitel 3, 6, 14, 15 kamen weitere Verstöße und Fehler heraus.

Geändert:

  • category auf automation, platforms: ["macos"] (Mac zuerst, iOS zieht nach), Version 0.2.0 (Build-Skript liest sie aus plugin.json).
  • Abhängigkeiten: package.json (patchright 1.61.0) und post_install-Hook (npm install, Chromium laden). Vorher nur von Hand global installiert.
  • browser.mjs: Reste eines fremden Projekts entfernt (Suche in VS-Code-Erweiterungen, /home/mike/..., ~/.codegpt). patchright wird im Plugin aufgelöst, Sessions liegen unter Application Support/Iris/plugin-data/iris-browser/sessions, das Profil wird beim Schließen gelöscht. session-list lief wegen require im ESM-Modul nie.
  • goBack/goForward: der frühere „Fix“ lud die aktuelle URL neu und gab URL/Titel aus der Session-Datei zurück, Snapshot und Text stammten von der falschen Seite. Jetzt echte History (page.goBack()), Eintrag erkannt über geänderte URL.
  • click/fill: liefen über --eval im Seitenkontext (ui is not defined), funktionierten nie. Neu --click, --fill --value.
  • panel_api.py (vorher browser_panel.py): Befehl über argv[1] laut Vertrag, genau ein JSON-Objekt, fachliche Fehler als {"ok": false}. Eingaben geprüft (Session-ID, http(s)-URL, Ref @e<Zahl>), keine Einsetzung in JS-Quelltext mehr. screenshot ergänzt, --lines wirkt jetzt.
  • browser.mjs.patched entfernt, SKILL.md und PLAN.md (Lessons Learned) berichtigt, tests/test_panel_api.py (7 Tests).

Geprüft: Paket gebaut, in leerem Verzeichnis per Hook installiert (npm + Chromium), alle Panel-Befehle gegen example.com, iana.org und eine lokale Formularseite (fill, click, goBack, goForward, Fehlerfälle). publish-plugins.sh --dry-run: 1 würde veröffentlicht, 0 fehlgeschlagen.

Offen:

  • Installation über die Iris-GUI auf dem Mac nicht getestet (Hook und Panel nur direkt aufgerufen); panel_api über die Route /plugins/iris-browser/api/<befehl> ebenfalls nicht.
  • SideView-Anzeige aus der Beschreibung ist nicht gebaut: Der Browser läuft headless, sichtbar ist nur der Screenshot.
  • Linux-Server (kein Hook dort), store/, Test gegen externe Seiten, Veröffentlichung.
**PR #149 (iris-browser 0.2.0): Plugin-Protokoll-konform** Befund: `publish-plugins.sh` lehnte das Plugin ab (`category` „navigation“ unbekannt). Beim Prüfen gegen README Kapitel 3, 6, 14, 15 kamen weitere Verstöße und Fehler heraus. Geändert: - `category` auf `automation`, `platforms: ["macos"]` (Mac zuerst, iOS zieht nach), Version 0.2.0 (Build-Skript liest sie aus `plugin.json`). - Abhängigkeiten: `package.json` (patchright 1.61.0) und `post_install`-Hook (npm install, Chromium laden). Vorher nur von Hand global installiert. - `browser.mjs`: Reste eines fremden Projekts entfernt (Suche in VS-Code-Erweiterungen, `/home/mike/...`, `~/.codegpt`). patchright wird im Plugin aufgelöst, Sessions liegen unter `Application Support/Iris/plugin-data/iris-browser/sessions`, das Profil wird beim Schließen gelöscht. `session-list` lief wegen `require` im ESM-Modul nie. - `goBack`/`goForward`: der frühere „Fix“ lud die aktuelle URL neu und gab URL/Titel aus der Session-Datei zurück, Snapshot und Text stammten von der falschen Seite. Jetzt echte History (`page.goBack()`), Eintrag erkannt über geänderte URL. - `click`/`fill`: liefen über `--eval` im Seitenkontext (`ui is not defined`), funktionierten nie. Neu `--click`, `--fill --value`. - `panel_api.py` (vorher `browser_panel.py`): Befehl über `argv[1]` laut Vertrag, genau ein JSON-Objekt, fachliche Fehler als `{"ok": false}`. Eingaben geprüft (Session-ID, `http(s)`-URL, Ref `@e<Zahl>`), keine Einsetzung in JS-Quelltext mehr. `screenshot` ergänzt, `--lines` wirkt jetzt. - `browser.mjs.patched` entfernt, SKILL.md und PLAN.md (Lessons Learned) berichtigt, `tests/test_panel_api.py` (7 Tests). Geprüft: Paket gebaut, in leerem Verzeichnis per Hook installiert (npm + Chromium), alle Panel-Befehle gegen example.com, iana.org und eine lokale Formularseite (fill, click, goBack, goForward, Fehlerfälle). `publish-plugins.sh --dry-run`: 1 würde veröffentlicht, 0 fehlgeschlagen. Offen: - Installation über die Iris-GUI auf dem Mac nicht getestet (Hook und Panel nur direkt aufgerufen); `panel_api` über die Route `/plugins/iris-browser/api/<befehl>` ebenfalls nicht. - SideView-Anzeige aus der Beschreibung ist nicht gebaut: Der Browser läuft headless, sichtbar ist nur der Screenshot. - Linux-Server (kein Hook dort), `store/`, Test gegen externe Seiten, Veröffentlichung.
Author
Owner

Plan: Browser pro Chat mit Tabs und Screenshot-Ansicht

Im Gespräch (grill-me) festgelegt, Wortlaut jetzt auch in der Issue-Beschreibung und in iris-browser/PLAN.md. Die Beschreibung oben (Ideen, ältere Umsetzungsschritte) ist teilweise überholt: Stand und Fehlerkorrekturen siehe PR #149, Zielbild siehe den angehängten Abschnitt.

Browser pro Chat: Tabs und Screenshot-Ansicht (Plan, 2026-10-19)

Ziel: Das Seitenpanel „Browser“ ist ein echter Browser mit mehreren Tabs. Jeder Chat hat eigene Tabs, das Panel zeigt die Tabs des geöffneten Chats; der Agent arbeitet in denselben Tabs.

Ausgangslage: Das Panel (BrowserTabView.swift) und der Agent sind nicht verbunden. Der Agent nimmt eine beliebige Session-ID, das Panel hat eine eigene und zeigt nur, was es selbst gestartet hat („Inaktiv“). Das Panel startet auf dem Mac /usr/bin/node browser.mjs direkt und parst Text, remote ruft es /plugins/iris-browser/api/browser auf, die Route gibt es seit 0.2.0 nicht mehr. browser.mjs kennt keine Tabs. Die Chat-ID kommt als IRIS_JOB_ID in der Umgebung des Agenten an; HERMES_SESSION_ID ist nicht verlässlich.

Entscheidungen

  1. Lebensdauer: Der Browser eines Chats lebt, bis der Nutzer ihn schließt (Mülleimer) oder den Chat löscht. Er überlebt Chatwechsel, geschlossenes Panel und App-Neustart. Dazu ein Leerlauf-Timeout (Richtwert 2 h ohne Zugriff, Tab-URLs bleiben gemerkt) und ein Limit für Tabs je Chat.
  2. Profil: Ein gemeinsames Profil für alle Chats (Logins einmal). Folge: ein Chromium je Server statt eines je Chat; jeder Chat besitzt darin eine Gruppe von Tabs, das Plugin merkt sich die Zuordnung Tab → Chat.
  3. Trennung: Streng. Jeder Befehl wirkt nur auf Tabs des eigenen Chats (Chat-ID aus IRIS_JOB_ID, im Plugin geprüft, nicht dem Agenten überlassen); tabs listet nur die eigenen. Gemeinsam sind Logins, nicht Seiten.
  4. Bedienung im Panel: Stufe 1: Tab-Leiste, Adressleiste, Zurück/Vor/Neu laden, Klick an einer Stelle im Bild, Scrollen. Stufe 2: Tastatureingabe in Felder, damit sich der Nutzer selbst anmelden kann, ohne dass der Agent ein Passwort sieht. Rechtsklick und Textauswahl bleiben draußen.
  5. Aktualisierung: Abfragen im Takt über panel_api (etwa 1 s, solange das Panel sichtbar ist und etwas passiert, sonst 5 s, bei geschlossenem Panel nicht). Der Server liefert eine Prüfsumme des Screenshots, das Bild wird nur bei Änderung übertragen; nach einer Aktion sofort. Kein Datenstrom, keine neue Route im Iris-Hauptcode. Ein CDP-Screencast mit dauerhaftem Dienst ist ein möglicher späterer Ausbau.
  6. Gleichzeitige Arbeit: Befehle eines Chats laufen nacheinander (Sperre im Plugin), die Oberfläche wird nicht gesperrt. Das Panel zeigt „Agent aktiv“, solange ein Agentenbefehl läuft oder gerade lief. Was der Nutzer tut, gilt. Ungültig gewordene Refs melden einen klaren Fehler („Seite hat sich geändert, neuen Snapshot holen“).
  7. Plattformen: Mac-Server zuerst, platforms bleibt ["macos"]. iOS zieht über denselben panel_api-Weg nach, der Linux-Server später (dort läuft kein post_install).

Schritte (je ein PR, alles in #123)

  1. Plugin 0.3.0: ein Chromium mit gemeinsamem Profil, Tabs je Chat mit Zuordnung und Trennung, Befehle tabs, new-tab, switch-tab, close-tab, screenshot (mit Prüfsumme), click-at, scroll, Sperre je Chat, Leerlauf-Timeout. CLI und panel_api über denselben Code, Chat-ID aus IRIS_JOB_ID. SKILL.md und Systemprompt anpassen. Test gegen eine lokale Seite.
  2. Panel in Iris.app und IrisClient: BrowserTabView und BrowserSessionManager auf die panel_api-Route (POST /plugins/iris-browser/api/<befehl>, JSON) umbauen, Tab-Leiste, Adressleiste, Screenshot-Ansicht mit Klick und Scrollen, Abfragen im Takt, „Agent aktiv“. Der Direktaufruf von /usr/bin/node und der Textparser entfallen.
  3. Stufe 2: Tastatureingabe im Bild.
  4. Später: iOS, Linux-Server.

Veröffentlicht wird 0.3.0 erst nach Test von Schritt 1 und 2 durch den Nutzer; bis dahin bleibt 0.2.0 im Marktplatz.

**Plan: Browser pro Chat mit Tabs und Screenshot-Ansicht** Im Gespräch (grill-me) festgelegt, Wortlaut jetzt auch in der Issue-Beschreibung und in `iris-browser/PLAN.md`. Die Beschreibung oben (Ideen, ältere Umsetzungsschritte) ist teilweise überholt: Stand und Fehlerkorrekturen siehe PR #149, Zielbild siehe den angehängten Abschnitt. ## Browser pro Chat: Tabs und Screenshot-Ansicht (Plan, 2026-10-19) Ziel: Das Seitenpanel „Browser“ ist ein echter Browser mit mehreren Tabs. Jeder Chat hat eigene Tabs, das Panel zeigt die Tabs des geöffneten Chats; der Agent arbeitet in denselben Tabs. Ausgangslage: Das Panel (`BrowserTabView.swift`) und der Agent sind nicht verbunden. Der Agent nimmt eine beliebige Session-ID, das Panel hat eine eigene und zeigt nur, was es selbst gestartet hat („Inaktiv“). Das Panel startet auf dem Mac `/usr/bin/node browser.mjs` direkt und parst Text, remote ruft es `/plugins/iris-browser/api/browser` auf, die Route gibt es seit 0.2.0 nicht mehr. `browser.mjs` kennt keine Tabs. Die Chat-ID kommt als `IRIS_JOB_ID` in der Umgebung des Agenten an; `HERMES_SESSION_ID` ist nicht verlässlich. ### Entscheidungen 1. **Lebensdauer:** Der Browser eines Chats lebt, bis der Nutzer ihn schließt (Mülleimer) oder den Chat löscht. Er überlebt Chatwechsel, geschlossenes Panel und App-Neustart. Dazu ein Leerlauf-Timeout (Richtwert 2 h ohne Zugriff, Tab-URLs bleiben gemerkt) und ein Limit für Tabs je Chat. 2. **Profil:** Ein gemeinsames Profil für alle Chats (Logins einmal). Folge: **ein** Chromium je Server statt eines je Chat; jeder Chat besitzt darin eine Gruppe von Tabs, das Plugin merkt sich die Zuordnung Tab → Chat. 3. **Trennung:** Streng. Jeder Befehl wirkt nur auf Tabs des eigenen Chats (Chat-ID aus `IRIS_JOB_ID`, im Plugin geprüft, nicht dem Agenten überlassen); `tabs` listet nur die eigenen. Gemeinsam sind Logins, nicht Seiten. 4. **Bedienung im Panel:** Stufe 1: Tab-Leiste, Adressleiste, Zurück/Vor/Neu laden, Klick an einer Stelle im Bild, Scrollen. Stufe 2: Tastatureingabe in Felder, damit sich der Nutzer selbst anmelden kann, ohne dass der Agent ein Passwort sieht. Rechtsklick und Textauswahl bleiben draußen. 5. **Aktualisierung:** Abfragen im Takt über `panel_api` (etwa 1 s, solange das Panel sichtbar ist und etwas passiert, sonst 5 s, bei geschlossenem Panel nicht). Der Server liefert eine Prüfsumme des Screenshots, das Bild wird nur bei Änderung übertragen; nach einer Aktion sofort. Kein Datenstrom, keine neue Route im Iris-Hauptcode. Ein CDP-Screencast mit dauerhaftem Dienst ist ein möglicher späterer Ausbau. 6. **Gleichzeitige Arbeit:** Befehle eines Chats laufen nacheinander (Sperre im Plugin), die Oberfläche wird nicht gesperrt. Das Panel zeigt „Agent aktiv“, solange ein Agentenbefehl läuft oder gerade lief. Was der Nutzer tut, gilt. Ungültig gewordene Refs melden einen klaren Fehler („Seite hat sich geändert, neuen Snapshot holen“). 7. **Plattformen:** Mac-Server zuerst, `platforms` bleibt `["macos"]`. iOS zieht über denselben `panel_api`-Weg nach, der Linux-Server später (dort läuft kein `post_install`). ### Schritte (je ein PR, alles in #123) 1. **Plugin 0.3.0:** ein Chromium mit gemeinsamem Profil, Tabs je Chat mit Zuordnung und Trennung, Befehle `tabs`, `new-tab`, `switch-tab`, `close-tab`, `screenshot` (mit Prüfsumme), `click-at`, `scroll`, Sperre je Chat, Leerlauf-Timeout. CLI und `panel_api` über denselben Code, Chat-ID aus `IRIS_JOB_ID`. SKILL.md und Systemprompt anpassen. Test gegen eine lokale Seite. 2. **Panel in Iris.app und IrisClient:** `BrowserTabView` und `BrowserSessionManager` auf die `panel_api`-Route (`POST /plugins/iris-browser/api/<befehl>`, JSON) umbauen, Tab-Leiste, Adressleiste, Screenshot-Ansicht mit Klick und Scrollen, Abfragen im Takt, „Agent aktiv“. Der Direktaufruf von `/usr/bin/node` und der Textparser entfallen. 3. **Stufe 2:** Tastatureingabe im Bild. 4. **Später:** iOS, Linux-Server. Veröffentlicht wird 0.3.0 erst nach Test von Schritt 1 und 2 durch den Nutzer; bis dahin bleibt 0.2.0 im Marktplatz.
Author
Owner

PR #150 gemergt: docs(browser): Plan Browser pro Chat mit Tabs und Screenshot-Ansicht (#123)
#150

Commits:

  • docs(browser): Plan Browser pro Chat mit Tabs und Screenshot-Ansicht (#123)
PR #150 gemergt: docs(browser): Plan Browser pro Chat mit Tabs und Screenshot-Ansicht (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/150 Commits: - docs(browser): Plan Browser pro Chat mit Tabs und Screenshot-Ansicht (#123)
Author
Owner

PR #151 gemergt: feat(browser): Schritt 1 Browser pro Chat: ein Chromium, Tabs je Chat, Screenshot-Ansicht, panel_api (#123)
#151

Commits:

  • feat(browser): Schritt 1 Browser pro Chat: ein Chromium, Tabs je Chat, Screenshot-Ansicht, panel_api (#123)
PR #151 gemergt: feat(browser): Schritt 1 Browser pro Chat: ein Chromium, Tabs je Chat, Screenshot-Ansicht, panel_api (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/151 Commits: - feat(browser): Schritt 1 Browser pro Chat: ein Chromium, Tabs je Chat, Screenshot-Ansicht, panel_api (#123)
Author
Owner

PR (Schritt 1, iris-browser 0.3.0): Browser pro Chat mit Tabs

Umgesetzt wie im Plan (Entscheidungen 1 bis 7), nur das Plugin; das Panel (Schritt 2) ist noch nicht angepasst.

  • Ein Chromium je Server mit gemeinsamem Profil (plugin-data/iris-browser/profile), detached, über CDP angesprochen. Tabs gehören zu einem Chat (state.json, Tab-ID tN, Zuordnung über die CDP-Ziel-ID). Ein Chat sieht und steuert nur seine Tabs; Chat-ID aus IRIS_JOB_ID (Agent) bzw. chat_id (Panel).
  • Neue Befehle: --new-tab, --tabs, --tab, --close-tab, --close, --click-at, --scroll, --type, --key, --view (lesend ohne Sperre: Tabs, aktiver Tab, JPEG des Viewports nur bei Änderung über Prüfsumme, agent_active). Befehle eines Chats laufen nacheinander. Tabs, die ein Klick öffnet (target=_blank), werden übernommen.
  • Leerlauf: Wächterprozess parkt Chats nach 2 h ohne Zugriff (URLs bleiben), beendet den Chromium, wenn nichts mehr offen ist; ein geparkter oder verlorener Tab wird beim nächsten Zugriff mit der gemerkten URL neu geöffnet. --view startet nie einen Browser. Höchstens 10 Tabs je Chat, nur http(s).
  • panel_api.py für alle Befehle neu (chat_id Pflicht, JSON direkt von Node, Eingaben geprüft). browser.mjs in lib/ zerlegt; --script und die Session-ID entfallen. SKILL.md und Systemprompt gekürzt und aufeinander abgestimmt.
  • Geprüft: tests/smoke.sh gegen echten Chromium (zwei Chats, Trennung, Popup-Tab, Eingaben, Verlauf, Wiederherstellen nach Chromium-Ende) bestanden; tests/test_panel_api.py (10 Tests); alle panel_api-Befehle end-to-end mit dem gebauten Paket; Parken und Beenden des Chromium von Hand; publish-plugins.sh --dry-run ohne Fehler.

Offen: 0.3.0 ist nicht veröffentlicht (Marktplatz zeigt 0.2.0), bis Schritt 2 getestet ist. Nicht geprüft: Installation über die Iris-GUI, Verhalten bei parallelen Chats mit echter Agentenlast, Viewport (1280 × 657 sichtbar, Panel nutzt den gemeldeten Wert). Weiter mit Schritt 2 (Panel in Iris.app und IrisClient).

**PR (Schritt 1, iris-browser 0.3.0): Browser pro Chat mit Tabs** Umgesetzt wie im Plan (Entscheidungen 1 bis 7), nur das Plugin; das Panel (Schritt 2) ist noch nicht angepasst. - Ein Chromium je Server mit gemeinsamem Profil (`plugin-data/iris-browser/profile`), detached, über CDP angesprochen. Tabs gehören zu einem Chat (`state.json`, Tab-ID `tN`, Zuordnung über die CDP-Ziel-ID). Ein Chat sieht und steuert nur seine Tabs; Chat-ID aus `IRIS_JOB_ID` (Agent) bzw. `chat_id` (Panel). - Neue Befehle: `--new-tab`, `--tabs`, `--tab`, `--close-tab`, `--close`, `--click-at`, `--scroll`, `--type`, `--key`, `--view` (lesend ohne Sperre: Tabs, aktiver Tab, JPEG des Viewports nur bei Änderung über Prüfsumme, `agent_active`). Befehle eines Chats laufen nacheinander. Tabs, die ein Klick öffnet (`target=_blank`), werden übernommen. - Leerlauf: Wächterprozess parkt Chats nach 2 h ohne Zugriff (URLs bleiben), beendet den Chromium, wenn nichts mehr offen ist; ein geparkter oder verlorener Tab wird beim nächsten Zugriff mit der gemerkten URL neu geöffnet. `--view` startet nie einen Browser. Höchstens 10 Tabs je Chat, nur http(s). - `panel_api.py` für alle Befehle neu (`chat_id` Pflicht, JSON direkt von Node, Eingaben geprüft). `browser.mjs` in `lib/` zerlegt; `--script` und die Session-ID entfallen. SKILL.md und Systemprompt gekürzt und aufeinander abgestimmt. - Geprüft: `tests/smoke.sh` gegen echten Chromium (zwei Chats, Trennung, Popup-Tab, Eingaben, Verlauf, Wiederherstellen nach Chromium-Ende) bestanden; `tests/test_panel_api.py` (10 Tests); alle `panel_api`-Befehle end-to-end mit dem gebauten Paket; Parken und Beenden des Chromium von Hand; `publish-plugins.sh --dry-run` ohne Fehler. Offen: 0.3.0 ist nicht veröffentlicht (Marktplatz zeigt 0.2.0), bis Schritt 2 getestet ist. Nicht geprüft: Installation über die Iris-GUI, Verhalten bei parallelen Chats mit echter Agentenlast, Viewport (1280 × 657 sichtbar, Panel nutzt den gemeldeten Wert). Weiter mit Schritt 2 (Panel in Iris.app und IrisClient).
Author
Owner

PR #90 gemergt: feat(browser): Panel für Browser pro Chat: Tabs, Adressleiste, Screenshot-Ansicht über panel_api (iris/iris-plugins#123)
iris/Iris#90

Commits:

  • feat(browser): Panel für Browser pro Chat: Tabs, Adressleiste, Screenshot-Ansicht über panel_api (iris/iris-plugins#123)
PR #90 gemergt: feat(browser): Panel für Browser pro Chat: Tabs, Adressleiste, Screenshot-Ansicht über panel_api (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/90 Commits: - feat(browser): Panel für Browser pro Chat: Tabs, Adressleiste, Screenshot-Ansicht über panel_api (iris/iris-plugins#123)
Author
Owner

PR #152 gemergt: fix(browser): panel_api.py auch mit dem System-Python 3.9 lauffähig, PLAN.md Schritt 2 (#123)
#152

Commits:

  • fix(browser): panel_api.py auch mit dem System-Python 3.9 lauffähig, PLAN.md Schritt 2 (#123)
PR #152 gemergt: fix(browser): panel_api.py auch mit dem System-Python 3.9 lauffähig, PLAN.md Schritt 2 (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/152 Commits: - fix(browser): panel_api.py auch mit dem System-Python 3.9 lauffähig, PLAN.md Schritt 2 (#123)
Author
Owner

PR iris/Iris#90 (Schritt 2): Panel für Browser pro Chat

Das Seitenpanel „Browser“ in Iris.app und IrisClient ist auf das Plugin 0.3.0 umgestellt (Entscheidungen 4 bis 6 des Plans).

  • BrowserPanelState.swift (reiner Zustand, Antworten des Plugins lesen), BrowserPanelModel.swift (ein Modell je Chat, Chat-ID = Job-ID), BrowserTabView.swift neu: Tab-Leiste mit „+“ und Schließen, Adressleiste mit Zurück, Vor und Neu laden, die Seite als Bild. Ein Klick auf das Bild wird in Viewport-Pixel umgerechnet und als click-at gesendet, das Mausrad als scroll (Schritte gesammelt, nie mehrere Befehle gleichzeitig). „Agent aktiv“ aus agent_active; geparkter Chat zeigt „Fortsetzen“; fehlendes oder zu altes Plugin zeigt einen Hinweis.
  • Abfragen im Takt: view jede Sekunde bei Aktivität (Agent oder Bedienung in den letzten 10 s), sonst alle 5 s, bei geschlossenem oder verdecktem Panel gar nicht; Bild nur bei geänderter Prüfsumme.
  • RemoteServerClient.browserCommand: POST /plugins/iris-browser/api/<befehl> mit chat_id, derselbe Weg für den lokalen Mac-Server und entfernte Server. Entfallen: Direktaufruf von /usr/bin/node, BrowserAction.swift, BrowserSessionManager.swift, die Text-Parser.
  • Die drei Browser-Dateien waren im Xcode-Projekt vom Target IrisClient ausgeschlossen, obwohl RemoteClientView sie benutzt; Ausschlüsse entfernt.
  • Plugin-Repo: panel_api.py läuft jetzt auch mit dem System-Python 3.9 (Fallback des Servers); Paket 0.3.0 neu gebaut.

Geprüft: scripts/test-browser-panel-state.sh (22 Prüfungen), Iris.app baut über Xcode (Binary neu, Fehler keine). Nicht geprüft: das Panel in der laufenden App gegen einen Server mit Plugin 0.3.0, der Mausrad- und Klickweg, IrisClient (nicht gebaut, xcodebuild ist laut Projektregel tabu), ob IRIS_JOB_ID beim Aufruf durch Hermes ankommt (sonst arbeiten Agent und Panel in verschiedenen Chats).

Offen: Test durch den Nutzer; Schritt 3 (Tastatureingabe im Bild), Schritt 4 (iOS, Linux-Server); Veröffentlichung von 0.3.0 erst nach dem Test.

**PR iris/Iris#90 (Schritt 2): Panel für Browser pro Chat** Das Seitenpanel „Browser“ in Iris.app und IrisClient ist auf das Plugin 0.3.0 umgestellt (Entscheidungen 4 bis 6 des Plans). - `BrowserPanelState.swift` (reiner Zustand, Antworten des Plugins lesen), `BrowserPanelModel.swift` (ein Modell je Chat, Chat-ID = Job-ID), `BrowserTabView.swift` neu: Tab-Leiste mit „+“ und Schließen, Adressleiste mit Zurück, Vor und Neu laden, die Seite als Bild. Ein Klick auf das Bild wird in Viewport-Pixel umgerechnet und als `click-at` gesendet, das Mausrad als `scroll` (Schritte gesammelt, nie mehrere Befehle gleichzeitig). „Agent aktiv“ aus `agent_active`; geparkter Chat zeigt „Fortsetzen“; fehlendes oder zu altes Plugin zeigt einen Hinweis. - Abfragen im Takt: `view` jede Sekunde bei Aktivität (Agent oder Bedienung in den letzten 10 s), sonst alle 5 s, bei geschlossenem oder verdecktem Panel gar nicht; Bild nur bei geänderter Prüfsumme. - `RemoteServerClient.browserCommand`: `POST /plugins/iris-browser/api/<befehl>` mit `chat_id`, derselbe Weg für den lokalen Mac-Server und entfernte Server. Entfallen: Direktaufruf von `/usr/bin/node`, `BrowserAction.swift`, `BrowserSessionManager.swift`, die Text-Parser. - Die drei Browser-Dateien waren im Xcode-Projekt vom Target `IrisClient` ausgeschlossen, obwohl `RemoteClientView` sie benutzt; Ausschlüsse entfernt. - Plugin-Repo: `panel_api.py` läuft jetzt auch mit dem System-Python 3.9 (Fallback des Servers); Paket 0.3.0 neu gebaut. Geprüft: `scripts/test-browser-panel-state.sh` (22 Prüfungen), Iris.app baut über Xcode (Binary neu, Fehler keine). Nicht geprüft: das Panel in der laufenden App gegen einen Server mit Plugin 0.3.0, der Mausrad- und Klickweg, IrisClient (nicht gebaut, `xcodebuild` ist laut Projektregel tabu), ob `IRIS_JOB_ID` beim Aufruf durch Hermes ankommt (sonst arbeiten Agent und Panel in verschiedenen Chats). Offen: Test durch den Nutzer; Schritt 3 (Tastatureingabe im Bild), Schritt 4 (iOS, Linux-Server); Veröffentlichung von 0.3.0 erst nach dem Test.
Author
Owner

PR #153 gemergt: fix(browser): Chat-ID aus dem Workspace, Viewport in Panelgröße (--resize), Tastatur-Befehle, Plugin 0.3.1 (#123)
#153

Commits:

  • fix(browser): Chat-ID aus dem Workspace, Viewport in Panelgröße (--resize), Tastatur-Befehle, Plugin 0.3.1 (#123)
PR #153 gemergt: fix(browser): Chat-ID aus dem Workspace, Viewport in Panelgröße (--resize), Tastatur-Befehle, Plugin 0.3.1 (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/153 Commits: - fix(browser): Chat-ID aus dem Workspace, Viewport in Panelgröße (--resize), Tastatur-Befehle, Plugin 0.3.1 (#123)
Author
Owner

PR #91 gemergt: fix(browser): Panel: Viewport in Panelgröße, Tastatureingabe an die Seite (iris/iris-plugins#123)
iris/Iris#91

Commits:

PR #91 gemergt: fix(browser): Panel: Viewport in Panelgröße, Tastatureingabe an die Seite (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/91 Commits: - fix(browser): Panel: Viewport in Panelgröße, Tastatureingabe an die Seite (iris/iris-plugins#123)
Author
Owner

Nachbesserungen nach dem ersten Test (Plugin 0.3.1, Panel PR in iris/Iris)

Der erste Test (Nutzer, Chat „nextcloud…“) zeigte: Das Panel funktioniert, die Seite des Agenten erscheint. Drei Dinge waren falsch oder fehlten.

  • Chat-ID: IRIS_JOB_ID war im Terminal des Agenten leer (der Agent meldete es selbst und leitete die ID zufällig aus dem Workspace-Ordner ab). HERMES_SESSION_ID gilt laut Iris-Code als unzuverlässig. Verlässlich ist das Arbeitsverzeichnis …/Workspaces/<Job-UUID>, das Iris je Chat setzt (agent.log: „Session snapshot created … cwd=…“). browser.mjs nimmt jetzt IRIS_BROWSER_CHAT (Panel), sonst die UUID im Arbeitsverzeichnis, sonst IRIS_JOB_ID; Fehlermeldung nennt den Ausweg IRIS_BROWSER_CHAT=<UUID>. SKILL.md angepasst.
  • Eingebautes Toolset: Der erste Versuch lief mit dem Hermes-eigenen browser_navigate, das Panel blieb leer. Auf Nutzerentscheidung das Toolset browser für api_server in ~/.hermes/config.yaml abgeschaltet (Mac; Linux-Server unberührt).
  • Größe: Der Browser hatte fest 1280 × 657 und füllte nur die obere Hälfte des Panels. Das Panel meldet jetzt die Größe seines Seitenbereichs mit jedem Befehl (size); das Plugin stellt das Browserfenster per CDP so ein, dass der Viewport passt (bleibt über Aufrufe bestehen), und merkt sich die Größe je Chat, damit auch vom Agenten geöffnete Tabs passen. Geprüft: 900 × 1000 und 600 × 700, neuer Tab übernimmt die Größe.
  • Tastatur (Schritt 3, vorgezogen): Tasten gingen verloren, macOS gab nur einen Fehlton. Nach einem Klick auf die Seite nimmt das Panel jetzt Tasten an (PageInputCatcher): Text als type (zusammengefasst, damit ein schnell getipptes Wort ein Befehl bleibt), Sondertasten (Enter, Tab, Rück, Entf, Pfeile, Pos1, Ende, Bild auf/ab, Escape) als key, Cmd+V als Text, Cmd+A. Ein Rahmen zeigt, dass die Seite die Tastatur hat; Klick in die Adressleiste gibt sie zurück.
  • Plugin 0.3.1 (Paket auf dem Desktop), 11 Python-Tests, 22 Prüfungen des Panel-Zustands, Iris.app baut über Xcode (Binary neu).

Nicht geprüft: Tippen und Größenänderung in der laufenden App (Nutzer), IrisClient (nicht gebaut), Verzögerung beim Tippen (jeder Befehl braucht etwa 0,5 s). Offen: Schritt 4 (iOS, Linux-Server), Veröffentlichung nach dem Test.

**Nachbesserungen nach dem ersten Test (Plugin 0.3.1, Panel PR in iris/Iris)** Der erste Test (Nutzer, Chat „nextcloud…“) zeigte: Das Panel funktioniert, die Seite des Agenten erscheint. Drei Dinge waren falsch oder fehlten. - **Chat-ID:** `IRIS_JOB_ID` war im Terminal des Agenten leer (der Agent meldete es selbst und leitete die ID zufällig aus dem Workspace-Ordner ab). `HERMES_SESSION_ID` gilt laut Iris-Code als unzuverlässig. Verlässlich ist das Arbeitsverzeichnis `…/Workspaces/<Job-UUID>`, das Iris je Chat setzt (`agent.log`: „Session snapshot created … cwd=…“). `browser.mjs` nimmt jetzt `IRIS_BROWSER_CHAT` (Panel), sonst die UUID im Arbeitsverzeichnis, sonst `IRIS_JOB_ID`; Fehlermeldung nennt den Ausweg `IRIS_BROWSER_CHAT=<UUID>`. SKILL.md angepasst. - **Eingebautes Toolset:** Der erste Versuch lief mit dem Hermes-eigenen `browser_navigate`, das Panel blieb leer. Auf Nutzerentscheidung das Toolset `browser` für `api_server` in `~/.hermes/config.yaml` abgeschaltet (Mac; Linux-Server unberührt). - **Größe:** Der Browser hatte fest 1280 × 657 und füllte nur die obere Hälfte des Panels. Das Panel meldet jetzt die Größe seines Seitenbereichs mit jedem Befehl (`size`); das Plugin stellt das Browserfenster per CDP so ein, dass der Viewport passt (bleibt über Aufrufe bestehen), und merkt sich die Größe je Chat, damit auch vom Agenten geöffnete Tabs passen. Geprüft: 900 × 1000 und 600 × 700, neuer Tab übernimmt die Größe. - **Tastatur (Schritt 3, vorgezogen):** Tasten gingen verloren, macOS gab nur einen Fehlton. Nach einem Klick auf die Seite nimmt das Panel jetzt Tasten an (`PageInputCatcher`): Text als `type` (zusammengefasst, damit ein schnell getipptes Wort ein Befehl bleibt), Sondertasten (Enter, Tab, Rück, Entf, Pfeile, Pos1, Ende, Bild auf/ab, Escape) als `key`, Cmd+V als Text, Cmd+A. Ein Rahmen zeigt, dass die Seite die Tastatur hat; Klick in die Adressleiste gibt sie zurück. - Plugin 0.3.1 (Paket auf dem Desktop), 11 Python-Tests, 22 Prüfungen des Panel-Zustands, Iris.app baut über Xcode (Binary neu). Nicht geprüft: Tippen und Größenänderung in der laufenden App (Nutzer), IrisClient (nicht gebaut), Verzögerung beim Tippen (jeder Befehl braucht etwa 0,5 s). Offen: Schritt 4 (iOS, Linux-Server), Veröffentlichung nach dem Test.
Author
Owner

PR #154 gemergt: perf(browser): Browser-Dienst hält die Verbindung offen, Aktionen liefern das Bild mit, Popup-Tabs über den Opener, Plugin 0.3.2 (#123)
#154

Commits:

  • perf(browser): Browser-Dienst hält die Verbindung offen, Aktionen liefern das Bild mit, Popup-Tabs über den Opener, Plugin 0.3.2 (#123)
PR #154 gemergt: perf(browser): Browser-Dienst hält die Verbindung offen, Aktionen liefern das Bild mit, Popup-Tabs über den Opener, Plugin 0.3.2 (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/154 Commits: - perf(browser): Browser-Dienst hält die Verbindung offen, Aktionen liefern das Bild mit, Popup-Tabs über den Opener, Plugin 0.3.2 (#123)
Author
Owner

PR #92 gemergt: perf(browser): Panel nutzt Antworten mit Bild, Abfrage alle 0,5 s bei Aktivität (iris/iris-plugins#123)
iris/Iris#92

Commits:

  • perf(browser): Panel nutzt Antworten mit Bild, Abfrage alle 0,5 s bei Aktivität (iris/iris-plugins#123)
PR #92 gemergt: perf(browser): Panel nutzt Antworten mit Bild, Abfrage alle 0,5 s bei Aktivität (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/92 Commits: - perf(browser): Panel nutzt Antworten mit Bild, Abfrage alle 0,5 s bei Aktivität (iris/iris-plugins#123)
Author
Owner

Beschleunigung (Plugin 0.3.2, Panel in iris/Iris): Browser-Dienst

Nutzer: „alles extrem träge“. Gemessen, bevor etwas umgebaut wurde (Mac, lokal): Jeder Befehl kostete rund 300 ms Grundlast (Node-Start 77 ms, patchright laden etwa 170 ms, Verbindung zum Chromium 33 ms), die Arbeit selbst nur 1 bis 55 ms (Tastendruck 1 ms, JPEG-Bild 53 ms). Dazu feste Wartezeiten (400 ms nach Klick, 150 ms beim Scrollen), eine zweite Abfrage nach jeder Aktion und der Takt von 1 s: ein getipptes Zeichen war erst nach gut 0,8 s zu sehen.

  • Dienst: lib/daemon.mjs, ein dauerhafter Node-Prozess je Server, hält Verbindung und Zustand offen. Unix-Socket in /tmp (0600), Versionsprüfung (ein Dienst älterer Version wird ersetzt), endet, wenn der Chromium nicht mehr läuft; der Wächter für den Leerlauf läuft im Dienst. browser.mjs ist ein dünner Client, panel_api.py spricht den Socket direkt an (ohne Node) und fällt auf browser.mjs zurück. Befehlslogik in lib/commands.mjs, Befehle je Chat über eine Warteschlange im Dienst.
  • Aktionen liefern das Bild mit (--shot, Prüfsumme since); das Panel macht keine zweite Abfrage mehr und fragt bei Aktivität alle 0,5 s (sonst 3 s).
  • Neue Tabs ereignisgesteuert: Zuordnung über page.opener() zum Chat des Openers statt 400 ms warten und Seitenlisten vergleichen; nur nach einem Klick auf einen Verweis mit target bis 800 ms.
  • Ergebnis (Mac, lokal, panel_api → Dienst): Text oder Taste samt neuem Bild etwa 90 ms, Klick 110 ms, Scrollen 140 ms, Abfrage 75 ms (davon etwa 50 ms Start von Python, die bleiben).
  • Geprüft: tests/smoke.sh über den Dienst (zwei Chats, Trennung, Popup-Tab, Eingaben, Verlauf, Wiederherstellen), 13 Python-Tests, Zeitmessung aller Befehle, Panel baut über Xcode. Nicht geprüft: das Panel in der laufenden App (Nutzer), Dienst unter Linux, mehrere Chats gleichzeitig unter Last, IrisClient.

Hinweis: Ein neu installiertes Plugin ersetzt den laufenden Dienst beim ersten Aufruf von selbst (Versionsprüfung); in ~/Library/Application Support/Iris/plugin-data/iris-browser/ liegen nur Zustandsdateien, Profil und Sperren.

**Beschleunigung (Plugin 0.3.2, Panel in iris/Iris): Browser-Dienst** Nutzer: „alles extrem träge“. Gemessen, bevor etwas umgebaut wurde (Mac, lokal): Jeder Befehl kostete rund 300 ms Grundlast (Node-Start 77 ms, patchright laden etwa 170 ms, Verbindung zum Chromium 33 ms), die Arbeit selbst nur 1 bis 55 ms (Tastendruck 1 ms, JPEG-Bild 53 ms). Dazu feste Wartezeiten (400 ms nach Klick, 150 ms beim Scrollen), eine zweite Abfrage nach jeder Aktion und der Takt von 1 s: ein getipptes Zeichen war erst nach gut 0,8 s zu sehen. - **Dienst:** `lib/daemon.mjs`, ein dauerhafter Node-Prozess je Server, hält Verbindung und Zustand offen. Unix-Socket in `/tmp` (0600), Versionsprüfung (ein Dienst älterer Version wird ersetzt), endet, wenn der Chromium nicht mehr läuft; der Wächter für den Leerlauf läuft im Dienst. `browser.mjs` ist ein dünner Client, `panel_api.py` spricht den Socket direkt an (ohne Node) und fällt auf `browser.mjs` zurück. Befehlslogik in `lib/commands.mjs`, Befehle je Chat über eine Warteschlange im Dienst. - **Aktionen liefern das Bild mit** (`--shot`, Prüfsumme `since`); das Panel macht keine zweite Abfrage mehr und fragt bei Aktivität alle 0,5 s (sonst 3 s). - **Neue Tabs ereignisgesteuert:** Zuordnung über `page.opener()` zum Chat des Openers statt 400 ms warten und Seitenlisten vergleichen; nur nach einem Klick auf einen Verweis mit `target` bis 800 ms. - Ergebnis (Mac, lokal, `panel_api` → Dienst): Text oder Taste samt neuem Bild etwa 90 ms, Klick 110 ms, Scrollen 140 ms, Abfrage 75 ms (davon etwa 50 ms Start von Python, die bleiben). - Geprüft: `tests/smoke.sh` über den Dienst (zwei Chats, Trennung, Popup-Tab, Eingaben, Verlauf, Wiederherstellen), 13 Python-Tests, Zeitmessung aller Befehle, Panel baut über Xcode. Nicht geprüft: das Panel in der laufenden App (Nutzer), Dienst unter Linux, mehrere Chats gleichzeitig unter Last, IrisClient. Hinweis: Ein neu installiertes Plugin ersetzt den laufenden Dienst beim ersten Aufruf von selbst (Versionsprüfung); in `~/Library/Application Support/Iris/plugin-data/iris-browser/` liegen nur Zustandsdateien, Profil und Sperren.
Author
Owner

PR #155 gemergt: feat(browser): Plugin 0.4.0: Dienst über TCP mit Token für den Linux-Server, Screenshot-Datei schreibt der Client (#123)
#155

Commits:

  • feat(browser): Plugin 0.4.0: Dienst über TCP mit Token für den Linux-Server, Screenshot-Datei schreibt der Client (#123)
PR #155 gemergt: feat(browser): Plugin 0.4.0: Dienst über TCP mit Token für den Linux-Server, Screenshot-Datei schreibt der Client (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/155 Commits: - feat(browser): Plugin 0.4.0: Dienst über TCP mit Token für den Linux-Server, Screenshot-Datei schreibt der Client (#123)
Author
Owner

PR #47 gemergt: feat(browser): Container iris-browser für das Plugin iris-browser, Sandbox-Umgebung und Token (iris/iris-plugins#123)
iris/iris-linux-server#47

Commits:

  • feat(browser): Container iris-browser für das Plugin iris-browser, Sandbox-Umgebung und Token (iris/iris-plugins#123)
PR #47 gemergt: feat(browser): Container iris-browser für das Plugin iris-browser, Sandbox-Umgebung und Token (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/47 Commits: - feat(browser): Container iris-browser für das Plugin iris-browser, Sandbox-Umgebung und Token (iris/iris-plugins#123)
Author
Owner

PR #156 gemergt: feat(browser): platforms linux, Plan Schritt 4b, SKILL.md Chat-Hinweis (#123)
#156

Commits:

  • feat(browser): platforms linux, Plan Schritt 4b, SKILL.md Chat-Hinweis (#123)
PR #156 gemergt: feat(browser): platforms linux, Plan Schritt 4b, SKILL.md Chat-Hinweis (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/156 Commits: - feat(browser): platforms linux, Plan Schritt 4b, SKILL.md Chat-Hinweis (#123)
Author
Owner

Schritt 4 (Linux-Server): Plugin 0.4.0 und Container iris-browser

Nach dem Entwurf im Gespräch (eigener Container, Dienst über TCP mit Token, nur im Docker-Netz).

  • Plugin 0.4.0: Der Dienst kann über TCP sprechen (IRIS_BROWSER_LISTEN=host:port, Pflicht IRIS_BROWSER_TOKEN, zeitkonstanter Vergleich, Anfragen höchstens 1 MB). Clients wählen ihn über IRIS_BROWSER_DAEMON=host:port (+ Token); dann startet kein Client einen Dienst, Fehler kommen als Meldung (nicht erreichbar, Token abgelehnt, Version passt nicht). Ein Dienst mit IRIS_BROWSER_LISTEN beendet sich nie selbst. --screenshot <pfad> schreibt der Client aus den Bilddaten des Dienstes (der Dienst liegt in einem anderen Container). platforms: ["macos", "linux"].
  • Linux-Repo (PR iris/iris-linux-server#47): Container iris-browser (browser/Dockerfile: Playwright-Basisimage mit Node, patchright 1.61.0 und dessen Chromium; browser/entrypoint.sh: startet den Dienst aus dem installierten Plugin, /data/plugins nur lesend, erneuert ihn bei neuer Plugin-Version, wartet ohne Plugin). Port 8095 nur an IRIS_BROWSER_BIND (Bridge-Gateway, Standard 172.17.0.1), nicht im LAN. scripts/detect-host-env.sh erzeugt Token und Bind-Adresse in .env. Der Sandbox-Container des Agenten liegt im Standard-Bridge-Netz und kennt keine Compose-Dienstnamen: docker_env (toolcall_proxy_config_writer.py) trägt Adresse und Token ein; panel_api.py im server-Container nutzt den Dienstnamen. Test test_render_block_gives_sandbox_the_browser_service_when_configured, 15 Tests grün.
  • Geprüft auf alf@iris-server (rsync, docker compose up -d --build, Sandbox-Container entfernt): Panel-Weg (server-Container → iris-browser:8095: öffnen, abfragen samt Bild in der Panelgröße), Agent-Weg (Sandbox-Container → 172.17.0.1:8095: Snapshot, Screenshot als Datei im Sandbox-Container, derselbe Tab wie im Panel), falsches Token abgelehnt, Port nur auf der Bridge-Adresse, docker_env in der Hermes-config.yaml vorhanden, /health ok.
  • Nicht geprüft: ein echter Chat gegen den Linux-Server (ob Hermes dort den Skill statt eines eingebauten Browser-Werkzeugs wählt; die Hermes-Konfiguration des Linux-Servers setzt keine Toolsets und wurde nicht geändert), das Panel der Mac-App gegen den Linux-Server. Auf Linux setzt der Server kein Arbeitsverzeichnis je Chat (Terminal steht auf /root); der Agent nennt den Chat über IRIS_BROWSER_CHAT=<UUID aus dem Workspace-Pfad> (SKILL.md angepasst).
  • Offen: Veröffentlichung von 0.4.0 (erst nach einem Test mit echtem Chat), Schritt 4c (iOS-Panel).
**Schritt 4 (Linux-Server): Plugin 0.4.0 und Container `iris-browser`** Nach dem Entwurf im Gespräch (eigener Container, Dienst über TCP mit Token, nur im Docker-Netz). - **Plugin 0.4.0:** Der Dienst kann über TCP sprechen (`IRIS_BROWSER_LISTEN=host:port`, Pflicht `IRIS_BROWSER_TOKEN`, zeitkonstanter Vergleich, Anfragen höchstens 1 MB). Clients wählen ihn über `IRIS_BROWSER_DAEMON=host:port` (+ Token); dann startet kein Client einen Dienst, Fehler kommen als Meldung (nicht erreichbar, Token abgelehnt, Version passt nicht). Ein Dienst mit `IRIS_BROWSER_LISTEN` beendet sich nie selbst. `--screenshot <pfad>` schreibt der Client aus den Bilddaten des Dienstes (der Dienst liegt in einem anderen Container). `platforms: ["macos", "linux"]`. - **Linux-Repo (PR iris/iris-linux-server#47):** Container `iris-browser` (`browser/Dockerfile`: Playwright-Basisimage mit Node, patchright 1.61.0 und dessen Chromium; `browser/entrypoint.sh`: startet den Dienst aus dem installierten Plugin, `/data/plugins` nur lesend, erneuert ihn bei neuer Plugin-Version, wartet ohne Plugin). Port 8095 nur an `IRIS_BROWSER_BIND` (Bridge-Gateway, Standard 172.17.0.1), nicht im LAN. `scripts/detect-host-env.sh` erzeugt Token und Bind-Adresse in `.env`. Der Sandbox-Container des Agenten liegt im Standard-Bridge-Netz und kennt keine Compose-Dienstnamen: `docker_env` (`toolcall_proxy_config_writer.py`) trägt Adresse und Token ein; `panel_api.py` im `server`-Container nutzt den Dienstnamen. Test `test_render_block_gives_sandbox_the_browser_service_when_configured`, 15 Tests grün. - **Geprüft auf `alf@iris-server`** (rsync, `docker compose up -d --build`, Sandbox-Container entfernt): Panel-Weg (`server`-Container → `iris-browser:8095`: öffnen, abfragen samt Bild in der Panelgröße), Agent-Weg (Sandbox-Container → `172.17.0.1:8095`: Snapshot, Screenshot als Datei im Sandbox-Container, derselbe Tab wie im Panel), falsches Token abgelehnt, Port nur auf der Bridge-Adresse, `docker_env` in der Hermes-`config.yaml` vorhanden, `/health` ok. - **Nicht geprüft:** ein echter Chat gegen den Linux-Server (ob Hermes dort den Skill statt eines eingebauten Browser-Werkzeugs wählt; die Hermes-Konfiguration des Linux-Servers setzt keine Toolsets und wurde nicht geändert), das Panel der Mac-App gegen den Linux-Server. Auf Linux setzt der Server kein Arbeitsverzeichnis je Chat (Terminal steht auf `/root`); der Agent nennt den Chat über `IRIS_BROWSER_CHAT=<UUID aus dem Workspace-Pfad>` (SKILL.md angepasst). - **Offen:** Veröffentlichung von 0.4.0 (erst nach einem Test mit echtem Chat), Schritt 4c (iOS-Panel).
Author
Owner

PR #48 gemergt: fix(hermes): Arbeitsverzeichnis des Jobs (cwd) an Hermes durchreichen, Hermes-Update-Hinweis (iris/iris-plugins#123)
iris/iris-linux-server#48

Commits:

  • fix(hermes): Arbeitsverzeichnis des Jobs (cwd) an Hermes durchreichen, Hermes-Update-Hinweis (iris/iris-plugins#123)
PR #48 gemergt: fix(hermes): Arbeitsverzeichnis des Jobs (cwd) an Hermes durchreichen, Hermes-Update-Hinweis (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/48 Commits: - fix(hermes): Arbeitsverzeichnis des Jobs (cwd) an Hermes durchreichen, Hermes-Update-Hinweis (iris/iris-plugins#123)
Author
Owner

PR #49 gemergt: fix(hermes): eingebautes Toolset browser für den API-Server aus, damit der Agent den Skill iris-browser nimmt (iris/iris-plugins#123)
iris/iris-linux-server#49

Commits:

  • fix(hermes): eingebautes Toolset browser für den API-Server aus, damit der Agent den Skill iris-browser nimmt (iris/iris-plugins#123)
PR #49 gemergt: fix(hermes): eingebautes Toolset browser für den API-Server aus, damit der Agent den Skill iris-browser nimmt (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/49 Commits: - fix(hermes): eingebautes Toolset browser für den API-Server aus, damit der Agent den Skill iris-browser nimmt (iris/iris-plugins#123)
Author
Owner

PR #157 gemergt: docs(browser): Plan Linux-Ergebnis, cwd und Toolset, Lessons Learned (#123)
#157

Commits:

  • docs(browser): Plan Linux-Ergebnis, cwd und Toolset, Lessons Learned (#123)
PR #157 gemergt: docs(browser): Plan Linux-Ergebnis, cwd und Toolset, Lessons Learned (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/157 Commits: - docs(browser): Plan Linux-Ergebnis, cwd und Toolset, Lessons Learned (#123)
Author
Owner

Linux-Server: Arbeitsverzeichnis je Chat, eingebautes Browser-Toolset, Veröffentlichung 0.4.0

Nutzer: fehlendes Arbeitsverzeichnis auf Linux sei „öfters ein Ärgernis“, jetzt endlich lösen.

  • Ursachen (beide belegt): (1) hermes_client.start_run kannte das Feld cwd nicht, der Mac schickt es seit dem 06.10. (HermesGatewayClient.swift); das Terminal des Agenten stand im Sandbox-Container auf /root. (2) Der Hermes in iris-hermes/iris-hermes-scheduled war der Stand vom Erstbau: Der git fetch in hermes/Dockerfile liegt im Docker-Cache, docker compose up -d --build erneuert ihn nie; der Container war 16 Fork-Commits hinter main und hatte den cwd-Patch nicht.
  • Behoben: start_run(..., cwd=), agent_jobs übergibt den Workspace des Jobs bei jedem Lauf (auch Follow-ups); Test test_hermes_client_cwd.py. Hermes über POST /hermes/agent/update auf den Fork-Stand gebracht (Prüfung und Rollback der Route; beide Container neu gestartet). Beleg: Ein Chat mit „führe pwd aus“ antwortet /workspaces/<Job-UUID>; im Hermes-Log: Session snapshot created … cwd=/workspaces/<Job-UUID>. Vorgehen zum Aktuellhalten steht jetzt in linux-server/CLAUDE.md.
  • Eingebautes Browser-Toolset: Auf Linux wählte das Modell zuerst browser_navigate (scheitert im Sandbox-Image, libcups.so.2 fehlt) und erst danach den Skill. hermes_config_writer.render_config_block schreibt jetzt platform_toolsets.api_server ausdrücklich ohne browser (Konstante API_SERVER_TOOLSETS, die Gruppen, die Hermes sonst für den API-Server aktiviert, laut hermes tools list --platform api_server); Admin-Block gilt auch für hermes-scheduled. Test test_render_config_block_enables_api_server_tools_without_builtin_browser; auf dem Dev-Server per erneutem POST /config (gleiche Werte) übernommen.
  • Geprüft (alles auf alf@iris-server): echter Browser-Chat „Öffne den Browser und gehe nach example.com“: skill_view und ein terminal-Aufruf, kein Fehlversuch, Tab https://example.com/ im Container iris-browser unter der Chat-ID aus dem Workspace-Pfad; Test-Jobs, Test-Tabs und Sandbox-Container danach entfernt. Linux-Repo: 17 Tests grün.
  • Veröffentlicht: Plugin 0.4.0 im Marktplatz (Mac und Linux).
  • Nicht geprüft: das Panel der Mac-App gegen den Linux-Server; Dienst und Container unter Last. Offen: Schritt 4c (iOS-Panel).
**Linux-Server: Arbeitsverzeichnis je Chat, eingebautes Browser-Toolset, Veröffentlichung 0.4.0** Nutzer: fehlendes Arbeitsverzeichnis auf Linux sei „öfters ein Ärgernis“, jetzt endlich lösen. - **Ursachen (beide belegt):** (1) `hermes_client.start_run` kannte das Feld `cwd` nicht, der Mac schickt es seit dem 06.10. (HermesGatewayClient.swift); das Terminal des Agenten stand im Sandbox-Container auf `/root`. (2) Der Hermes in `iris-hermes`/`iris-hermes-scheduled` war der Stand vom Erstbau: Der `git fetch` in `hermes/Dockerfile` liegt im Docker-Cache, `docker compose up -d --build` erneuert ihn nie; der Container war 16 Fork-Commits hinter `main` und hatte den `cwd`-Patch nicht. - **Behoben:** `start_run(..., cwd=)`, `agent_jobs` übergibt den Workspace des Jobs bei jedem Lauf (auch Follow-ups); Test `test_hermes_client_cwd.py`. Hermes über `POST /hermes/agent/update` auf den Fork-Stand gebracht (Prüfung und Rollback der Route; beide Container neu gestartet). Beleg: Ein Chat mit „führe pwd aus“ antwortet `/workspaces/<Job-UUID>`; im Hermes-Log: `Session snapshot created … cwd=/workspaces/<Job-UUID>`. Vorgehen zum Aktuellhalten steht jetzt in `linux-server/CLAUDE.md`. - **Eingebautes Browser-Toolset:** Auf Linux wählte das Modell zuerst `browser_navigate` (scheitert im Sandbox-Image, `libcups.so.2` fehlt) und erst danach den Skill. `hermes_config_writer.render_config_block` schreibt jetzt `platform_toolsets.api_server` ausdrücklich ohne `browser` (Konstante `API_SERVER_TOOLSETS`, die Gruppen, die Hermes sonst für den API-Server aktiviert, laut `hermes tools list --platform api_server`); Admin-Block gilt auch für `hermes-scheduled`. Test `test_render_config_block_enables_api_server_tools_without_builtin_browser`; auf dem Dev-Server per erneutem `POST /config` (gleiche Werte) übernommen. - **Geprüft (alles auf `alf@iris-server`):** echter Browser-Chat „Öffne den Browser und gehe nach example.com“: `skill_view` und ein `terminal`-Aufruf, kein Fehlversuch, Tab `https://example.com/` im Container `iris-browser` unter der Chat-ID aus dem Workspace-Pfad; Test-Jobs, Test-Tabs und Sandbox-Container danach entfernt. Linux-Repo: 17 Tests grün. - **Veröffentlicht:** Plugin **0.4.0** im Marktplatz (Mac und Linux). - **Nicht geprüft:** das Panel der Mac-App gegen den Linux-Server; Dienst und Container unter Last. **Offen:** Schritt 4c (iOS-Panel).
Author
Owner

PR #93 gemergt: feat(plugins): Manifest-Feld disables_hermes_toolsets: Plugins schalten eingebaute Hermes-Toolsets ab, solange sie installiert sind (iris/iris-plugins#123)
iris/Iris#93

Commits:

  • feat(plugins): Manifest-Feld disables_hermes_toolsets: Plugins schalten eingebaute Hermes-Toolsets ab, solange sie installiert sind (iris/iris-plugins#123)
PR #93 gemergt: feat(plugins): Manifest-Feld disables_hermes_toolsets: Plugins schalten eingebaute Hermes-Toolsets ab, solange sie installiert sind (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/93 Commits: - feat(plugins): Manifest-Feld disables_hermes_toolsets: Plugins schalten eingebaute Hermes-Toolsets ab, solange sie installiert sind (iris/iris-plugins#123)
Author
Owner

PR #50 gemergt: feat(plugins): disables_hermes_toolsets: Hermes-Werkzeuge des API-Servers folgen den installierten Plugins (iris/iris-plugins#123)
iris/iris-linux-server#50

Commits:

  • feat(plugins): disables_hermes_toolsets: Hermes-Werkzeuge des API-Servers folgen den installierten Plugins (iris/iris-plugins#123)
PR #50 gemergt: feat(plugins): disables_hermes_toolsets: Hermes-Werkzeuge des API-Servers folgen den installierten Plugins (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/50 Commits: - feat(plugins): disables_hermes_toolsets: Hermes-Werkzeuge des API-Servers folgen den installierten Plugins (iris/iris-plugins#123)
Author
Owner

PR #158 gemergt: feat(browser): Plugin 0.4.1: disables_hermes_toolsets browser, README (#123)
#158

Commits:

  • feat(browser): Plugin 0.4.1: disables_hermes_toolsets browser, README (#123)
PR #158 gemergt: feat(browser): Plugin 0.4.1: disables_hermes_toolsets browser, README (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/158 Commits: - feat(browser): Plugin 0.4.1: disables_hermes_toolsets browser, README (#123)
Author
Owner

Plugin 0.4.1: eingebaute Hermes-Toolsets werden vom Plugin selbst abgeschaltet

Nutzer: Das Abschalten des Hermes-Browsers müsse bei der Installation des Plugins automatisch passieren, sonst laufe jeder Nutzer gegen die Wand.

  • Manifest-Feld disables_hermes_toolsets (Liste von Toolset-Namen wie in hermes tools list, iris-browser: ["browser"]): Solange das Plugin installiert und aktiviert ist, sind diese eingebauten Toolsets für den Chat (api_server) abgeschaltet; beim Entfernen oder Deaktivieren sind sie wieder an. Kein Hook, keine Handarbeit in der Hermes-Konfiguration. README Kapitel 3 beschreibt das Feld.
  • Mac (iris/Iris c12d393): HermesToolsetPlan.swift (reine Planung, scripts/test-hermes-toolset-plan.sh, 15 Prüfungen) und HermesToolsetPolicy.swift (führt hermes tools disable|enable --platform api_server aus, startet das Gateway nur bei einer Änderung neu, merkt sich, was Iris selbst abgeschaltet hat: Ein vom Nutzer schon vorher abgeschaltetes Toolset wird beim Entfernen nicht wieder eingeschaltet). PluginManager gleicht bei jedem Speichern des Plugin-Index (Installieren, Aktivieren, Entfernen) und beim Start ab, gebündelt nach 2 s.
  • Linux (iris-linux-server a57e806): Die Liste des API-Servers im Admin-Block (hermes_config_writer.API_SERVER_TOOLSETS minus plugin_disabled_toolsets()) ergibt sich bei jedem Schreiben aus den installierten, aktivierten Plugins; hermes_toolsets.sync() schreibt den Block nach Installieren, Entfernen und Aktivieren neu und startet beide Hermes-Container nur bei einer echten Änderung neu. Das Index-Feld disables_hermes_toolsets wird mitgeschrieben. 21 Tests.
  • Geprüft auf alf@iris-server: Boot ohne das Feld (0.4.0) → browser an; Installation 0.4.1 → aus (Hermes neu gestartet); Plugin deaktiviert → an; aktiviert → aus; entfernt → an; wieder installiert → aus. Dabei fiel auf: Testpakete in der Dropzone werden nach dem Entfernen vom 60-s-Wächter wieder installiert, deshalb nach Tests aus der Dropzone löschen. Mac: kompiliert (Xcode), Planungslogik getestet; der Weg über die Hermes-CLI und das Gateway selbst ist nicht in der laufenden App geprüft (Nutzer: Plugin 0.4.1 importieren, vorher hermes tools enable browser --platform api_server, danach hermes tools list --platform api_server zeigt browser abgeschaltet).
  • Veröffentlicht: 0.4.1 im Marktplatz. Ein Iris-Build ohne das Feld ignoriert es: Plugin läuft wie 0.4.0, das eingebaute Toolset bleibt dann an. Nicht gebaut: Hinweis im Installationsdialog („schaltet Hermes-Toolset X ab“); die Plugin-Beschreibung nennt es.
**Plugin 0.4.1: eingebaute Hermes-Toolsets werden vom Plugin selbst abgeschaltet** Nutzer: Das Abschalten des Hermes-Browsers müsse bei der Installation des Plugins automatisch passieren, sonst laufe jeder Nutzer gegen die Wand. - **Manifest-Feld** `disables_hermes_toolsets` (Liste von Toolset-Namen wie in `hermes tools list`, `iris-browser`: `["browser"]`): Solange das Plugin installiert und aktiviert ist, sind diese eingebauten Toolsets für den Chat (`api_server`) abgeschaltet; beim Entfernen oder Deaktivieren sind sie wieder an. Kein Hook, keine Handarbeit in der Hermes-Konfiguration. README Kapitel 3 beschreibt das Feld. - **Mac** (iris/Iris `c12d393`): `HermesToolsetPlan.swift` (reine Planung, `scripts/test-hermes-toolset-plan.sh`, 15 Prüfungen) und `HermesToolsetPolicy.swift` (führt `hermes tools disable|enable --platform api_server` aus, startet das Gateway nur bei einer Änderung neu, merkt sich, was Iris selbst abgeschaltet hat: Ein vom Nutzer schon vorher abgeschaltetes Toolset wird beim Entfernen nicht wieder eingeschaltet). `PluginManager` gleicht bei jedem Speichern des Plugin-Index (Installieren, Aktivieren, Entfernen) und beim Start ab, gebündelt nach 2 s. - **Linux** (iris-linux-server `a57e806`): Die Liste des API-Servers im Admin-Block (`hermes_config_writer.API_SERVER_TOOLSETS` minus `plugin_disabled_toolsets()`) ergibt sich bei jedem Schreiben aus den installierten, aktivierten Plugins; `hermes_toolsets.sync()` schreibt den Block nach Installieren, Entfernen und Aktivieren neu und startet beide Hermes-Container nur bei einer echten Änderung neu. Das Index-Feld `disables_hermes_toolsets` wird mitgeschrieben. 21 Tests. - **Geprüft auf `alf@iris-server`:** Boot ohne das Feld (0.4.0) → `browser` an; Installation 0.4.1 → aus (Hermes neu gestartet); Plugin deaktiviert → an; aktiviert → aus; entfernt → an; wieder installiert → aus. Dabei fiel auf: Testpakete in der Dropzone werden nach dem Entfernen vom 60-s-Wächter wieder installiert, deshalb nach Tests aus der Dropzone löschen. Mac: kompiliert (Xcode), Planungslogik getestet; der Weg über die Hermes-CLI und das Gateway selbst ist **nicht** in der laufenden App geprüft (Nutzer: Plugin 0.4.1 importieren, vorher `hermes tools enable browser --platform api_server`, danach `hermes tools list --platform api_server` zeigt `browser` abgeschaltet). - **Veröffentlicht:** 0.4.1 im Marktplatz. Ein Iris-Build ohne das Feld ignoriert es: Plugin läuft wie 0.4.0, das eingebaute Toolset bleibt dann an. Nicht gebaut: Hinweis im Installationsdialog („schaltet Hermes-Toolset X ab“); die Plugin-Beschreibung nennt es.
Author
Owner

PR #18 gemergt: feat(browser): Browser-Seite im Chat: Tabs, Adressleiste, Seitenbild mit Tippen, Wischen und Tastatur (iris/iris-plugins#123)
iris/2ndbrain-ios#18

Commits:

  • feat(browser): Browser-Seite im Chat: Tabs, Adressleiste, Seitenbild mit Tippen, Wischen und Tastatur (iris/iris-plugins#123)
PR #18 gemergt: feat(browser): Browser-Seite im Chat: Tabs, Adressleiste, Seitenbild mit Tippen, Wischen und Tastatur (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/2ndbrain-ios/pulls/18 Commits: - feat(browser): Browser-Seite im Chat: Tabs, Adressleiste, Seitenbild mit Tippen, Wischen und Tastatur (iris/iris-plugins#123)
Author
Owner

PR #159 gemergt: fix(ios-install): list-devices verträgt Simulatoren ohne Entwicklermodus und Tunnel-Zustand (iris/iris-plugins#123)
#159

Commits:

  • fix(ios-install): list-devices verträgt Simulatoren ohne Entwicklermodus und Tunnel-Zustand (iris/iris-plugins#123)
PR #159 gemergt: fix(ios-install): list-devices verträgt Simulatoren ohne Entwicklermodus und Tunnel-Zustand (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/159 Commits: - fix(ios-install): list-devices verträgt Simulatoren ohne Entwicklermodus und Tunnel-Zustand (iris/iris-plugins#123)
Author
Owner

PR #160 gemergt: docs(browser): Plan Schritt 4c iOS, Stand 0.4.1 (#123)
#160

Commits:

  • docs(browser): Plan Schritt 4c iOS, Stand 0.4.1 (#123)
PR #160 gemergt: docs(browser): Plan Schritt 4c iOS, Stand 0.4.1 (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/160 Commits: - docs(browser): Plan Schritt 4c iOS, Stand 0.4.1 (#123)
Author
Owner

Schritt 4c (iOS): Browser-Seite im Chat, iris/Iris d1d9b7f (frontend/ios)

  • Platz: dritte Seite im vorhandenen Pager (Chat ↔ Notiz ↔ Browser, Umschalter und Wisch); auf dem iPad quer rechts neben dem Chat ein Umschalter Notiz | Browser wie am Mac. Auf der Browser-Seite ist das Seiten-Wischen aus, zurück über Umschalter oder linke Randzone.
  • Bedienung: Tippen klickt auf die Seite (Koordinaten im Viewport), ein Finger wischt (Seite scrollt, Schritte gesammelt), die Bildschirmtastatur erscheint nur, wenn nach dem Tippen ein Textfeld Fokus hat (kurze eval-Abfrage), mit Leiste Tab/Fertig; Hardware-Tastatur geht an die Seite (Pfeile, Escape, Tab, Pos1, Ende, Bild auf/ab, Entf). Während die Tastatur steht, bleibt die Größe des Browsers (sonst bricht die Seite bei jedem Ein-/Ausblenden um). Tabs, Adressleiste, „Agent aktiv“, „Fortsetzen“, Hinweis bei fehlendem Plugin wie am Mac.
  • Code: BrowserPanelState.swift (Kopie der Mac-Datei, dort die Tests scripts/test-browser-panel-state.sh; beide gleich halten), BrowserPanelModel.swift (UIImage, ServerConnection, gleiche panel_api-Route POST /plugins/iris-browser/api/<befehl>, daher Mac- und Linux-Server), ChatBrowserPageView.swift, Änderung in ChatNotePager.swift. Keine Serveränderung nötig.
  • Geprüft: iOS-Build (Simulator-SDK) erfolgreich; vom Nutzer auf dem iPhone getestet: funktioniert. Beim Installieren fiel ios-install list-devices auf (KeyError, weil devicectl Simulatoren ohne Entwicklermodus mitlistet); behoben, iris-plugins ccb23ba.
  • Stand des Issues: Schritte 1 bis 4 umgesetzt, Plugin 0.4.1 veröffentlicht, Daily Logs und PLAN.md nachgezogen. Offen und nicht gebaut: Hinweis im Installationsdialog („schaltet Hermes-Toolset X ab“), Test des automatischen Abschaltens auf dem Mac in der laufenden App, Panel der Mac-App gegen den Linux-Server. Das Issue bleibt offen, bis du „Issue schließen“ sagst.
**Schritt 4c (iOS): Browser-Seite im Chat, iris/Iris `d1d9b7f` (`frontend/ios`)** - **Platz:** dritte Seite im vorhandenen Pager (Chat ↔ Notiz ↔ Browser, Umschalter und Wisch); auf dem iPad quer rechts neben dem Chat ein Umschalter Notiz | Browser wie am Mac. Auf der Browser-Seite ist das Seiten-Wischen aus, zurück über Umschalter oder linke Randzone. - **Bedienung:** Tippen klickt auf die Seite (Koordinaten im Viewport), ein Finger wischt (Seite scrollt, Schritte gesammelt), die Bildschirmtastatur erscheint nur, wenn nach dem Tippen ein Textfeld Fokus hat (kurze `eval`-Abfrage), mit Leiste Tab/Fertig; Hardware-Tastatur geht an die Seite (Pfeile, Escape, Tab, Pos1, Ende, Bild auf/ab, Entf). Während die Tastatur steht, bleibt die Größe des Browsers (sonst bricht die Seite bei jedem Ein-/Ausblenden um). Tabs, Adressleiste, „Agent aktiv“, „Fortsetzen“, Hinweis bei fehlendem Plugin wie am Mac. - **Code:** `BrowserPanelState.swift` (Kopie der Mac-Datei, dort die Tests `scripts/test-browser-panel-state.sh`; beide gleich halten), `BrowserPanelModel.swift` (UIImage, `ServerConnection`, gleiche `panel_api`-Route `POST /plugins/iris-browser/api/<befehl>`, daher Mac- und Linux-Server), `ChatBrowserPageView.swift`, Änderung in `ChatNotePager.swift`. Keine Serveränderung nötig. - **Geprüft:** iOS-Build (Simulator-SDK) erfolgreich; vom Nutzer auf dem iPhone getestet: funktioniert. Beim Installieren fiel `ios-install list-devices` auf (`KeyError`, weil `devicectl` Simulatoren ohne Entwicklermodus mitlistet); behoben, iris-plugins `ccb23ba`. - **Stand des Issues:** Schritte 1 bis 4 umgesetzt, Plugin 0.4.1 veröffentlicht, Daily Logs und `PLAN.md` nachgezogen. Offen und nicht gebaut: Hinweis im Installationsdialog („schaltet Hermes-Toolset X ab“), Test des automatischen Abschaltens auf dem Mac in der laufenden App, Panel der Mac-App gegen den Linux-Server. Das Issue bleibt offen, bis du „Issue schließen“ sagst.
Author
Owner

PR #161 gemergt: docs(readme): Bestätigungsdialog nennt abgeschaltete Hermes-Toolsets (iris/iris-plugins#123)
#161

Commits:

PR #161 gemergt: docs(readme): Bestätigungsdialog nennt abgeschaltete Hermes-Toolsets (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/161 Commits: - docs(readme): Bestätigungsdialog nennt abgeschaltete Hermes-Toolsets (iris/iris-plugins#123)
Author
Owner

PR #94 gemergt: feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
iris/Iris#94

Commits:

  • feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
PR #94 gemergt: feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/94 Commits: - feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
Author
Owner

PR #19 gemergt: feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
iris/2ndbrain-ios#19

Commits:

  • feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
PR #19 gemergt: feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/2ndbrain-ios/pulls/19 Commits: - feat(marketplace): Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die das Plugin abschaltet (iris/iris-plugins#123)
Author
Owner

PR #51 gemergt: feat(marketplace): Paket-Zusammenfassung trägt disables_hermes_toolsets (iris/iris-plugins#123)
iris/iris-linux-server#51

Commits:

PR #51 gemergt: feat(marketplace): Paket-Zusammenfassung trägt disables_hermes_toolsets (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/51 Commits: - feat(marketplace): Paket-Zusammenfassung trägt disables_hermes_toolsets (iris/iris-plugins#123)
Author
Owner

Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die ein Plugin abschaltet (Mac 2a1abe9, iOS 0ef7805, Linux 1706341, README b1a39e2)

Wer Plugin 0.4.1 installiert, sieht vorher: „Schaltet eingebaute Hermes-Werkzeuge ab, solange es installiert ist: browser. Das Plugin ersetzt sie; beim Deaktivieren oder Entfernen sind sie wieder an.“ Damit steht die Wirkung des Manifest-Felds disables_hermes_toolsets nicht nur in der Beschreibung.

  • Die Paket-Zusammenfassung der Server trägt das Feld disables_hermes_toolsets (Linux marketplace_summary.py, Mac MarketplaceCore.swift; gleiche Form, Unsinn im Feld fällt weg).
  • MarketplaceConfirmation.swift (Quelle Mac, Kopie iOS; tools/check-marketplace-page-sync grün) liest es; Mac- und iOS-Dialog zeigen eine Zeile mit Warnsymbol.
  • Geprüft: Linux 73 Tests, Mac test-marketplace-core.sh 204 Prüfungen, beide Apps bauen (Xcode, iOS-Simulator-SDK), am echten Paket auf alf@iris-server gelesen (['browser']). Nicht gesehen: der Dialog selbst in der laufenden App.
  • Offen weiterhin: Test des automatischen Abschaltens auf dem Mac in der laufenden App, Panel der Mac-App gegen den Linux-Server, Prüfsummen-Regel für Installationen des Agenten.
**Bestätigungsdialog nennt eingebaute Hermes-Toolsets, die ein Plugin abschaltet** (Mac `2a1abe9`, iOS `0ef7805`, Linux `1706341`, README `b1a39e2`) Wer Plugin 0.4.1 installiert, sieht vorher: „Schaltet eingebaute Hermes-Werkzeuge ab, solange es installiert ist: browser. Das Plugin ersetzt sie; beim Deaktivieren oder Entfernen sind sie wieder an.“ Damit steht die Wirkung des Manifest-Felds `disables_hermes_toolsets` nicht nur in der Beschreibung. - Die Paket-Zusammenfassung der Server trägt das Feld `disables_hermes_toolsets` (Linux `marketplace_summary.py`, Mac `MarketplaceCore.swift`; gleiche Form, Unsinn im Feld fällt weg). - `MarketplaceConfirmation.swift` (Quelle Mac, Kopie iOS; `tools/check-marketplace-page-sync` grün) liest es; Mac- und iOS-Dialog zeigen eine Zeile mit Warnsymbol. - Geprüft: Linux 73 Tests, Mac `test-marketplace-core.sh` 204 Prüfungen, beide Apps bauen (Xcode, iOS-Simulator-SDK), am echten Paket auf `alf@iris-server` gelesen (`['browser']`). Nicht gesehen: der Dialog selbst in der laufenden App. - Offen weiterhin: Test des automatischen Abschaltens auf dem Mac in der laufenden App, Panel der Mac-App gegen den Linux-Server, Prüfsummen-Regel für Installationen des Agenten.
Author
Owner

PR #95 gemergt: fix(ui): Umschalter Notiz | Browser im Seitenpanel statt in der Titelleiste (iris/iris-plugins#123)
iris/Iris#95

Commits:

PR #95 gemergt: fix(ui): Umschalter Notiz | Browser im Seitenpanel statt in der Titelleiste (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/95 Commits: - fix(ui): Umschalter Notiz | Browser im Seitenpanel statt in der Titelleiste (iris/iris-plugins#123)
Author
Owner

PR #52 gemergt: chore(release): Image iris-browser im Release, Hermes-Fork-Stand bricht den Docker-Cache (iris/iris-plugins#123)
iris/iris-linux-server#52

Commits:

  • chore(release): Image iris-browser im Release, Hermes-Fork-Stand bricht den Docker-Cache (iris/iris-plugins#123)
PR #52 gemergt: chore(release): Image iris-browser im Release, Hermes-Fork-Stand bricht den Docker-Cache (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/52 Commits: - chore(release): Image iris-browser im Release, Hermes-Fork-Stand bricht den Docker-Cache (iris/iris-plugins#123)
Author
Owner

Release der Linux-Server-Images: v1.6.51, latest (Nutzerwunsch: alle Iris-Images bauen und auf latest setzen)

  • build-and-push.sh --version v1.6.51 auf alf@iris-server: server, hermes, tunnel, hermes-sandbox, web-automation und neu browser gebaut und nach forgejo.lewerken.duckdns.org/iris/iris-* gepusht; Git-Tag v1.6.51 gepusht; danach --promote-latest v1.6.51. In der Registry haben v1.6.51 und latest bei allen sechs Images denselben Digest (server 4516d0c4c705, hermes 185f7b8859dc, tunnel bbc1a6ff2c91, hermes-sandbox c73f367e330b, web-automation 1211e0d2d173, browser 01117e86fb31).
  • Zwei Änderungen am Release-Weg (c82b63b): browser ist Teil der Image-Liste; der Hermes-Fork-Stand geht als Build-Argument HERMES_AGENT_REV mit, sonst hätte der Docker-Cache dem Hermes-Image den Stand des Erstbaus gegeben (ohne cwd-Patch). Verwendet: Fork 2d572e6.
  • Nicht gebaut, offen: docker-compose.deploy.yml.template kennt den Dienst iris-browser nicht. Neuinstallationen und Aktualisierungen aus der Mac-App starten deshalb keinen Browser-Container, das Plugin meldet dort „Browser-Dienst nicht erreichbar“. Nötig: Dienst und Platzhalter für IRIS_BROWSER_TOKEN/IRIS_BROWSER_BIND in der Vorlage, Erzeugen des Tokens und Nachrüsten bestehender Instanzen in LinuxServerDeployManager.swift (wie bei web-automation). Nicht geprüft: ein Start dieser Images in einer frischen Instanz.
**Release der Linux-Server-Images: v1.6.51, `latest`** (Nutzerwunsch: alle Iris-Images bauen und auf `latest` setzen) - `build-and-push.sh --version v1.6.51` auf `alf@iris-server`: server, hermes, tunnel, hermes-sandbox, web-automation und neu **browser** gebaut und nach `forgejo.lewerken.duckdns.org/iris/iris-*` gepusht; Git-Tag `v1.6.51` gepusht; danach `--promote-latest v1.6.51`. In der Registry haben `v1.6.51` und `latest` bei allen sechs Images denselben Digest (server `4516d0c4c705`, hermes `185f7b8859dc`, tunnel `bbc1a6ff2c91`, hermes-sandbox `c73f367e330b`, web-automation `1211e0d2d173`, browser `01117e86fb31`). - Zwei Änderungen am Release-Weg (`c82b63b`): `browser` ist Teil der Image-Liste; der Hermes-Fork-Stand geht als Build-Argument `HERMES_AGENT_REV` mit, sonst hätte der Docker-Cache dem Hermes-Image den Stand des Erstbaus gegeben (ohne `cwd`-Patch). Verwendet: Fork `2d572e6`. - **Nicht gebaut, offen:** `docker-compose.deploy.yml.template` kennt den Dienst `iris-browser` nicht. Neuinstallationen und Aktualisierungen aus der Mac-App starten deshalb keinen Browser-Container, das Plugin meldet dort „Browser-Dienst nicht erreichbar“. Nötig: Dienst und Platzhalter für `IRIS_BROWSER_TOKEN`/`IRIS_BROWSER_BIND` in der Vorlage, Erzeugen des Tokens und Nachrüsten bestehender Instanzen in `LinuxServerDeployManager.swift` (wie bei web-automation). Nicht geprüft: ein Start dieser Images in einer frischen Instanz.
Author
Owner

PR #53 gemergt: feat(deploy): Dienst iris-browser in der Deploy-Vorlage, Token erzeugt der Server beim Start (browser_service.py) (iris/iris-plugins#123)
iris/iris-linux-server#53

Commits:

  • feat(deploy): Dienst iris-browser in der Deploy-Vorlage, Token erzeugt der Server beim Start (browser_service.py) (iris/iris-plugins#123)
PR #53 gemergt: feat(deploy): Dienst iris-browser in der Deploy-Vorlage, Token erzeugt der Server beim Start (browser_service.py) (iris/iris-plugins#123) https://forgejo.lewerken.duckdns.org/iris/iris-linux-server/pulls/53 Commits: - feat(deploy): Dienst iris-browser in der Deploy-Vorlage, Token erzeugt der Server beim Start (browser_service.py) (iris/iris-plugins#123)
Author
Owner

Deploy-Vorlage und Release v1.6.52 (linux-server 7274665, Tag v1.6.52, latest zeigt darauf)

  • Vorlage: docker-compose.deploy.yml.template hat den Dienst iris-browser (Image iris-browser:__VERSION__, /data nur lesend, data/browser-state für Profil und Zustand, Port nur auf 172.17.0.1:8095). Die Mac-App lädt die Vorlage der Version von Forgejo; die des Tags v1.6.52 enthält den Dienst.
  • Token ohne Platzhalter: app/browser_service.py setzt beim Start IRIS_BROWSER_DAEMON, IRIS_BROWSER_SANDBOX_DAEMON und IRIS_BROWSER_TOKEN selbst (Umgebung hat Vorrang, sonst Token einmalig in /data/browser-token, 0600); der Container liest die Datei. Dadurch keine Änderung an LinuxServerDeployManager.swift: syncMissingComposeServices hängt den fehlenden Dienstblock bei bestehenden Instanzen generisch an (wie damals bei web-automation), ein Eingriff in den server-Block bestehender Compose-Dateien entfällt.
  • Geprüft (Dev-Host): Token-Datei ohne Token in der Umgebung; Container ohne Token in der Umgebung startet mit dem Datei-Token; Agent-Weg aus einer Sandbox gegen ihn; falsches Token abgelehnt. Tests: 11 (Server, davon 5 neu für browser_service), 246 Einrichtungs-Tests grün. Release: alle sechs Images unter v1.6.52 und latest mit gleichem Digest (server 93c9858f6787, hermes eab4b5ae610f, tunnel ba5ed3c6c7cb, hermes-sandbox 3184bca6b07b, web-automation 77ebe85a1b05, browser a4fdd19cc3bf).
  • Nicht gesehen: eine frische Instanz aus der Vorlage mit v1.6.52 (Start aller Container) und das Nachrüsten einer bestehenden Instanz über „Iris-Server aktualisieren“ in der Mac-App.
**Deploy-Vorlage und Release v1.6.52** (linux-server `7274665`, Tag `v1.6.52`, `latest` zeigt darauf) - **Vorlage:** `docker-compose.deploy.yml.template` hat den Dienst `iris-browser` (Image `iris-browser:__VERSION__`, `/data` nur lesend, `data/browser-state` für Profil und Zustand, Port nur auf `172.17.0.1:8095`). Die Mac-App lädt die Vorlage der Version von Forgejo; die des Tags `v1.6.52` enthält den Dienst. - **Token ohne Platzhalter:** `app/browser_service.py` setzt beim Start `IRIS_BROWSER_DAEMON`, `IRIS_BROWSER_SANDBOX_DAEMON` und `IRIS_BROWSER_TOKEN` selbst (Umgebung hat Vorrang, sonst Token einmalig in `/data/browser-token`, 0600); der Container liest die Datei. Dadurch **keine Änderung an `LinuxServerDeployManager.swift`**: `syncMissingComposeServices` hängt den fehlenden Dienstblock bei bestehenden Instanzen generisch an (wie damals bei web-automation), ein Eingriff in den `server`-Block bestehender Compose-Dateien entfällt. - **Geprüft (Dev-Host):** Token-Datei ohne Token in der Umgebung; Container ohne Token in der Umgebung startet mit dem Datei-Token; Agent-Weg aus einer Sandbox gegen ihn; falsches Token abgelehnt. Tests: 11 (Server, davon 5 neu für `browser_service`), 246 Einrichtungs-Tests grün. Release: alle sechs Images unter `v1.6.52` und `latest` mit gleichem Digest (server `93c9858f6787`, hermes `eab4b5ae610f`, tunnel `ba5ed3c6c7cb`, hermes-sandbox `3184bca6b07b`, web-automation `77ebe85a1b05`, browser `a4fdd19cc3bf`). - **Nicht gesehen:** eine frische Instanz aus der Vorlage mit `v1.6.52` (Start aller Container) und das Nachrüsten einer bestehenden Instanz über „Iris-Server aktualisieren“ in der Mac-App.
Author
Owner

PR #162 gemergt: fix(browser): Plugin 0.4.2: fester Skill-Aufruf ohne Leerzeichen im Pfad, browser.mjs ausführbar, Version ohne plugin.json tolerant (#123)
#162

Commits:

  • fix(browser): Plugin 0.4.2: fester Skill-Aufruf ohne Leerzeichen im Pfad, browser.mjs ausführbar, Version ohne plugin.json tolerant (#123)
PR #162 gemergt: fix(browser): Plugin 0.4.2: fester Skill-Aufruf ohne Leerzeichen im Pfad, browser.mjs ausführbar, Version ohne plugin.json tolerant (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/162 Commits: - fix(browser): Plugin 0.4.2: fester Skill-Aufruf ohne Leerzeichen im Pfad, browser.mjs ausführbar, Version ohne plugin.json tolerant (#123)
Author
Owner

Befund vom MacBook und Fix (Plugin 0.4.2, 7c9512d, noch nicht veröffentlicht)

Nutzer: Iris habe auf silicon-macbook immer wieder Schwierigkeiten mit dem Browser. Angemeldet (lesend): Plugin 0.4.1 vollständig (node_modules, daemon.mjs, Hook), node unter /opt/homebrew/bin, Hermes-Toolset browser aus, Iris-Build 19:26.

  • Ursache: Der Agent scheiterte am Aufruf des Skills, nicht am Browser. Zwei Fälle im agent.log/agent_jobs.json: (1) Permission denied (exit 126): die Datei wurde direkt statt mit node ausgeführt; (2) Cannot find module '…/Application\ Support/…': Backslash vor dem Leerzeichen in Anführungszeichen; danach erklärte der Agent dem Nutzer, der Browser sei nicht installiert, und nahm web_search. Das SKILL.md ließ ihn einen Pfad mit Leerzeichen zusammensetzen.
  • Der Bericht des Nutzers (Prompt nicht „immer aktiv“, Umlaute doppelt codiert) traf nicht zu: Plugin-Prompts sind bewusst nicht immer aktiv (PluginManager.swift:928), der Installer liest system_prompt.md als UTF-8 (:902); auf dem Mac Studio sind die Umlaute im Speicher korrekt. Der Eingriff des Berichts-Agenten in die plist (Browser-Prompt „immer aktiv“) war nicht nötig.
  • Fix 0.4.2: fester Aufruf node ~/.hermes/skills/browser/browser.mjs … in SKILL.md (Skill-Ordner des Agenten, ohne Leerzeichen; Mac: Symlink ins Plugin, Linux: Kopie ohne plugin.json), andere Pfade und direktes Ausführen verboten, der Schluss „nicht installiert“ nach einem Aufruffehler verboten; browser.mjs ausführbar; pluginVersion() liefert ohne plugin.json null, der Dienst weist einen Client ohne Version nicht ab (sonst hätte die Linux-Kopie dev gemeldet und wäre abgelehnt worden). tests/smoke.sh prüft Symlink und Kopie, lokal und mit REMOTE=1; 14 Python-Tests.
  • Offen: 0.4.2 veröffentlichen und auf dem MacBook aktualisieren; danach dort den Test „Öffne den Browser und gehe zu …“ wiederholen. Der geänderte Browser-Prompt auf dem MacBook kann zurück auf „nicht immer aktiv“.
**Befund vom MacBook und Fix (Plugin 0.4.2, `7c9512d`, noch nicht veröffentlicht)** Nutzer: Iris habe auf `silicon-macbook` immer wieder Schwierigkeiten mit dem Browser. Angemeldet (lesend): Plugin 0.4.1 vollständig (`node_modules`, `daemon.mjs`, Hook), `node` unter `/opt/homebrew/bin`, Hermes-Toolset `browser` aus, Iris-Build 19:26. - **Ursache:** Der Agent scheiterte am Aufruf des Skills, nicht am Browser. Zwei Fälle im `agent.log`/`agent_jobs.json`: (1) `Permission denied` (exit 126): die Datei wurde direkt statt mit `node` ausgeführt; (2) `Cannot find module '…/Application\ Support/…'`: Backslash vor dem Leerzeichen in Anführungszeichen; danach erklärte der Agent dem Nutzer, der Browser sei nicht installiert, und nahm `web_search`. Das SKILL.md ließ ihn einen Pfad mit Leerzeichen zusammensetzen. - **Der Bericht des Nutzers** (Prompt nicht „immer aktiv“, Umlaute doppelt codiert) traf nicht zu: Plugin-Prompts sind bewusst nicht immer aktiv (`PluginManager.swift:928`), der Installer liest `system_prompt.md` als UTF-8 (`:902`); auf dem Mac Studio sind die Umlaute im Speicher korrekt. Der Eingriff des Berichts-Agenten in die `plist` (Browser-Prompt „immer aktiv“) war nicht nötig. - **Fix 0.4.2:** fester Aufruf `node ~/.hermes/skills/browser/browser.mjs …` in SKILL.md (Skill-Ordner des Agenten, ohne Leerzeichen; Mac: Symlink ins Plugin, Linux: Kopie ohne `plugin.json`), andere Pfade und direktes Ausführen verboten, der Schluss „nicht installiert“ nach einem Aufruffehler verboten; `browser.mjs` ausführbar; `pluginVersion()` liefert ohne `plugin.json` null, der Dienst weist einen Client ohne Version nicht ab (sonst hätte die Linux-Kopie `dev` gemeldet und wäre abgelehnt worden). `tests/smoke.sh` prüft Symlink und Kopie, lokal und mit `REMOTE=1`; 14 Python-Tests. - **Offen:** 0.4.2 veröffentlichen und auf dem MacBook aktualisieren; danach dort den Test „Öffne den Browser und gehe zu …“ wiederholen. Der geänderte Browser-Prompt auf dem MacBook kann zurück auf „nicht immer aktiv“.
Author
Owner

PR #163 gemergt: feat(browser): Store-Seite im Marktplatz: Icon, Langtext, Seite aus store-page.json (#123)
#163

Commits:

  • feat(browser): Store-Seite im Marktplatz: Icon, Langtext, Seite aus store-page.json (#123)
PR #163 gemergt: feat(browser): Store-Seite im Marktplatz: Icon, Langtext, Seite aus store-page.json (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/163 Commits: - feat(browser): Store-Seite im Marktplatz: Icon, Langtext, Seite aus store-page.json (#123)
Author
Owner

Store-Seite für iris-browser (e7a8261, Registry 250033e, „nur store/ aktualisiert“, Version bleibt 0.4.2)

Nutzer: Die Karte im Marktplatz sehe hässlich aus, es gebe keine Store-Konfiguration im Plugin.

  • Neu: store-page.json (Symbol window, Tagline „Ein Browser pro Chat, den du und Iris gemeinsam bedienen.“, 3 Schritte, Ablauf, 6 Merkmale, Beispielsätze aus dem Systemprompt des Plugins, Voraussetzungen, Hinweise), daraus store/hero.html und store/icon.svg (registry-tools/store_page.py, --check grün), dazu store/description.md (deutsch, Gliederung nach README Kapitel 20).
  • Geprüft: Seite lokal in Chromium gerendert und angesehen (nach Scrollen, sie blendet Abschnitte beim Scrollen ein); veröffentlicht mit publish-plugins.sh iris-browser (nur store/), in der Registry liegen description.md, hero.html, icon.svg.
  • Nicht gesehen: die Karte im Marktplatz selbst nach dem Neuladen. Keine Screenshots der App im Paket (die vorhandenen zeigen private Chats); store/custom.md mit echten Bildern wäre eine Ergänzung.
**Store-Seite für iris-browser** (`e7a8261`, Registry `250033e`, „nur store/ aktualisiert“, Version bleibt 0.4.2) Nutzer: Die Karte im Marktplatz sehe hässlich aus, es gebe keine Store-Konfiguration im Plugin. - Neu: `store-page.json` (Symbol `window`, Tagline „Ein Browser pro Chat, den du und Iris gemeinsam bedienen.“, 3 Schritte, Ablauf, 6 Merkmale, Beispielsätze aus dem Systemprompt des Plugins, Voraussetzungen, Hinweise), daraus `store/hero.html` und `store/icon.svg` (`registry-tools/store_page.py`, `--check` grün), dazu `store/description.md` (deutsch, Gliederung nach README Kapitel 20). - Geprüft: Seite lokal in Chromium gerendert und angesehen (nach Scrollen, sie blendet Abschnitte beim Scrollen ein); veröffentlicht mit `publish-plugins.sh iris-browser` (nur `store/`), in der Registry liegen `description.md`, `hero.html`, `icon.svg`. - Nicht gesehen: die Karte im Marktplatz selbst nach dem Neuladen. Keine Screenshots der App im Paket (die vorhandenen zeigen private Chats); `store/custom.md` mit echten Bildern wäre eine Ergänzung.
Author
Owner

PR #164 gemergt: feat(browser): lokale HTML-Dateien über automatisch gestarteten Webserver öffnen (#123)
#164

Commits:

  • feat(browser): lokale HTML-Dateien über automatisch gestarteten Webserver öffnen (#123)
PR #164 gemergt: feat(browser): lokale HTML-Dateien über automatisch gestarteten Webserver öffnen (#123) https://forgejo.lewerken.duckdns.org/iris/iris-plugins/pulls/164 Commits: - feat(browser): lokale HTML-Dateien über automatisch gestarteten Webserver öffnen (#123)
Author
Owner

Stand zu PR #164 (0.4.3): lokale HTML-Dateien

Befund: Auf silicon-macbook scheiterte „Öffne …/index.html mit dem Browser“ an der Sperre für file://; der Agent baute sich einen Webserver selbst.

Geändert: Neu lib/fileserver.mjs. Ein Pfad (absolut, ~/, relativ zum Workspace) oder file://… startet im Dienst einen Webserver je Basisverzeichnis (nur Loopback, freier Port, 30 min Leerlauf, max. 8); der Tab öffnet http://127.0.0.1:<Port>/<Datei>. Server: nur GET/HEAD, nur unter dem Basisverzeichnis (Symlinks aufgelöst), keine Punktdateien/-verzeichnisse, nur Web-Dateitypen, Host-Header geprüft; Wurzel/Home als Basis abgelehnt. SKILL.md nur eine Zeile.

Geprüft: tests/smoke.sh lokal und REMOTE=1 bestanden (Pfad, file://, relativ, fehlende Datei, Dateityp, 404 für .env und ../, 403 bei falschem Host).

Grenzen: Auf dem Linux-Server sieht der Container Host-Pfade nicht (Meldung „Datei nicht gefunden“). Panel-Adressleiste bleibt bei http(s). Noch nicht veröffentlicht (Registry steht auf 0.4.2).

**Stand zu PR #164 (0.4.3): lokale HTML-Dateien** **Befund:** Auf silicon-macbook scheiterte „Öffne …/index.html mit dem Browser“ an der Sperre für `file://`; der Agent baute sich einen Webserver selbst. **Geändert:** Neu `lib/fileserver.mjs`. Ein Pfad (absolut, `~/`, relativ zum Workspace) oder `file://…` startet im Dienst einen Webserver je Basisverzeichnis (nur Loopback, freier Port, 30 min Leerlauf, max. 8); der Tab öffnet `http://127.0.0.1:<Port>/<Datei>`. Server: nur GET/HEAD, nur unter dem Basisverzeichnis (Symlinks aufgelöst), keine Punktdateien/-verzeichnisse, nur Web-Dateitypen, Host-Header geprüft; Wurzel/Home als Basis abgelehnt. SKILL.md nur eine Zeile. **Geprüft:** `tests/smoke.sh` lokal und `REMOTE=1` bestanden (Pfad, `file://`, relativ, fehlende Datei, Dateityp, 404 für `.env` und `../`, 403 bei falschem Host). **Grenzen:** Auf dem Linux-Server sieht der Container Host-Pfade nicht (Meldung „Datei nicht gefunden“). Panel-Adressleiste bleibt bei http(s). Noch nicht veröffentlicht (Registry steht auf 0.4.2).
alf closed this issue 2026-10-21 23:33:47 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/iris-plugins#123
No description provided.