{
  "name": "AgentMessageList",
  "category": "AI",
  "subcategory": null,
  "description": "Chat message stream for AI agents with role-based styling.",
  "thumbnail": "/preview-cards/agent-message-list.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/AgentMessageList/AgentMessage.razor",
    "UI/AgentMessageList/AgentMessageList.razor"
  ],
  "dependencies": [],
  "packageDependencies": [],
  "cssVars": [
    "--color-foreground",
    "--color-muted",
    "--color-muted-foreground",
    "--color-primary",
    "--color-primary-foreground",
    "--radius"
  ],
  "api": {
    "name": "AgentMessageList",
    "category": "AI",
    "subcategory": null,
    "description": "Chat message stream for AI agents with role-based styling.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/AgentMessageList/AgentMessage.razor",
      "UI/AgentMessageList/AgentMessageList.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [
      "IAsyncDisposable"
    ],
    "parameters": [
      {
        "name": "ChildContent",
        "type": "RenderFragment?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AutoScroll",
        "type": "bool",
        "default": "true",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Class",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AdditionalAttributes",
        "type": "Dictionary<string, object>?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": true
      }
    ],
    "events": [],
    "enums": [],
    "records": [],
    "cssVars": [
      "--color-foreground",
      "--color-muted",
      "--color-muted-foreground",
      "--color-primary",
      "--color-primary-foreground",
      "--radius"
    ],
    "examples": [],
    "subComponents": {
      "AgentMessage": {
        "componentName": "AgentMessage",
        "fileName": "AgentMessage.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Role",
            "type": "AgentMessageRole",
            "default": "AgentMessageRole.Assistant",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Avatar",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Name",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Timestamp",
            "type": "DateTimeOffset?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "IsStreaming",
            "type": "bool",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "ChildContent",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Class",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AdditionalAttributes",
            "type": "Dictionary<string, object>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": true
          }
        ],
        "events": [],
        "enums": [
          {
            "name": "AgentMessageRole",
            "values": [
              "User",
              "Assistant",
              "System",
              "Tool"
            ],
            "description": null
          }
        ],
        "records": [],
        "parseFailed": false,
        "parseError": null
      }
    },
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "agent-message-list",
  "docsUrl": "https://lumeo.nativ.sh/components/agent-message-list",
  "sourceUrl": [
    {
      "file": "UI/AgentMessageList/AgentMessage.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/AgentMessageList/AgentMessage.razor"
    },
    {
      "file": "UI/AgentMessageList/AgentMessageList.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/AgentMessageList/AgentMessageList.razor"
    }
  ],
  "source": [
    {
      "path": "UI/AgentMessageList/AgentMessage.razor",
      "content": "@namespace Lumeo\n\n@if (Role == AgentMessageRole.System)\n{\n    <div class=\"@SystemClass\" style=\"@BubbleMaxWidthStyle\" @attributes=\"AdditionalAttributes\">\n        @ChildContent\n    </div>\n}\nelse if (Role == AgentMessageRole.Tool)\n{\n    <div class=\"@ToolWrapperClass\" @attributes=\"AdditionalAttributes\">\n        @ChildContent\n    </div>\n}\nelse if (Role == AgentMessageRole.User)\n{\n    <div class=\"@UserRowClass\" @attributes=\"AdditionalAttributes\">\n        <div class=\"flex min-w-0 flex-col items-end gap-1\">\n            @if (!string.IsNullOrEmpty(Name) || Timestamp.HasValue)\n            {\n                <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n                    @if (Timestamp.HasValue)\n                    {\n                        <span>@FormatTimestamp(Timestamp.Value)</span>\n                    }\n                    @if (!string.IsNullOrEmpty(Name))\n                    {\n                        <span class=\"font-medium text-foreground\">@Name</span>\n                    }\n                </div>\n            }\n            <div class=\"@UserBubbleClass\" style=\"@BubbleMaxWidthStyle\">\n                @ChildContent\n                @if (IsStreaming)\n                {\n                    <span class=\"ml-0.5 inline-block align-baseline bg-current animate-pulse\" style=\"width: 2px; height: 1em;\">&nbsp;</span>\n                }\n            </div>\n        </div>\n        @if (Avatar is not null)\n        {\n            <div class=\"shrink-0\">@Avatar</div>\n        }\n    </div>\n}\nelse\n{\n    <div class=\"@AssistantRowClass\" @attributes=\"AdditionalAttributes\">\n        @if (Avatar is not null)\n        {\n            <div class=\"shrink-0 pt-0.5\">@Avatar</div>\n        }\n        <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n            @if (!string.IsNullOrEmpty(Name) || Timestamp.HasValue)\n            {\n                <div class=\"flex items-center gap-2 text-xs text-muted-foreground\">\n                    @if (!string.IsNullOrEmpty(Name))\n                    {\n                        <span class=\"font-medium text-foreground\">@Name</span>\n                    }\n                    @if (Timestamp.HasValue)\n                    {\n                        <span>@FormatTimestamp(Timestamp.Value)</span>\n                    }\n                </div>\n            }\n            <div class=\"min-w-0 w-full text-sm leading-relaxed text-foreground\">\n                @ChildContent\n                @if (IsStreaming)\n                {\n                    <span class=\"ml-0.5 inline-block align-baseline bg-current animate-pulse\" style=\"width: 2px; height: 1em;\">&nbsp;</span>\n                }\n            </div>\n        </div>\n    </div>\n}\n\n@code {\n    [Parameter] public AgentMessageRole Role { get; set; } = AgentMessageRole.Assistant;\n    [Parameter] public RenderFragment? Avatar { get; set; }\n    [Parameter] public string? Name { get; set; }\n    [Parameter] public DateTimeOffset? Timestamp { get; set; }\n    [Parameter] public bool IsStreaming { get; set; }\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private string UserRowClass => $\"flex items-start justify-end gap-3 {Class}\".Trim();\n    private string UserBubbleClass => \"rounded-2xl bg-primary px-4 py-3 text-sm leading-relaxed text-primary-foreground shadow-sm\";\n    // max-w-[80%] is an arbitrary Tailwind class not in the pre-compiled utility\n    // bundle — use inline style so the bubble actually caps.\n    private const string BubbleMaxWidthStyle = \"max-width: 80%;\";\n\n    private string AssistantRowClass => $\"flex items-start gap-3 {Class}\".Trim();\n\n    private string SystemClass =>\n        $\"mx-auto rounded-full bg-muted/60 px-3 py-1.5 text-center text-xs italic text-muted-foreground {Class}\".Trim();\n\n    private string ToolWrapperClass => $\"w-full {Class}\".Trim();\n\n    private static string FormatTimestamp(DateTimeOffset ts)\n    {\n        var local = ts.ToLocalTime();\n        return local.ToString(\"HH:mm\");\n    }\n\n    public enum AgentMessageRole\n    {\n        User,\n        Assistant,\n        System,\n        Tool\n    }\n}\n"
    },
    {
      "path": "UI/AgentMessageList/AgentMessageList.razor",
      "content": "@namespace Lumeo\n@inject Services.ComponentInteropService Interop\n@implements IAsyncDisposable\n\n<div id=\"@_listId\" class=\"@RootClass\" @attributes=\"AdditionalAttributes\">\n    <div class=\"flex flex-col gap-4\">\n        @ChildContent\n    </div>\n</div>\n\n@code {\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter] public bool AutoScroll { get; set; } = true;\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private readonly string _listId = $\"agent-message-list-{Guid.NewGuid():N}\";\n    private bool _observerRegistered;\n\n    private string RootClass =>\n        $\"flex w-full flex-col overflow-y-auto {Class}\".Trim();\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (!firstRender) return;\n        if (!AutoScroll || _observerRegistered) return;\n        try\n        {\n            _observerRegistered = true;\n            await Interop.AiObserveAutoScroll(_listId);\n        }\n        catch (JSDisconnectedException) { }\n        catch (ObjectDisposedException) { }\n    }\n\n    public async ValueTask DisposeAsync()\n    {\n        if (_observerRegistered)\n        {\n            try\n            {\n                await Interop.AiDisposeAutoScroll(_listId);\n            }\n            catch (JSDisconnectedException) { /* ignore — circuit already gone */ }\n        }\n    }\n}\n"
    }
  ],
  "slots": [
    {
      "name": "ChildContent",
      "owner": "AgentMessageList",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "Avatar",
      "owner": "AgentMessage",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "ChildContent",
      "owner": "AgentMessage",
      "type": "RenderFragment?",
      "description": null
    }
  ],
  "serviceDependencies": [
    {
      "service": "ComponentInteropService",
      "namespace": "Services"
    }
  ],
  "cascadingDependencies": [],
  "relatedComponents": [
    {
      "name": "AgentMessage",
      "reason": "sub-component"
    }
  ],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/AgentMessageList/AgentMessageListTests.cs",
    "tests/Lumeo.Tests/Components/AgentMessageList/AgentMessageTests.cs"
  ],
  "mdSummary": "# AgentMessageList\n\nChat message stream for AI agents with role-based styling.\n\n**Package:** `Lumeo` · **Category:** AI\n**Docs:** https://lumeo.nativ.sh/components/agent-message-list\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| AgentMessageList | ChildContent | `RenderFragment?` | `` |  |\n| AgentMessageList | AutoScroll | `bool` | `true` |  |\n| AgentMessageList | Class | `string?` | `` |  |\n| AgentMessageList | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| AgentMessage | Role | `AgentMessageRole` | `AgentMessageRole.Assistant` |  |\n| AgentMessage | Avatar | `RenderFragment?` | `` |  |\n| AgentMessage | Name | `string?` | `` |  |\n| AgentMessage | Timestamp | `DateTimeOffset?` | `` |  |\n| AgentMessage | IsStreaming | `bool` | `` |  |\n| AgentMessage | ChildContent | `RenderFragment?` | `` |  |\n| AgentMessage | Class | `string?` | `` |  |\n| AgentMessage | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- `ChildContent` (AgentMessageList) — RenderFragment slot\n- `Avatar` (AgentMessage) — RenderFragment slot\n- `ChildContent` (AgentMessage) — RenderFragment slot\n\n## Events\n- (none)\n\n## Sub-components\n- `AgentMessage`\n\n## Cascading values it expects\n- (none)\n\n## Services it injects\n- `ComponentInteropService` (Services)\n\n## Keyboard\n—\n\n## Example\n```razor\n<AgentMessageList />\n```\n\n## CSS variables\n`--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-primary`, `--color-primary-foreground`, `--radius`\n\n## Files\n- `UI/AgentMessageList/AgentMessage.razor`\n- `UI/AgentMessageList/AgentMessageList.razor`\n"
}