From c32726f148c0bb53c27b4efa7eda10ce33fddd6c Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sun, 7 Jun 2026 17:21:05 -0700 Subject: [PATCH 1/3] docs(chat): voice pass on guides --- apps/website/content/docs/chat/guides/configuration.mdx | 6 +++--- apps/website/content/docs/chat/guides/custom-catalogs.mdx | 6 +++--- apps/website/content/docs/chat/guides/generative-ui.mdx | 6 +++--- apps/website/content/docs/chat/guides/layout-modes.mdx | 6 +++--- apps/website/content/docs/chat/guides/lifecycle.mdx | 2 +- apps/website/content/docs/chat/guides/markdown.mdx | 6 +++--- apps/website/content/docs/chat/guides/streaming.mdx | 6 +++--- apps/website/content/docs/chat/guides/theming.mdx | 6 +++--- .../content/docs/chat/guides/writing-an-adapter.mdx | 8 ++++---- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/apps/website/content/docs/chat/guides/configuration.mdx b/apps/website/content/docs/chat/guides/configuration.mdx index 930d624f..c18562d6 100644 --- a/apps/website/content/docs/chat/guides/configuration.mdx +++ b/apps/website/content/docs/chat/guides/configuration.mdx @@ -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() @@ -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. diff --git a/apps/website/content/docs/chat/guides/custom-catalogs.mdx b/apps/website/content/docs/chat/guides/custom-catalogs.mdx index 4b565ad2..76a491a3 100644 --- a/apps/website/content/docs/chat/guides/custom-catalogs.mdx +++ b/apps/website/content/docs/chat/guides/custom-catalogs.mdx @@ -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 @@ -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 @@ -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. diff --git a/apps/website/content/docs/chat/guides/generative-ui.mdx b/apps/website/content/docs/chat/guides/generative-ui.mdx index 0c7c87c2..ed227c9f 100644 --- a/apps/website/content/docs/chat/guides/generative-ui.mdx +++ b/apps/website/content/docs/chat/guides/generative-ui.mdx @@ -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 @@ -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 @@ -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'; diff --git a/apps/website/content/docs/chat/guides/layout-modes.mdx b/apps/website/content/docs/chat/guides/layout-modes.mdx index 606d9efa..0bb408cc 100644 --- a/apps/website/content/docs/chat/guides/layout-modes.mdx +++ b/apps/website/content/docs/chat/guides/layout-modes.mdx @@ -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 | |---|---|---| @@ -10,7 +10,7 @@ ## Embedded — `` -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) @@ -159,4 +159,4 @@ Toggle the sidebar from a nav button: | Should chat and app content coexist? | Use `` | | Should the sidebar push content aside? | Use `` | -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. diff --git a/apps/website/content/docs/chat/guides/lifecycle.mdx b/apps/website/content/docs/chat/guides/lifecycle.mdx index 25ba81d6..74c8f2d5 100644 --- a/apps/website/content/docs/chat/guides/lifecycle.mdx +++ b/apps/website/content/docs/chat/guides/lifecycle.mdx @@ -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 diff --git a/apps/website/content/docs/chat/guides/markdown.mdx b/apps/website/content/docs/chat/guides/markdown.mdx index 9a5f3b35..2c1a7c85 100644 --- a/apps/website/content/docs/chat/guides/markdown.mdx +++ b/apps/website/content/docs/chat/guides/markdown.mdx @@ -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 @@ -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'; @@ -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: diff --git a/apps/website/content/docs/chat/guides/streaming.mdx b/apps/website/content/docs/chat/guides/streaming.mdx index 82ed4d30..2a95ec91 100644 --- a/apps/website/content/docs/chat/guides/streaming.mdx +++ b/apps/website/content/docs/chat/guides/streaming.mdx @@ -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 @@ -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'; @@ -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(); diff --git a/apps/website/content/docs/chat/guides/theming.mdx b/apps/website/content/docs/chat/guides/theming.mdx index 43e36f2a..d2c089af 100644 --- a/apps/website/content/docs/chat/guides/theming.mdx +++ b/apps/website/content/docs/chat/guides/theming.mdx @@ -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 @@ -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 */ diff --git a/apps/website/content/docs/chat/guides/writing-an-adapter.mdx b/apps/website/content/docs/chat/guides/writing-an-adapter.mdx index d50a1569..61d7117f 100644 --- a/apps/website/content/docs/chat/guides/writing-an-adapter.mdx +++ b/apps/website/content/docs/chat/guides/writing-an-adapter.mdx @@ -1,6 +1,6 @@ # Writing an Adapter -Learn how to implement a custom `Agent` adapter so `@threadplane/chat` components work with any backend — whether that is a custom RPC service, an in-process mock, or an exotic streaming protocol. +Learn how to implement a custom `Agent` adapter so `@threadplane/chat` components work with any backend — a custom RPC service, an in-process mock, or an exotic streaming protocol. ## When to Write Your Own Adapter @@ -48,7 +48,7 @@ The design invariant is: **state lives on signals; `events$` carries only things ## Worked Example: An In-Process Echo Adapter -Below is a complete `EchoAgent` factory — roughly 80 lines — that satisfies the full `Agent` contract without any network call. It demonstrates the signal pattern clearly and is a solid starting point for your own adapter. +Below is a complete `EchoAgent` factory — roughly 80 lines — that satisfies the full `Agent` contract without any network call. It shows the signal pattern clearly and is a solid starting point for your own adapter. On `submit`, the factory optimistically appends the user message, then after a short delay appends an assistant message that echoes the input back. There are no tool calls, no custom events, and no interrupts. @@ -140,7 +140,7 @@ function cryptoRandomId(): string { ## Wiring It Into a Component -The cleanest approach is to register your factory behind an Angular injection token and inject it into your component. +For me, the cleanest approach is to register your factory behind an Angular injection token and inject it into your component. It's a touch more boilerplate than a bare `new`, but it keeps the wiring testable and swappable. ```typescript // app.config.ts @@ -228,7 +228,7 @@ If your protocol does store thread state, follow the LangGraph adapter's pattern ## Publishing Your Adapter -If you want to distribute your adapter as an npm package, keep the following in mind. +Want to distribute your adapter as an npm package? Keep the following in mind. **Peer dependencies** to declare in your `package.json`: From 9d4d76771e43dd210b5fe58d0f0166b2a0bf9e9e Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sun, 7 Jun 2026 17:25:46 -0700 Subject: [PATCH 2/3] docs(chat): voice pass on concepts --- .../content/docs/chat/concepts/message-model.mdx | 12 ++++++------ .../chat/concepts/primitives-vs-compositions.mdx | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/website/content/docs/chat/concepts/message-model.mdx b/apps/website/content/docs/chat/concepts/message-model.mdx index 973f0cab..38e99cbc 100644 --- a/apps/website/content/docs/chat/concepts/message-model.mdx +++ b/apps/website/content/docs/chat/concepts/message-model.mdx @@ -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 @@ -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 @@ -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 { @@ -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 @@ -172,7 +172,7 @@ agent.subagents?.(); // Map 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 @@ -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: diff --git a/apps/website/content/docs/chat/concepts/primitives-vs-compositions.mdx b/apps/website/content/docs/chat/concepts/primitives-vs-compositions.mdx index 6012e69d..b9157a9b 100644 --- a/apps/website/content/docs/chat/concepts/primitives-vs-compositions.mdx +++ b/apps/website/content/docs/chat/concepts/primitives-vs-compositions.mdx @@ -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 @@ -43,7 +43,7 @@ Use `` when you want the library to own the chat shell. /> ``` -`` 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. +`` 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'; @@ -54,7 +54,7 @@ import { ChatDebugComponent } from '@threadplane/chat/debug'; ``` -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 ``, pass `[agent]="agent"` and `[debug]="true"` to get the built-in footer launcher instead of adding a separate floating debug button. @@ -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 @@ -151,9 +151,9 @@ The mapping is: Give `` 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. From 7408d0f059da496fc09a6e6b087186e1923a5a97 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sun, 7 Jun 2026 17:31:17 -0700 Subject: [PATCH 3/3] docs(chat): voice pass on component + api reference intros --- apps/website/content/docs/chat/api/mock-agent.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/content/docs/chat/api/mock-agent.mdx b/apps/website/content/docs/chat/api/mock-agent.mdx index 606f1728..b53d7082 100644 --- a/apps/website/content/docs/chat/api/mock-agent.mdx +++ b/apps/website/content/docs/chat/api/mock-agent.mdx @@ -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:**