ChatPanel : mise en page de haut niveau et assemblage des outils
ChatPanel est le customElement de haut niveau de pi-web-ui (<pi-chat-panel>). Il ne gère pas lui-même la session ; il assemble AgentInterface, ArtifactsPanel et toolsFactory : il reçoit un Agent passé par l'extérieur, crée l'élément enfant agent-interface et lui assigne session, bascule entre deux dispositions d'artifacts (« côte à côte » et « superposé ») selon la largeur de l'écran, et appelle toolsFactory pour que l'hôte injecte des AgentTool supplémentaires.
Responsabilités
- Détient agent et agentInterface : deux champs
@state agentet@state agentInterface;agentest fourni par l'hôte,agentInterfaceest créé danssetAgentviadocument.createElement, voirpackages/web-ui/src/ChatPanel.ts:17-25. - Assemble l'hôte de session :
setAgentcréeAgentInterface, configure les callbacksenableAttachments/onApiKeyRequired/onBeforeSend, et attacheagentcommesession, voirpackages/web-ui/src/ChatPanel.ts:56-85. - Assemble le panneau d'artifacts :
new ArtifactsPanel(), injection desandboxUrlProvider, enregistrement deArtifactsToolRendererdans le registry des renderers, voirpackages/web-ui/src/ChatPanel.ts:86-94. - Construit les runtime providers :
runtimeProvidersFactoryagrège les pièces jointes de l'historique enAttachmentsRuntimeProvider, auquel s'ajoute unArtifactsRuntimeProvideren lecture/écriture, consommés par les outils REPL, voirpackages/web-ui/src/ChatPanel.ts:96-116. - Mise en page responsive :
windowWidth < 800bascule en overlay, sinon côte à côte 50/50 ; quand les artifacts sont repliés, on affiche un pill flottant, voirpackages/web-ui/src/ChatPanel.ts:159-208.
Motivations de design
Pourquoi avoir placé l'assemblage de l'ArtifactsPanel dans ChatPanel plutôt que dans AgentInterface ? Parce que les artifacts relèvent du concept de « produit de session », découplé du rendu de la liste de messages : AgentInterface ne voit que le flux de messages, ArtifactsPanel ne voit que les messages d'artifact et maintient sa propre Map artifacts. Les deux partagent les données via agent.state, mais leur cycle de vie et leur emplacement UI diffèrent. ChatPanel, en tant que couche de mise en page, les assemble et expose en même temps toolsFactory à l'hôte, pour que ce dernier puisse injecter des outils métier (par exemple un query_database propre à une app) sans toucher au code source de pi-web-ui.
BREAKPOINT = 800 est une valeur empirique : sur écran étroit, les artifacts passent en superposition plein écran sur la zone de chat, sinon les deux colonnes seraient trop compressées pour être lisibles ; sur écran large, l'affichage côte à côte permet de discuter tout en consultant les artefacts. overlay et collapsed sont poussés vers ArtifactsPanel par ChatPanel dans render selon l'état courant, plutôt que de laisser le panneau écouter lui-même la fenêtre — ainsi les décisions de mise en page restent centralisées au plus haut niveau.
Fichiers clés
packages/web-ui/src/ChatPanel.ts:17-25— déclaration declass ChatPanelet champs d'état.packages/web-ui/src/ChatPanel.ts:36-49—connectedCallback:windowWidthinitial, branchement du listenerresize, mise en flex.packages/web-ui/src/ChatPanel.ts:56-85— première moitié desetAgent: création deAgentInterface, attachement desession, forward des callbacks.packages/web-ui/src/ChatPanel.ts:86-116— assemblage du panneau d'artifacts, fermetureruntimeProvidersFactory.packages/web-ui/src/ChatPanel.ts:118-157— callback de changement d'artifacts etreconstructFromMessages(reconstruction des artifacts depuis l'historique).packages/web-ui/src/ChatPanel.ts:141-144— appel àtoolsFactory, assignation de[artifactsPanel.tool, ...additionalTools]àagent.state.tools.packages/web-ui/src/ChatPanel.ts:159-208—render: bascule de layout selonwindowWidth/hasArtifacts/showArtifactsPanel, rendu du pill flottant.
Dans setAgent, la création de AgentInterface et l'injection des callbacks constituent la couture entre l'hôte et l'hôte de session :
// 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 permet à l'hôte d'injecter des outils supplémentaires, mais l'outil d'artifacts est toujours le premier de la liste :
// 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;Flux de données
setAgent est le fil rouge qui assemble l'Agent reçu de l'hôte en une UI utilisable :
La bascule de layout est pilotée par les conditions dans render :
Limites et cas d'échec
- Agent non défini :
renderaffiche « No agent set » pour éviter un crash quandagentInterfaceest undefined, voirpackages/web-ui/src/ChatPanel.ts:160-164. - Suppression de l'auto-expansion à la reconstruction : avant
reconstructFromMessages, on neutralise temporairementonArtifactsChangepour éviter que les artifacts historiques ne déclenchent l'ouverture automatique du panneau, voirpackages/web-ui/src/ChatPanel.ts:148-151. - Compteur d'artifacts à 0 :
hasArtifacts=false,showArtifactsPanel=false, le pill n'est pas rendu, le panneau de droite est masqué. - Auto-expansion seulement pour les nouveaux artifacts :
showArtifactsPanelne passe à true que sicount > artifactCount, pour éviter qu'un artifact déjà présent ne force une popup en réapparaissant, voirpackages/web-ui/src/ChatPanel.ts:118-127. - Nettoyage du listener resize :
disconnectedCallbackretire le listenerwindow.resizepour éviter une fuite, voirpackages/web-ui/src/ChatPanel.ts:51-54.
Pour résumer
ChatPanel est la couche de mise en page et l'atelier d'assemblage : il branche AgentInterface, ArtifactsPanel et toolsFactory, et bascule la disposition selon la largeur de la fenêtre. Vers l'intérieur, voir AgentInterface, hôte de session ; pour le mécanisme d'enregistrement des renderers d'outils, voir Registre des renderers d'outils.