Skip to content

ChatPanel : mise en page de haut niveau et assemblage des outils

源码版本v0.73.1

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

  1. Détient agent et agentInterface : deux champs @state agent et @state agentInterface ; agent est fourni par l'hôte, agentInterface est créé dans setAgent via document.createElement, voir packages/web-ui/src/ChatPanel.ts:17-25.
  2. Assemble l'hôte de session : setAgent crée AgentInterface, configure les callbacks enableAttachments/onApiKeyRequired/onBeforeSend, et attache agent comme session, voir packages/web-ui/src/ChatPanel.ts:56-85.
  3. Assemble le panneau d'artifacts : new ArtifactsPanel(), injection de sandboxUrlProvider, enregistrement de ArtifactsToolRenderer dans le registry des renderers, voir packages/web-ui/src/ChatPanel.ts:86-94.
  4. Construit les runtime providers : runtimeProvidersFactory agrège les pièces jointes de l'historique en AttachmentsRuntimeProvider, auquel s'ajoute un ArtifactsRuntimeProvider en lecture/écriture, consommés par les outils REPL, voir packages/web-ui/src/ChatPanel.ts:96-116.
  5. Mise en page responsive : windowWidth < 800 bascule en overlay, sinon côte à côte 50/50 ; quand les artifacts sont repliés, on affiche un pill flottant, voir packages/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

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 :

typescript
// 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 :

typescript
// 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 : render affiche « No agent set » pour éviter un crash quand agentInterface est undefined, voir packages/web-ui/src/ChatPanel.ts:160-164.
  • Suppression de l'auto-expansion à la reconstruction : avant reconstructFromMessages, on neutralise temporairement onArtifactsChange pour éviter que les artifacts historiques ne déclenchent l'ouverture automatique du panneau, voir packages/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 : showArtifactsPanel ne passe à true que si count > artifactCount, pour éviter qu'un artifact déjà présent ne force une popup en réapparaissant, voir packages/web-ui/src/ChatPanel.ts:118-127.
  • Nettoyage du listener resize : disconnectedCallback retire le listener window.resize pour éviter une fuite, voir packages/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.