Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/website/content/docs/chat/api/mock-agent.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# mockAgent()

`mockAgent()` creates a runtime-neutral `Agent` mock with writable signals for testing `@threadplane/chat` components. Use it when you are testing chat UI behavior and do not need LangGraph-specific fields.
`mockAgent()` creates a runtime-neutral `Agent` mock with writable signals for testing `@threadplane/chat` components. Use it when you're testing chat UI behavior and don't need LangGraph-specific fields.

**Import:**

Expand Down
12 changes: 6 additions & 6 deletions apps/website/content/docs/chat/concepts/message-model.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`@threadplane/chat` renders a runtime-neutral message model. Adapters translate backend-specific messages into this shape, then components render from it.

This matters because provider message formats are not stable enough to build customer UI against directly. LangGraph, AG-UI, OpenAI, Anthropic, and custom backends all have different event and content shapes. The chat layer needs one model.
This matters because provider message formats aren't stable enough to build customer UI against directly. LangGraph, AG-UI, OpenAI, Anthropic, and custom backends all have different event and content shapes. The chat layer needs one model.

## Message Shape

Expand Down Expand Up @@ -50,7 +50,7 @@ You will also see the words `human`, `ai`, and `function` in template APIs:

`user` maps to `human`. `assistant` maps to `ai`. `tool` and `system` keep their names.

`function` is present for compatibility with older function-call vocabulary. The current runtime-neutral `Role` type does not include `function`. New adapters should normalize function results into `tool` messages or carry backend-specific function details in `extra`.
`function` is present for compatibility with older function-call vocabulary. The current runtime-neutral `Role` type doesn't include `function`. New adapters should normalize function results into `tool` messages or carry backend-specific function details in `extra`.

## Content

Expand All @@ -66,7 +66,7 @@ type ContentBlock =

Plain text is the common case. `ChatComponent` treats assistant text as streamable content. Markdown, json-render specs, and A2UI payloads are detected from that text.

Structured blocks are useful when the adapter can preserve more shape than a string. Custom templates should check whether `content` is a string before assuming it can be rendered directly.
Structured blocks are useful when the adapter can preserve more shape than a string. Custom templates should check whether `content` is a string before assuming they can render it directly.

```ts
function textOf(message: Message): string {
Expand Down Expand Up @@ -119,7 +119,7 @@ Tool result messages can also carry `toolCallId`.

Use `toolCalls()` when rendering cross-message tool status. Use `tool` messages when rendering tool output inside the transcript.

This matters because tool calls stream. Arguments may be partial while status is not `complete`. UI should treat `args` as unknown until the adapter marks the call complete or your tool template can handle partial data.
This matters because tool calls stream. Arguments may be partial while status isn't `complete`. UI should treat `args` as unknown until the adapter marks the call complete, or until your tool template can handle partial data.

## Citations

Expand Down Expand Up @@ -172,7 +172,7 @@ agent.subagents?.(); // Map<string, Subagent>

Each `Subagent` has a tool-call id, optional name, status signal, message signal, and state signal.

Use subagents when the backend delegates work to child graphs or specialized workers. Do not encode subagent progress as fake assistant messages if the runtime can expose structured subagent state. Structured state lets UI render progress, nested transcripts, and failure states without parsing prose.
Use subagents when the backend delegates work to child graphs or specialized workers. Don't encode subagent progress as fake assistant messages if the runtime can expose structured subagent state. Structured state lets UI render progress, nested transcripts, and failure states without parsing prose.

## A2UI And Generated Surfaces

Expand All @@ -192,7 +192,7 @@ The message still remains an assistant message. The generated UI is a rendering

Normalize at the adapter boundary. Components should not inspect raw LangGraph SDK messages or AG-UI events unless they are adapter-specific tools.

Treat `content` as `string | ContentBlock[]`. Do not assume every message can be interpolated directly.
Treat `content` as `string | ContentBlock[]`. Don't assume every message can be interpolated directly.

Use the exported type guards when role-specific code helps:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Use compositions when the default product shape is close to what you need. Use primitives when the layout, interaction model, or rendering policy is part of your application.

This matters because chat UI gets complicated quickly. Message streaming, input state, tool calls, reasoning, interrupts, subagents, auto-scroll, markdown, and generative UI all need to agree on the same `Agent`. The fastest path is usually to start with a composition and drop down only where the product needs control.
This matters because chat UI gets complicated fast. Message streaming, input state, tool calls, reasoning, interrupts, subagents, auto-scroll, markdown, and generative UI all need to agree on the same `Agent`. The fastest path is usually to start with a composition and drop down only where the product needs control.

## Compositions

Expand Down Expand Up @@ -43,7 +43,7 @@ Use `<chat>` when you want the library to own the chat shell.
/>
```

`<chat-debug>` is also a composition. It is built for development and inspection, not end-user chat layout, and ships from the debug-only secondary entry point.
`<chat-debug>` is also a composition. It's built for development and inspection, not end-user chat layout, and ships from the debug-only secondary entry point.

```ts
import { ChatDebugComponent } from '@threadplane/chat/debug';
Expand All @@ -54,7 +54,7 @@ import { ChatDebugComponent } from '@threadplane/chat/debug';
<chat-debug [agent]="agent" />
```

Use `chat-debug` when you need timeline and state inspection while building. Do not treat it as a customer-facing control surface unless you intentionally design around that.
Use `chat-debug` when you need timeline and state inspection while building. Don't treat it as a customer-facing control surface unless you intentionally design around that.

If you use `<chat-sidenav>`, pass `[agent]="agent"` and `[debug]="true"` to get the built-in footer launcher instead of adding a separate floating debug button.

Expand Down Expand Up @@ -120,7 +120,7 @@ Use primitives when you need:
| Full product-specific shell | primitives |
| You are building a design system wrapper | primitives |

The practical tradeoff is ownership. A composition owns more behavior for you. A primitive gives you more control and more responsibility.
The practical tradeoff is ownership. A composition owns more behavior for you. A primitive hands you more control, and more responsibility.

## Template Role Names

Expand Down Expand Up @@ -151,9 +151,9 @@ The mapping is:

Give `<chat>` a parent with height. The composition uses flex layout and `height: 100%`; without a constrained parent, it can collapse.

Do not pass a raw backend client to chat primitives. They need the `Agent` contract from `@threadplane/chat`, not a LangGraph SDK client or AG-UI `AbstractAgent`.
Don't pass a raw backend client to chat primitives. They need the `Agent` contract from `@threadplane/chat`, not a LangGraph SDK client or AG-UI `AbstractAgent`.

Do not mix two agents in one shell unless you mean it. `chat-message-list`, `chat-input`, tool-call UI, and debug UI should usually point at the same `Agent` instance.
Don't mix two agents in one shell unless you mean it. `chat-message-list`, `chat-input`, tool-call UI, and debug UI should usually point at the same `Agent` instance.

If you use primitives, you own the behaviors the composition normally provides: auto-scroll, empty state, error display, reasoning placement, tool-call placement, subagent placement, and interrupt display.

Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/configuration.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration

`@threadplane/chat` uses Angular's dependency injection system for shared configuration. The `provideChat()` function registers a `ChatConfig` object under the `CHAT_CONFIG` injection token and starts the package license check.
`@threadplane/chat` leans on Angular's dependency injection for shared configuration. The `provideChat()` function registers a `ChatConfig` object under the `CHAT_CONFIG` injection token and starts the package license check.

## provideChat()

Expand Down Expand Up @@ -116,10 +116,10 @@ export const routes: Routes = [

## Using Configuration Without provideChat()

All composition components use sensible defaults. If you do not call `provideChat()`, components will:
All composition components ship with sensible defaults. If you don't call `provideChat()`, components will:

- Use `"A"` as the avatar label
- Use `"Assistant"` as the assistant name
- Have no injected `CHAT_CONFIG`

This means you can use `ChatComponent`, `ChatInputComponent`, and all other components without global configuration for basic chat functionality. Generative UI is controlled by the `ChatComponent` `[views]`, `[store]`, and `[handlers]` inputs.
So you can use `ChatComponent`, `ChatInputComponent`, and the rest without any global configuration for basic chat. Generative UI is controlled by the `ChatComponent` `[views]`, `[store]`, and `[handlers]` inputs.
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/custom-catalogs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Compose custom component catalogs for generative UI using ViewRegis

# Custom Catalogs

Both json-render specs and A2UI surfaces render through the same `ViewRegistry`. Compose catalogs using `views`, `withViews`, and `withoutViews` from `@threadplane/render`.
Both json-render specs and A2UI surfaces render through the same `ViewRegistry`. Let's compose catalogs using `views`, `withViews`, and `withoutViews` from `@threadplane/render`.

## Using the Built-In A2UI Catalog

Expand Down Expand Up @@ -65,7 +65,7 @@ const catalog = views({

## No Generative UI

If `views` is not provided, no generative UI renders. Specs and A2UI surfaces are silently skipped.
If you don't provide `views`, no generative UI renders. Specs and A2UI surfaces are silently skipped.

```html
<chat [agent]="agentRef" />
Expand All @@ -91,4 +91,4 @@ export class MyChartComponent {
}
```

The component receives resolved props as inputs. `childKeys` and `spec` enable recursive child rendering. `emit` triggers event handlers defined in the spec's `on` bindings.
The component receives resolved props as inputs. `childKeys` and `spec` enable recursive child rendering, and `emit` triggers event handlers defined in the spec's `on` bindings.
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/generative-ui.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generative UI

Generative UI lets your LangGraph agent return structured JSON specs that render as Angular components in the chat. The `ChatComponent` auto-detects JSON specs in AI messages and renders them — no manual wiring needed.
Generative UI lets your LangGraph agent return structured JSON specs that render as Angular components in the chat. `ChatComponent` auto-detects JSON specs in AI messages and renders them — no manual wiring needed.

## How It Works

Expand Down Expand Up @@ -58,7 +58,7 @@ export class ChatPageComponent {
}
```

That's it. When the agent returns a JSON spec as a message, `ChatComponent` detects it and renders through your view registry.
That's it. When the agent returns a JSON spec as a message, `ChatComponent` detects it and renders it through your view registry.

## Creating View Components

Expand Down Expand Up @@ -116,7 +116,7 @@ Because the JSON is parsed character-by-character as tokens arrive:

## State Store

For interactive generative UI (forms, selections), pass a `StateStore` via the `[store]` input:
For interactive generative UI forms, selections pass a `StateStore` via the `[store]` input:

```typescript
import { signalStateStore } from '@threadplane/render';
Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/layout-modes.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Layout Modes

`@threadplane/chat` ships three ready-made layout compositions. Pick the one that best fits how chat fits into your application.
`@threadplane/chat` ships three ready-made layout compositions. Pick the one that best fits how chat lives inside your app.

| Mode | Component | Best for |
|---|---|---|
Expand All @@ -10,7 +10,7 @@

## Embedded — `<chat>`

The embedded composition fills its parent container using `height: 100%` and a flex column layout. Use it when the chat is the main feature of a route.
The embedded composition fills its parent container using `height: 100%` and a flex column layout. Reach for it when chat is the main feature of a route.

**When to pick this mode:**
- Chat is the whole page (e.g., a dedicated `/chat` route)
Expand Down Expand Up @@ -159,4 +159,4 @@ Toggle the sidebar from a nav button:
| Should chat and app content coexist? | Use `<chat-sidebar>` |
| Should the sidebar push content aside? | Use `<chat-sidebar [pushContent]="true">` |

All three compositions share the same `--ngaf-chat-*` token system. See [Theming](/docs/chat/guides/theming) to customize colors, shapes, and typography across all modes at once.
All three compositions share the same `--ngaf-chat-*` token system, so whichever mode you land on, it'll match your brand. Next, head to [Theming](/docs/chat/guides/theming) to customize colors, shapes, and typography across all modes at once.
2 changes: 1 addition & 1 deletion apps/website/content/docs/chat/guides/lifecycle.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Chat Lifecycle Signals

The `@threadplane/chat` library exposes per-instance lifecycle signals via the `CHAT_LIFECYCLE` injection token. Consumers can subscribe to these signals for debugging, custom dashboards, or telemetry integrations.
`@threadplane/chat` exposes per-instance lifecycle signals via the `CHAT_LIFECYCLE` injection token. Subscribe to them for debugging, custom dashboards, or telemetry integrations.

## Interface

Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/markdown.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Markdown Rendering

AI messages in `@threadplane/chat` can render full markdown -- headings, code blocks, tables, lists, blockquotes, and inline formatting. This is powered by the `renderMarkdown()` utility and styled with `CHAT_MARKDOWN_STYLES`.
AI messages in `@threadplane/chat` can render full markdown -- headings, code blocks, tables, lists, blockquotes, and inline formatting. The `renderMarkdown()` utility does the work, and `CHAT_MARKDOWN_STYLES` handles the styling.

## How It Works

Expand Down Expand Up @@ -84,7 +84,7 @@ All colors reference `--ngaf-chat-*` CSS custom properties, so markdown elements

## Using Markdown in Custom Components

To render markdown in a custom message template, apply both the styles and the `.chat-md` class:
Let's render markdown in a custom message template. Apply both the styles and the `.chat-md` class:

```typescript
import { Component, inject } from '@angular/core';
Expand Down Expand Up @@ -232,7 +232,7 @@ All built-in markdown view components consume the same `--ngaf-chat-*` and `--a2

## Without marked

If you choose not to install `marked`, markdown content will render as plain text with line breaks preserved. This can be appropriate for simple chat applications that do not need rich formatting.
If you skip installing `marked`, markdown content renders as plain text with line breaks preserved. That's fine for simple chat apps that don't need rich formatting.

```bash
# Full markdown support:
Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/streaming.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Streaming

The `ChatComponent` automatically classifies AI message content and routes it to the appropriate renderer. This page explains how the streaming pipeline works and how to use the classification APIs directly for custom integrations.
`ChatComponent` automatically classifies AI message content and routes it to the right renderer. This page walks through how the streaming pipeline works, and how to use the classification APIs directly for custom integrations.

## Content Classification

Expand Down Expand Up @@ -31,7 +31,7 @@ Tokens arrive character-by-character

## Using ContentClassifier Directly

For custom message rendering outside of `ChatComponent`, use `createContentClassifier()`:
For custom message rendering outside of `ChatComponent`, reach for `createContentClassifier()`:

```typescript
import { createContentClassifier } from '@threadplane/chat';
Expand Down Expand Up @@ -114,7 +114,7 @@ The resulting surfaces are available via `classifier.a2uiSurfaces()`, which retu

## Error Handling

Parse errors are captured in the `errors` signal and do not crash the rendering pipeline. When a malformed token arrives, the classifier records the error and continues processing subsequent tokens — partial results keep rendering.
Parse errors are captured in the `errors` signal and don't crash the rendering pipeline. When a malformed token arrives, the classifier records the error and keeps processing the tokens that follow — partial results keep rendering.

```typescript
const classifier = createContentClassifier();
Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/chat/guides/theming.mdx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Theming

`@threadplane/chat` uses CSS custom properties (variables) for all visual styling. Every color, radius, font, and spacing value is controlled by a variable prefixed with `--ngaf-chat-`, making it straightforward to match your application's design system.
`@threadplane/chat` styles everything with CSS custom properties (variables). Every color, radius, font, and spacing value is controlled by a variable prefixed with `--ngaf-chat-`, so matching your app's design system is straightforward.

## How Theming Works

Chat components define all design tokens using CSS custom properties on the `:host` element. The token system supports automatic light/dark switching via `prefers-color-scheme` and explicit override via a `[data-threadplane-chat-theme]` attribute.

No imported stylesheet is needed - tokens are applied automatically by each component's encapsulated styles. An optional global stylesheet (`@threadplane/chat/chat.css`) is available if you want to customize tokens at the `:root` level.
You don't need to import a stylesheet — each component's encapsulated styles apply the tokens automatically. An optional global stylesheet (`@threadplane/chat/chat.css`) is there if you want to customize tokens at the `:root` level.

## CSS Custom Properties Reference

Expand Down Expand Up @@ -85,7 +85,7 @@ The switching logic is:

### Deep override via the optional global stylesheet

Import `@threadplane/chat/chat.css` in your global styles to get a `:root`-level baseline you can override:
Import `@threadplane/chat/chat.css` in your global styles to get a `:root`-level baseline you can override. For me, this is the move when I'm theming several token groups at once — the cost is one more global import to keep track of, but you get everything in a single place:

```css
/* src/styles.css */
Expand Down
Loading
Loading