From 302899638bc586a2974484b6f79780c734bb0b8a Mon Sep 17 00:00:00 2001 From: Brian Love Date: Tue, 19 May 2026 10:09:39 -0700 Subject: [PATCH] fix(cockpit-chat): render messages in primitive-style demos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c-messages and c-input use standalone (intentionally, per their docstrings, to demonstrate primitive composition). The list discovers projected `` blocks via contentChildren; with none projected, every findTemplate call returns undefined and nothing renders. Project the minimal four templates (human, ai, tool, system) matching the defaults that the composed component provides internally. Templates use ChatMessageComponent + ChatStreamingMdComponent — the public primitives — so the demos still showcase "use the primitives directly without composition" as the docstrings intend. Unblocks Task #4's c-messages aimock e2e pilot (PR #462 was closed when this bug surfaced — the e2e was timing out waiting for assistant bubbles that never rendered). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../input/angular/src/app/input.component.ts | 47 +++++++++++++++++-- .../angular/src/app/messages.component.ts | 44 ++++++++++++++++- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/cockpit/chat/input/angular/src/app/input.component.ts b/cockpit/chat/input/angular/src/app/input.component.ts index 142f42d2..2a11e36a 100644 --- a/cockpit/chat/input/angular/src/app/input.component.ts +++ b/cockpit/chat/input/angular/src/app/input.component.ts @@ -1,7 +1,13 @@ // SPDX-License-Identifier: MIT import { Component, computed } from '@angular/core'; -import { ChatInputComponent as ChatInputPrimitive } from '@ngaf/chat'; -import { ChatMessageListComponent } from '@ngaf/chat'; +import { + ChatInputComponent as ChatInputPrimitive, + ChatMessageListComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + messageContent, +} from '@ngaf/chat'; import { ExampleChatLayoutComponent } from '@ngaf/example-layouts'; import { agent } from '@ngaf/langgraph'; import { environment } from '../environments/environment'; @@ -10,11 +16,23 @@ import { environment } from '../environments/environment'; * InputComponent showcases ChatInputComponent features including * keyboard handling, disabled state, and custom placeholder. * A sidebar displays the current input state. + * + * ChatMessageListComponent renders nothing on its own — it discovers + * projected `` blocks via + * contentChildren. Templates are projected here so the conversation + * surface actually displays user + assistant turns. */ @Component({ selector: 'app-input', standalone: true, - imports: [ChatInputPrimitive, ChatMessageListComponent, ExampleChatLayoutComponent], + imports: [ + ChatInputPrimitive, + ChatMessageListComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + ExampleChatLayoutComponent, + ], template: `
@@ -22,7 +40,27 @@ import { environment } from '../environments/environment';

Chat Input Demo

- + + + {{ messageContent(message) }} + + + + + + + + + {{ messageContent(message) }} + +
@@ -59,6 +97,7 @@ export class InputComponent { protected readonly streamStatus = computed(() => this.agent.status()); protected readonly isLoading = computed(() => this.agent.isLoading()); + protected readonly messageContent = messageContent; submitMessage(content: string) { this.agent.submit({ message: content }); diff --git a/cockpit/chat/messages/angular/src/app/messages.component.ts b/cockpit/chat/messages/angular/src/app/messages.component.ts index 516d7f0d..259fad8a 100644 --- a/cockpit/chat/messages/angular/src/app/messages.component.ts +++ b/cockpit/chat/messages/angular/src/app/messages.component.ts @@ -4,6 +4,10 @@ import { ChatMessageListComponent, ChatInputComponent, ChatTypingIndicatorComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + messageContent, } from '@ngaf/chat'; import { ExampleChatLayoutComponent } from '@ngaf/example-layouts'; import { agent } from '@ngaf/langgraph'; @@ -15,11 +19,25 @@ import { environment } from '../environments/environment'; * Uses ChatMessageListComponent, ChatInputComponent, and ChatTypingIndicatorComponent * individually rather than the composed ChatComponent, giving full control * over layout and message rendering. + * + * ChatMessageListComponent renders nothing on its own — it discovers + * projected `` blocks via + * contentChildren and uses them per message type. The composed `` + * component provides default templates internally; primitive consumers + * must project them explicitly. */ @Component({ selector: 'app-messages', standalone: true, - imports: [ChatMessageListComponent, ChatInputComponent, ChatTypingIndicatorComponent, ExampleChatLayoutComponent], + imports: [ + ChatMessageListComponent, + ChatInputComponent, + ChatTypingIndicatorComponent, + ChatMessageComponent, + ChatStreamingMdComponent, + MessageTemplateDirective, + ExampleChatLayoutComponent, + ], template: `
@@ -27,7 +45,27 @@ import { environment } from '../environments/environment';

Chat Messages Primitives

- + + + {{ messageContent(message) }} + + + + + + + + + {{ messageContent(message) }} + +
@@ -52,6 +90,8 @@ export class MessagesComponent { assistantId: environment.streamingAssistantId, }); + protected readonly messageContent = messageContent; + submitMessage(content: string) { this.agent.submit({ message: content }); }