ChatPanel: Top-Level-Layout und Tool-Verdrahtung
ChatPanel ist das Top-Level-customElement (<pi-chat-panel>) von pi-web-ui. Es treibt selbst keine Konversation, sondern setzt AgentInterface, ArtifactsPanel und toolsFactory zusammen: Es nimmt den von außen übergebenen Agent, erzeugt ein agent-interface-Kindelement und weist ihm die session zu, schaltet je nach Bildschirmbreite zwischen „Side-by-side" und „Overlay"-Layout für die Artifacts um und ruft toolsFactory auf, damit der Host zusätzliche AgentTool injizieren kann.
Zuständigkeiten
- agent und agentInterface halten: Die Felder
@state agentund@state agentInterface.agentwird vom Host übergeben,agentInterfaceinsetAgentperdocument.createElementerzeugt. Siehepackages/web-ui/src/ChatPanel.ts:17-25. - Session-Host verdrahten:
setAgenterzeugt dasAgentInterface, setzt die CallbacksenableAttachments/onApiKeyRequired/onBeforeSendund hängt denagentalssessionan. Siehepackages/web-ui/src/ChatPanel.ts:56-85. - Artifacts-Panel verdrahten:
new ArtifactsPanel(), injiziertsandboxUrlProvider, registriert denArtifactsToolRendererin der renderer registry. Siehepackages/web-ui/src/ChatPanel.ts:86-94. - Runtime providers aufbauen:
runtimeProvidersFactoryfasst die Anhänge aus der Konversationshistorie in einemAttachmentsRuntimeProviderzusammen und fügt den read-writeArtifactsRuntimeProviderhinzu, damit REPL-Tools sie konsumieren können. Siehepackages/web-ui/src/ChatPanel.ts:96-116. - Responsive Layout:
windowWidth < 800schaltet auf Overlay, sonst Side-by-side 50/50; bei eingeklappten Artifacts wird ein schwebendes Pill angezeigt. Siehepackages/web-ui/src/ChatPanel.ts:159-208.
Designmotivation
Warum wird die Verdrahtung des ArtifactsPanel in ChatPanel statt in AgentInterface gemacht? Weil Artifacts ein Konzept der Dimension „Konversationsprodukte" sind und von der Nachrichtenliste entkoppelt sind: AgentInterface sieht nur den Nachrichtenstrom, ArtifactsPanel sieht nur Artifact-Nachrichten und pflegt seine eigene artifacts-Map. Beide teilen Daten über agent.state, haben aber unterschiedliche Lebensdauer und UI-Position. ChatPanel baut sie als Layout-Schicht zusammen und gibt toolsFactory an den Host weiter, damit dieser fachliche Werkzeuge (z. B. query_database einer App) injizieren kann, ohne pi-web-ui-Quelle ändern zu müssen.
BREAKPOINT = 800 ist ein Erfahrungswert: Auf schmalen Bildschirmen überlagert das Artifacts-Panel den Chat vollflächig, damit nicht beide Spalten unleserlich zusammengedrückt werden; auf breiten Bildschirmen stehen sie Seite an Seite, damit man beim Chatten gleichzeitig die Produkte sieht. overlay und collapsed werden von ChatPanel in render an das ArtifactsPanel geschoben, anstatt das Panel selbst auf Window-Events zu hören — Layout-Entscheidungen bleiben an der Spitze konzentriert.
Wichtige Dateien
packages/web-ui/src/ChatPanel.ts:17-25—class ChatPanel-Deklaration und Zustandsfelder.packages/web-ui/src/ChatPanel.ts:36-49—connectedCallback: initialisiertwindowWidth, bindetresize-Listener, setzt flex-Layout.packages/web-ui/src/ChatPanel.ts:56-85—setAgenterste Hälfte: erzeugtAgentInterface, hängtsessionan, reicht Callbacks durch.packages/web-ui/src/ChatPanel.ts:86-116— Artifacts-Panel-Verdrahtung undruntimeProvidersFactory-Closure.packages/web-ui/src/ChatPanel.ts:118-157— Artifacts-Änderungs-Callback undreconstructFromMessages(Artifacts aus historischen Nachrichten wiederherstellen).packages/web-ui/src/ChatPanel.ts:141-144—toolsFactory-Aufruf, der[artifactsPanel.tool, ...additionalTools]anagent.state.toolszuweist.packages/web-ui/src/ChatPanel.ts:159-208—render: wechselt Layout nachwindowWidth/hasArtifacts/showArtifactsPanel, rendert das schwebende Pill.
In setAgent sind Erzeugung des AgentInterface und Injektion der Callbacks die Naht zwischen Host und Session-Host:
// packages/web-ui/src/ChatPanel.ts:74-84
this.agentInterface = document.createElement("agent-interface") as AgentInterface;
this.agentInterface.session = agent;
this.agentInterface.enableAttachments = true;
this.agentInterface.enableModelSelector = true;
this.agentInterface.enableThinkingSelector = true;
this.agentInterface.showThemeToggle = false;
this.agentInterface.onApiKeyRequired = config?.onApiKeyRequired;
this.agentInterface.onModelSelect = config?.onModelSelect;
this.agentInterface.onBeforeSend = config?.onBeforeSend;
this.agentInterface.onCostClick = config?.onCostClick;toolsFactory lässt den Host weitere Tools injizieren; das artifacts-Tool wird immer als erstes eingefügt:
// packages/web-ui/src/ChatPanel.ts:141-144
const additionalTools =
config?.toolsFactory?.(agent, this.agentInterface, this.artifactsPanel, runtimeProvidersFactory) || [];
const tools = [this.artifactsPanel.tool, ...additionalTools];
this.agent.state.tools = tools;Datenfluss
setAgent ist eine Hauptlinie, die den vom Host übergebenen Agent zu einer funktionierenden UI verdrahtet:
Der Layout-Wechsel wird von den Zustandsprüfungen in render angetrieben:
Randbedingungen und Fehler
- agent nicht gesetzt:
renderzeigt direkt „No agent set", damit bei undefinedagentInterfacenichts crasht. Siehepackages/web-ui/src/ChatPanel.ts:160-164. - Auto-Aufklappen beim Wiederherstellen unterdrücken: Vor
reconstructFromMessageswirdonArtifactsChangetemporär auf null gesetzt, damit historische Artifacts nicht das Panel automatisch aufklappen. Siehepackages/web-ui/src/ChatPanel.ts:148-151. - Artifacts-Anzahl ist 0:
hasArtifacts=false,showArtifactsPanel=false, das Pill wird nicht gerendert, das rechte Panel versteckt. - Nur neue Artifact klappen auf: Nur wenn
count > artifactCount, wirdshowArtifactsPanelauf true gesetzt, damit ein wieder auftauchendes, bereits bekanntes Artifact nicht das Panel aufzwingt. Siehepackages/web-ui/src/ChatPanel.ts:118-127. - resize-Listener aufräumen:
disconnectedCallbackentfernt denwindow.resize-Listener, kein Leak. Siehepackages/web-ui/src/ChatPanel.ts:51-54.
Zusammenfassung
ChatPanel ist Layout-Schicht und Verdrahtungswerkstatt: setzt AgentInterface, ArtifactsPanel und toolsFactory zusammen und schaltet das Layout nach Fensterbreite um. Nach innen liegt der AgentInterface Session-Host; wie das Render-Interface für Tools registriert wird, steht in Tool-Renderer-Registry.