ChatPanel: layout de nivel superior y ensamblaje de herramientas
ChatPanel es el customElement de nivel superior de pi-web-ui (<pi-chat-panel>). No corre la sesión; ensambla AgentInterface, ArtifactsPanel y toolsFactory: recibe el Agent externo, crea el child agent-interface y le asigna session, alterna entre layouts de artifacts "lado a lado" y "overlay" según el ancho de pantalla, y llama a toolsFactory para que el host inyecte AgentTool adicionales.
Responsabilidades
- Mantener agent y agentInterface:
@state agenty@state agentInterface;agentlo pasa el host,agentInterfacese crea condocument.createElementensetAgent. Verpackages/web-ui/src/ChatPanel.ts:17-25. - Ensamlar host de sesión:
setAgentcrea elAgentInterface, fija los callbacksenableAttachments/onApiKeyRequired/onBeforeSendy cuelga elagentcomosession. Verpackages/web-ui/src/ChatPanel.ts:56-85. - Ensamlar panel de artifacts:
new ArtifactsPanel(), inyectasandboxUrlProvider, registraArtifactsToolRendereren la registry de renderers. Verpackages/web-ui/src/ChatPanel.ts:86-94. - Construir runtime providers:
runtimeProvidersFactoryagrega los attachments del historial de sesión en unAttachmentsRuntimeProvider, más unArtifactsRuntimeProviderreadable/writable, para que las herramientas REPL los consuman. Verpackages/web-ui/src/ChatPanel.ts:96-116. - Layout responsivo: si
windowWidth < 800va a overlay; si no, lado a lado 50/50; cuando artifacts está colapsado se muestra un pill flotante. Verpackages/web-ui/src/ChatPanel.ts:159-208.
Motivación de diseño
¿Por qué el ensamblaje del ArtifactsPanel está en ChatPanel y no en AgentInterface? Porque artifacts es un concepto de la dimensión "producto de sesión", desacoplado del render de la lista de mensajes: AgentInterface sólo mira el flujo de mensajes; ArtifactsPanel sólo mira los mensajes artifact y mantiene su propio Map de artifacts. Ambos comparten datos a través de agent.state, pero sus ciclos de vida y posiciones de UI son distintos. ChatPanel como capa de layout los ensambla y a la vez expone toolsFactory al host, para que el host pueda inyectar herramientas de negocio (p. ej. query_database para una app concreta) sin tocar el código de pi-web-ui.
BREAKPOINT = 800 es un valor empírico: en pantallas estrechas los artifacts cubren toda el área de chat para evitar que las dos columnas queden ilegibles; en anchas se muestran lado a lado para charlar y ver productos a la vez. overlay y collapsed los empuja ChatPanel desde render hacia ArtifactsPanel, en vez de dejar que el panel escuche el resize, para concentrar las decisiones de layout en el nivel superior.
Archivos clave
packages/web-ui/src/ChatPanel.ts:17-25— Declaración declass ChatPanely campos de estado.packages/web-ui/src/ChatPanel.ts:36-49—connectedCallback: inicializawindowWidth, cuelga el listenerresize, fija el layout flex.packages/web-ui/src/ChatPanel.ts:56-85—setAgentprimera mitad: creaAgentInterface, cuelgasession, pasa callbacks.packages/web-ui/src/ChatPanel.ts:86-116— Ensamblaje del panel de artifacts, closure deruntimeProvidersFactory.packages/web-ui/src/ChatPanel.ts:118-157— Callback de cambios de artifacts yreconstructFromMessages(reconstruye artifacts desde el historial).packages/web-ui/src/ChatPanel.ts:141-144— Invocación detoolsFactory, asigna[artifactsPanel.tool, ...additionalTools]aagent.state.tools.packages/web-ui/src/ChatPanel.ts:159-208—render: cambia layout segúnwindowWidth/hasArtifacts/showArtifactsPanel, renderiza el pill flotante.
En setAgent la creación del AgentInterface y la inyección de callbacks es la juntura entre host y host de sesión:
// 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 permite al host inyectar herramientas adicionales, mientras que la herramienta de artifacts siempre se añade primero:
// 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;Flujo de datos
setAgent es la línea principal que ensambla el Agent pasado por el host en una UI usable:
El cambio de layout lo conduce el estado evaluado en render:
Límites y fallos
- Agent sin setear:
rendermuestra "No agent set", evitando crashear cuandoagentInterfacees undefined. Verpackages/web-ui/src/ChatPanel.ts:160-164. - Suprime auto-expansión en reconstrucción: antes de
reconstructFromMessagesse poneonArtifactsChangea null temporalmente, evitando que los artifacts históricos disparen el panel automáticamente. Verpackages/web-ui/src/ChatPanel.ts:148-151. - Cuenta de artifacts en 0:
hasArtifacts=false,showArtifactsPanel=false, el pill no se renderiza y el panel derecho se oculta. - Sólo auto-expande artifacts nuevos: sólo cuando
count > artifactCountse poneshowArtifactsPanela true, evitando que artifacts ya presentes al reaparecer fuercen el popup. Verpackages/web-ui/src/ChatPanel.ts:118-127. - Limpieza del listener resize:
disconnectedCallbackquita el listener dewindow.resizepara evitar leaks. Verpackages/web-ui/src/ChatPanel.ts:51-54.
Resumen
ChatPanel es la capa de layout + taller de ensamblaje: monta AgentInterface, ArtifactsPanel y toolsFactory, y alterna layout según el ancho de ventana. Hacia dentro está host de sesión AgentInterface; el mecanismo de registro de render de herramientas en registro de renderers de herramientas.