Plugin-Panel im rechten Seitenpanel — dritter Reiter „Plugin“, chat-gebunden, Plugin-UI im WKWebView #169
Labels
No labels
herkunft/alpha-feedback
status
blockiert
status
zu-testen
typ
bug
typ
docs
typ
enhancement
typ
feature
typ
idea
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
iris/Iris#169
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Kontext
Das rechte Seitenpanel im Chat-Fenster kennt zwei Inhalte: die verbundene Notiz und den Browser des
Chats. Umschaltung:
Iris/RemoteClientView.swift,enum Panels { case note, browser }undsidePanelSwitcher. Auf iOS dasselbe, handgemacht und nicht geteilt:frontend/ios/.../ChatNotePager.swift,enum ChatNotePage { case chat, note, browser }.Ein Plugin mit eigener Oberfläche bekommt davon nichts ab: seine Web-Seiten öffnen heute eigene
Fenster (
settingsWebViewPath→ „Konfigurieren",usageWebViewPath→ der „Plugins"-Chevron,beide über
HTMLPreviewWindowController.open). Ein Plugin, das mit dem Nutzer an einem Standarbeitet (FreeCAD-Viewer, Schnitt-Bridge), steht damit neben dem Chat statt darin — und Hermes
sieht diesen Stand nicht, weil er in einem Fenster lebt, das zu keinem Chat gehört.
Gewünscht: ein dritter Reiter „Plugin", chat-gebunden, sodass der Agent denselben Stand liest und
verändert wie der Nutzer.
Die Entscheidungen sind in einer grill-me-Sitzung am 2026-10-24 ausgehandelt und abgeschlossen.
Der vollständige Plan mit Begründungen, Datei-Inventar und Fallstricken liegt in
obsidian-docs/plans/SEITENPANEL-PLUGIN.md— vor dem ersten Commit lesen.Was gebaut wird
side_panel: "web/panel.html"(Pfad, kein Objekt —Label kommt aus
name). Gilt unabhängig vonprovidedBlockTypes; das bestehendewebViewPathist an Canvas-Blöcke gekoppelt und macht ohne sie nichts (
PluginManager.registerPluginWebView).PluginSidePanelRegistrynach VorbildPluginWebViewRegistry.has_side_panel_web_viewinGET /plugins(berechnet, Muster
has_settings_web_view) undGET /plugins/:id/side-panel-webview-url, das wiedie bestehenden Routen einen kurzlebigen
cfg_tokenmünzt. iOS: dritter Fall inenum PluginWebViewKind.chat_idin der URL nebencfg_token; die Seite schickt ihn bei jedempanel_api-Aufruf mit. Kein Sicherheitspfand — der Deckel ist Sichtbarmachung (Punkt 6).status, erweitert umsummary— nur verlangt, wennside_panelim Manifeststeht. Antwort:
{ok, chat_id, summary, detail}.summaryeine Zeile, von Iris auf 300 Zeichengekappt;
detailkommt nie automatisch in eine Nachricht. Vier Plugins habenstatusschon(filmcraft, iris-nextcloud-cookbook, iris-plugin-dev, iris-solidcraft).
PluginPanelView(macOS, WKWebView, Pinning wiePinnedWebView) und Gegenstückauf iOS neben
PluginCanvasWebView. Polling-Gating wieBrowserPanelModel. Weicht derzurückgegebene
chat_idvom gesendeten ab, zeigt der Reiter einen Fehler statt fremder Daten.statusalle ~5 s solange der Reiter offen ist (nie blockierend), beimSenden als Prefix aus dem Cache.
cursorContextPrefixwird zu generischemcontextPrefixmitzwei Lieferanten, fester Reihenfolge (Notiz zuerst). Keine Protokolländerung — der Server
sieht weiter nur
text.Panels(macOS) undChatNotePage(iOS), drittes Segment, drittesZStack-Kind nach dem opacity-/allowsHitTesting-Muster,.id(selectedJobID). Zweiter Pickerim Reiter, wenn mehrere Plugins ein Panel haben. Kein drittes Segment, wenn kein Plugin eines hat.
iris-solidcraftim selben Zug —viewer.htmlin den Reiter,statusum
summaryundchat_iderweitern, Skill dem Agenten die Schreibbefehle erklären.Bewusst so entschieden
Mechanismus gestülpt. Interne Plugin-Oberflächen sind eine andere Fläche.
Plugin-Autoren. Ein Formularstand, der nur im JS lebt, ist beim Chat-Wechsel weg.
detailselbst über die Befehle des Plugins; seinSkill muss sie ihm erklären.
chat_idnicht — Durchsetzen kann Iris nicht, ihr ist die Datenstruktur desPlugins unbekannt.
Fallstricke
irisCallist die Falle.PluginActionsCore.bridgeScriptführt Skripte auf dem Rechner desClients aus und existiert auf iOS nicht (kein einziges
WKUserScriptinfrontend/ios). Siewird in
CanvasPluginWebBlockVieweingespielt — wer den Host kopiert, bekommt sie gratis und bautein Panel, das auf iOS nicht läuft. Vertrag ist
panel_api.notePanelMinWidth/MaxWidth), ein echter WKWebViewlaid out in echter Breite, nicht skaliert wie das Browser-JPEG. Die Seite muss damit umgehen.
.frame(width: 180)(sidePanelSwitcher) und trägt drei Segmentenicht.
statusdarf nie blockieren — Manifeste erlauben Timeout bis 240 s (iris-server-hosts).Abgrenzung
Der Chat, der sich Notiz, Tabs und Panel merkt und alles in den Chat-Export bringt, ist ein
eigenes Issue danach. Notiz (
vaultNotePathamAgentJob) und Tabs (<jobID>-browserim Pluginiris-browser) liegen heute an verschiedenen Orten; ein halber generischer Mechanismus ist der
teuerste. Dieses Issue liefert die Voraussetzung:
statusmitsummary/detail, ohne laufendenClient aufrufbar.
PR #170 gemergt: feat(side-panel): Plugin-Reiter im rechten Seitenpanel — side_panel im Manifest, Route side-panel-webview-url, prüfbarer Kern, dritter Reiter (#169)
#170
Commits:
Stand — Plugin-Reiter gebaut (Mac)
Befund: Issue durchgrillt und geplant (
plans/SEITENPANEL-PLUGIN.md), Umsetzung in diesem Zug gebaut.Geändert:
InstalledPlugin.swift— viertes Web-View-FeldsidePanelWebViewPath(Coding-Keyside_panel);IrisRemoteServer.swift—has_side_panel_web_viewinGET /plugins(berechnet) und RouteGET /plugins/:id/side-panel-webview-url(cfg_token gemintet,chat_idhängt der Client an);PluginSidePanelCore.swift(neu, rein Foundation) — der prüfbare Vertrag: Pflichtbefehlstatusmit{ok, chat_id, summary, detail}, Auslegungvalid/mismatch/invalid, summary auf eine Zeile/300 Zeichen,Marker
[PLUGIN-PANEL: <Plugin>], Reihenfolge der Kontext-Marker; zugleich Quelle der iOS-Kopie(viertes Paar in
check-marketplace-page-sync).ChatNoteCursorRegistry.swift→ChatContextRegistry.swift(zwei Lieferanten, ein Prefix, feste Reihenfolge).
PluginSidePanelRegistry.swift,PluginPanelView.swift,PluginPanelModel.swift(neu) — dritter Reiter mit WKWebView, Polling nur bei offenem Reiter;RemoteClientView.swift,RemoteJobChatView.swift,RemoteServerClient.swift,AgentJob.swift,VaultNoteSourceEditor.swift— Reiter, Prefix-Versand, Client-Routen, Agenten-Hinweis.Geprüft:
scripts/test-plugin-side-panel-core.sh— 20 Prüfungen grün (chat_id-Abweichung,300-Zeichen-Kappung, Marker-Reihenfolge); Parse-Check aller geänderten Dateien;
swiftc -typecheckfür Core + Registries zusammen;check-marketplace-page-syncidentisch.Nicht geprüft: kein Xcode-Build von
Iris/IrisClient(neue Dateien liegen im synchronisiertenOrdner, brauchen keine pbxproj-Einträge — das bestätigt erst der Build); kein Klicktest, kein Reiter
gegen ein echtes Plugin.
Grenzen / offen:
iris-solidcraftals erster echter Fall noch nicht angepasst (wederside_panelim Manifest noch
summary/chat_idin seinemstatus); Gegenstücke: iOS (2ndbrain-ios), Linux-Server(iris-linux-server), Doku im Wurzel-Repo — werden im selben Zug geshippt. Issue bleibt mit
status/zu-testenoffen; Test im Alltag.PR #43 gemergt: feat(side-panel): Plugin-Reiter im Chat — dritter Reiter neben Notiz und Browser, panel_api ohne Bridge (#42, iris/Iris#169)
iris/2ndbrain-ios#43
Commits:
Stand — Plugin-Reiter gebaut (iOS)
Befund: Gegenstück zu iris/Iris#169, auf iOS gebaut.
Geändert:
Plugin.swift—hasSidePanelWebViewam Plugin-Eintrag,case sidePanelbeim Web-View-Typ(dieselbe Route wie auf dem Mac,
chat_idhängt der Client an);ChatPluginPanelPageView.swift(neu) —der Host, bewusst ohne Bridge: Vertrag ist
panel_api, nieirisCall; Zertifikat gegen den beimKoppeln gemerkten Fingerabdruck.
ChatPluginPanelRegistry.swift(neu) — Kontext-Lieferant pro Chat,Registrierung an Sichtbarkeit (onAppear/onChange(isVisible)), der Versand liest nur den Cache.
ChatNotePager.swift— dritterChatNotePage-Fall: Segment im schmalen Umschalter und im breitenSeitenbereich; Reiter fehlt ganz, wenn kein Plugin ein Panel hat.
AgentChatView.swift— Panel-Markerüber das Registry vor die Nachricht.
PluginSidePanelCore.swift— Kopie aus der Mac-App, viertesPaar in
tools/check-marketplace-page-sync.Geprüft: Parse-Check aller geänderten Dateien;
xcrun -sdk iphoneos swiftc -target arm64-apple-ios17.0 -typecheckfürPluginSidePanelCore.swift+ChatPluginPanelRegistry.swift(exit 0);check-marketplace-page-syncidentisch. Neue Dateien liegen im synchronisierten Root-Group-Ordner,kein pbxproj-Eintrag nötig.
Nicht geprüft: kein Xcode-Build des Targets, keine Installation auf einem Gerät, kein Reiter gegen
ein echtes Plugin.
Grenzen / offen: Speicher pro WKWebView (ein WKWebView je Chat) ist die offene Frage des Plans;
Cursor-Zeile der Notiz auf iOS noch nicht gebaut (CHAT-NOTIZ-CURSOR-KONTEXT Phase 2 offen — hier meldet
sich nur der Panel-Lieferant). Mac (iris/Iris#169), Linux-Server und Doku im Wurzel-Repo werden im
selben Zug geshippt. Issue bleibt mit
status/zu-testenoffen.PR #98 gemergt: feat(side-panel): Gegenstück zum Plugin-Reiter — side_panel im Index, side-panel-webview-url, PLUGIN-PANEL-Hinweis (#97, iris/Iris#169)
iris/iris-linux-server#98
Commits:
Stand — Gegenstück zum Plugin-Reiter gebaut (Linux-Server)
Befund: Der Linux-Server bildet das Mac-Original von iris/Iris#169 nach.
Geändert:
plugin_installer.py—side_panelaus dem Manifest in den Index-Eintrag (persistiert wieusage_web_view_path, das Wire-Feld wird daraus berechnet).plugins_routes.py—has_side_panel_web_viewin
GET /plugins(berechnet, bewusst ohnehas_settings_panel-Gate) undGET /plugins/{plugin_id}/side-panel-webview-urlals drittes Gegenstück zu config-/usage-webview-url:gleicher
_CFG_TOKENS-Namensraum, 16 Hex-Zeichen,/htmlserver/-Pfad,404wenn das Plugin fehlt oderkein
side_panelhat.agent_jobs.py— PLUGIN-PANEL-Abschnitt in_hermes_base_instructions, Wortlautidentisch zum Mac (
AgentJob.swift), bewusst unabhängig vonnote_line.ROUTES.md— die beidenfehlenden Web-View-Token-Routen und
POST /plugins/{id}/api/{command}nachgezogen.Was der Server nicht tut: die Chat-Kennung. Er mintet den plugin-gebundenen Token und sonst nichts;
chat_idhängt der Client an, der Server prüft es nie.Geprüft:
python3 -m py_compileüber die drei geänderten Dateien.Nicht geprüft: keine pytest-Suite für die neue Route —
tests/test_plugins.pydeckt config-, doc- undpanel_api-Routen ab, die neue nicht; ein Test nach dem Muster
test_plugin_config_route_accepts_cfg_token_without_bearerwäre die natürliche Ergänzung. Kein Lauf gegenalf@iris-server, kein Deploy per rsync, keindocker compose. Der Mac-Client wurde nicht gegen diesenServer getestet.
Grenzen / offen: Mac (iris/Iris#169), iOS (2ndbrain-ios#42) und die Doku im Wurzel-Repo werden im
selben Zug geshippt. Issue bleibt mit
status/zu-testenoffen.PR #107 gemergt: docs(wire): Plugin-Reiter im Seitenpanel — side_panel, side-panel-webview-url, Befehlsroute; PluginSidePanelCore.swift als viertes Kopien-Paar (iris/Iris#169)
alf/2ndbrain#107
Commits:
Stand — Plugin-Reiter gebaut (Mac)
Befund: Issue durchgrillt und geplant (
plans/SEITENPANEL-PLUGIN.md), Umsetzung in diesem Zug gebaut.Geändert:
InstalledPlugin.swift— viertes Web-View-FeldsidePanelWebViewPath(Coding-Keyside_panel);IrisRemoteServer.swift—has_side_panel_web_viewinGET /plugins(berechnet) und RouteGET /plugins/:id/side-panel-webview-url(cfg_token gemintet,chat_idhängt der Client an);PluginSidePanelCore.swift(neu, rein Foundation) — der prüfbare Vertrag: Pflichtbefehlstatusmit{ok, chat_id, summary, detail}, Auslegungvalid/mismatch/invalid, summary auf eine Zeile/300 Zeichen,Marker
[PLUGIN-PANEL: <Plugin>], Reihenfolge der Kontext-Marker; zugleich Quelle der iOS-Kopie(viertes Paar in
check-marketplace-page-sync).ChatNoteCursorRegistry.swift→ChatContextRegistry.swift(zwei Lieferanten, ein Prefix, feste Reihenfolge).
PluginSidePanelRegistry.swift,PluginPanelView.swift,PluginPanelModel.swift(neu) — dritter Reiter mit WKWebView, Polling nur bei offenem Reiter;RemoteClientView.swift,RemoteJobChatView.swift,RemoteServerClient.swift,AgentJob.swift,VaultNoteSourceEditor.swift— Reiter, Prefix-Versand, Client-Routen, Agenten-Hinweis.Geprüft:
scripts/test-plugin-side-panel-core.sh— 20 Prüfungen grün (chat_id-Abweichung,300-Zeichen-Kappung, Marker-Reihenfolge); Parse-Check aller geänderten Dateien;
swiftc -typecheckfür Core + Registries zusammen;check-marketplace-page-syncidentisch.Nicht geprüft: kein Xcode-Build von
Iris/IrisClient(neue Dateien liegen im synchronisiertenOrdner, brauchen keine pbxproj-Einträge — das bestätigt erst der Build); kein Klicktest, kein Reiter
gegen ein echtes Plugin.
Grenzen / offen:
iris-solidcraftals erster echter Fall noch nicht angepasst (wederside_panelim Manifest noch
summary/chat_idin seinemstatus); Gegenstücke: iOS (2ndbrain-ios), Linux-Server(iris-linux-server), Doku im Wurzel-Repo — werden im selben Zug geshippt. Issue bleibt mit
status/zu-testenoffen; Test im Alltag.Stand des ganzen Zugs — gebaut und geshippt, noch nicht getestet
Der Plugin-Reiter ist in allen vier Repos gemergt, jeder Teil auf seinem eigenen PR:
side_panel, Routeside-panel-webview-url,PluginSidePanelCore(prüfbarer Vertrag, Quelle der iOS-Kopie),ChatNoteCursorRegistry→ChatContextRegistry, dritter Reiter inRemoteClientView, Prefix-Versand, Agenten-HinweisChatNotePage-Fall,ChatPluginPanelPageViewohne Bridge, Registry für den Prefix, Kern als Kopieside_panelim Index,has_side_panel_web_view, Route, PLUGIN-PANEL-Hinweis byte-gleich zum Mac,ROUTES.mdnachgezogenside_panel/has_side_panel_web_viewim Plugin-System,PluginSidePanelCore.swiftals viertes Kopien-Paar im Vertrag und incheck-marketplace-page-syncGeprüft: Kern-Prüfskript
scripts/test-plugin-side-panel-core.sh(20 Prüfungen grün: chat_id-Abweichung, 300-Zeichen-Kappung, Marker-Reihenfolge); Parse-Checks Mac und iOS;swiftc -typecheck(Mac: Core + Registries; iOS:-sdk iphoneos -target arm64-apple-ios17.0für Core + Registry, exit 0);py_compileLinux;check-marketplace-page-sync— alle vier Paare identisch.Nicht geprüft: kein Xcode-Build von
Iris/IrisClient/iOS-Target, kein Gerät, kein Reiter gegen ein echtes Plugin, kein pytest für die neue Linux-Route, kein Deploy aufalf@iris-server.Offen:
iris-solidcraftals erster echter Fall anpassen (side_panelim Manifest,summary/chat_idin seinemstatus); iOS-Speicherfrage (ein WKWebView je Chat); pytest fürside-panel-webview-url.Alle drei Projekt-Issues (#169, 2ndbrain-ios#42, iris-linux-server#97) tragen
status/zu-testen— Test im Alltag, Schließen bleibt beim Nutzer. Branches sind aufgeräumt: alle Repos aufmain, die vier Platzhalter-Branches und die beiden toten 167-Branches in iris-plugins gelöscht.PR #171 gemergt: fix(side-panel): Buildfehler aus #169 — Self-Bezug auf AgentJob, Combine-Import, self in Logger-Interpolation (#169)
#171
Commits:
Befund: Der Build von #169 war nie gelaufen (Stand-Kommentar nannte ihn „nicht geprüft"). Xcode meldete drei Fehler.
Geändert:
AgentJob.swift(3295, 3806, 4126):Self.pluginPanelInstructionLine→AgentJob.pluginPanelInstructionLine. Die Interpolationen liegen inAgentJobManager;Selfmeint dort den Manager, das statische Glied gehört zuAgentJob.PluginPanelModel.swift:import Combineergänzt — das Ziel baut mitMemberImportVisibility,@Publishedkommt aus Combine,import SwiftUIgenügt nicht.PluginPanelModel.swift:109:self.jobID.uuidStringin der Logger-Interpolation (Autoclosure verlangt explizitesself).Geprüft:
xcodebuild -scheme Iris -configuration Debug buildgrün;-scheme IrisClientgrün;check-marketplace-page-syncalle vier Paare identisch.Nicht geprüft: unverändert aus #169 — kein Klicktest, kein Reiter gegen ein echtes Plugin,
iris-solidcraftnoch nicht angepasst.status/zu-testenbleibt.PR #172 gemergt: fix(side-panel): Seitenpanel-Registry auch beim App-Start füllen — Reiter überlebte keinen Neustart (#169)
#172
Commits:
Befund: Beim App-Start wurden nur Canvas-Blöcke, Settings-Panel und Web-View neu registriert —
registerPluginSidePanelfehlte in dieser Schleife (PluginManager.swift:1209). Die Registry ist rein im Speicher: nach einem Iris-Neustart warhas_side_panel_web_viewzwar im Index, aber der Reiter fand keine Entry-Datei. Aufgetaucht beim ersten echten Fall (iris-solidcraft 0.2.0, iris/iris-plugins).Geändert:
registerPluginSidePanel(for:pluginID:)in die Start-Schleife ergänzt — dieselbe Stelle, an der die drei anderen Registrierungen schon stehen.Geprüft:
xcodebuild -scheme Iris -configuration Debug buildgrün.Nicht geprüft: kein Neustart-Klicktest (Reiter nach Iris-Neustart mit installiertem iris-solidcraft 0.2.0).
status/zu-testenbleibt.Mit im Commit:
Localizable.xcstrings— Xcode hat die drei neuen Texte aus #169 (Plugin-Reiter) automatisch extrahiert.PR #48 gemergt: fix(side-panel): iOS — Plugin-Wechsel lädt die Seite, Auswahl als Dropdown (iris/Iris#169)
iris/2ndbrain-ios#48
Commits:
Befund: In der iOS-App wechselte die Plugin-Auswahl im Seitenpanel den Namen, aber nicht die Seite: die WebView-
identhielt nur Chat und Reload-Zähler,PinnedRemoteHTMLViewlädt inupdateUIViewnie neu. Zusätzlich war die segmentierte Pillenliste bei sechs und mehr Plugins unlesbar (Namen gekürzt).Geändert: Auswahl als Dropdown (Menü mit Häkchen am aktiven Plugin); die WebView-
identhält die Plugin-ID, ein Wechsel lädt die neue Seite.Geprüft:
xcodebuildgrün.Nicht geprüft: Wechsel auf dem Gerät (nach der Installation).
PR #49 gemergt: fix(side-panel): iOS — Plugin-Wechsel zeigt nie die Seite des vorigen Plugins (iris/Iris#169)
iris/2ndbrain-ios#49
Commits:
Befund: Der Dropdown-Fix aus #48 reichte nicht: Beim Wechsel änderte sich die Plugin-ID sofort, die neue Adresse kam erst nach dem Server-Aufruf. Die neu angelegte WebView bekam dadurch noch die Adresse des vorigen Plugins und lud nie neu (Kopfzeile „Buchhaltung“, Inhalt „Hintergrundjobs“).
Geändert:
selectPluginleert die Adresse sofort; die WebView-Identität hängt an der Adresse, nicht an der Plugin-ID.Geprüft:
xcodebuildgrün; Ursache aus dem Screenshot (Kopfzeile und Statuszeile Buchhaltung, Inhalt Hintergrundjobs) abgeleitet.Nicht geprüft: Wechsel auf dem Gerät vor dem Einreichen.
PR #50 gemergt: fix(side-panel): iOS — Randwisch wechselt zur Nachbarseite (Notiz ↔ Browser ↔ Plugin) (iris/Iris#169)
iris/2ndbrain-ios#50
Commits:
Befund: Auf dem iPhone ließ sich nur zwischen Chat und Notiz wischen. Auf Notiz-, Browser- und Plugin-Seite ist das freie Seiten-Scrollen bewusst aus (Tabellen, Textauswahl, Block-Ziehen, WebViews); die einzige Randzone führte immer zum Chat.
Geändert: Randzonen (32 pt) führen zur jeweiligen Nachbarseite: links zur vorigen, rechts zur nächsten (Notiz → Browser → Plugin). Freies Wischen bleibt dem Inhalt.
Geprüft:
xcodebuildgrün.Nicht geprüft: Gestik auf dem Gerät; ob die rechte Randzone im Browser mit Seiten-Gesten der WebView kollidiert. Nicht installiert.