npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@threadplane/chat

v0.0.52

Published

Drop-in agent chat UI for Angular 20+. Headless UI primitives plus opinionated compositions that read a runtime-neutral `Agent` contract — ship a production chat surface in days without coupling to a specific backend.

Readme

@threadplane/chat

Drop-in agent chat UI for Angular 20+. Headless UI primitives plus opinionated compositions that read a runtime-neutral Agent contract — ship a production chat surface in days without coupling to a specific backend.

Part of Threadplane.

Source-available. Free for noncommercial use under PolyForm Noncommercial License 1.0.0. Commercial production use — SaaS, internal tools, agency work, paid client projects — requires a Threadplane Commercial license.


What it does

  • Full chat surface in one tag. <chat [agent]="agent" /> wires up message history, streaming output, typing indicator, input, interrupts, tool calls, subagents, citations, and generative UI — all from a single binding.
  • Layered architecture. Use the opinionated compositions for fast shipping, drop down to individual primitives (30+) to build custom layouts, or mix both.
  • Runtime-neutral. Compositions consume an Agent contract. The library has no hard dependency on LangGraph, AG-UI, or any other backend — swap or combine adapters without touching your UI.
  • A2UI generative UI. Agents emit structured surface specs; <a2ui-surface> renders them as interactive Angular components with a themeable --a2ui-* token system.

Install

npm install @threadplane/chat

Peer dependencies:

@angular/core              ^20.0.0 || ^21.0.0
@angular/common            ^20.0.0 || ^21.0.0
@angular/platform-browser  ^20.0.0 || ^21.0.0
@threadplane/licensing     *
@threadplane/render        *
@threadplane/a2ui          *
@json-render/core          ^0.16.0
@langchain/core            ^1.1.33
rxjs                       ~7.8.0
marked                     ^15.0.0 || ^16.0.0

Quick start

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideChat } from '@threadplane/chat';

export const appConfig: ApplicationConfig = {
  providers: [provideChat({ license: 'eyJ…' })],
};
// my.component.ts
import { Component } from '@angular/core';
import { ChatComponent } from '@threadplane/chat';
import { agent } from '@threadplane/langgraph';

@Component({
  selector: 'app-root',
  imports: [ChatComponent],
  template: `<chat [agent]="myAgent" />`,
})
export class AppComponent {
  myAgent = agent({ apiUrl: '/api/langgraph', graphId: 'agent' });
}

Get the agent signal from @threadplane/langgraph (for LangGraph Platform backends) or @threadplane/ag-ui (for AG-UI-compatible backends). See those packages for setup details.


Capabilities

Compositions

Ready-to-use full-feature layouts:

| Component | Selector | Description | |---|---|---| | ChatComponent | <chat> | Full-page chat layout; primary entry point | | ChatPopupComponent | <chat-popup> | Floating popup with a launcher button | | ChatSidebarComponent | <chat-sidebar> | Sidebar-docked layout | | ChatSidenavComponent | <chat-sidenav> | Sidenav host with project/thread list panel | | ChatTimelineSliderComponent | <chat-timeline-slider> | Time-travel slider for agent checkpoint history | | ChatInterruptPanelComponent | <chat-interrupt-panel> | Full interrupt-handling composition | | ChatApprovalCardComponent | <chat-approval-card> | Approval/rejection dialog for HITL flows | | ChatToolCallCardComponent | <chat-tool-call-card> | Rich card for a single tool call | | ChatSubagentCardComponent | <chat-subagent-card> | Rich card for a subagent delegation |

Primitives

30+ standalone components for custom layouts:

<chat-message-list>, <chat-message>, <chat-message-actions>, <chat-window>, <chat-input>, <chat-typing-indicator>, <chat-tool-calls>, <chat-subagents>, <chat-citations>, <chat-streaming-md>, <chat-trace>, <chat-reasoning>, <chat-interrupt>, <chat-error>, <chat-scroll-bubble>, <chat-launcher-button>, <chat-suggestions>, <chat-welcome>, <chat-select>, <chat-thread-list>, <chat-project-list>, <chat-timeline>, <chat-generative-ui>, <chat-genui-skeleton>, <chat-overflow-menu>, <chat-confirm-dialog>, <chat-history-search-palette>, <chat-sidenav-scrim>.

Custom content templates for message bubbles, tool call rows, and citation cards use structural directives: MessageTemplateDirective, ChatToolCallTemplateDirective, and ChatCitationCardTemplateDirective.

Human-in-the-loop (interrupts)

<chat-interrupt-panel> surfaces the current AgentInterrupt from an agent and renders approve/reject controls. <chat-approval-card> composes as a dialog for explicit approval workflows. Both emit typed action results (InterruptAction, ChatApprovalAction) that the caller submits back to the agent.

<chat-interrupt-panel
  [agent]="agent"
  (interruptAction)="onAction($event)"
/>

Tool calls and subagents

<chat-tool-calls> renders in-progress and completed tool calls. Customize per-call layout with ChatToolCallTemplateDirective — the chatToolCallTemplate input takes a tool name to match, or "*" for all; the template context exposes the ToolCall ($implicit) and its status:

<chat-tool-calls [agent]="agent">
  <ng-template chatToolCallTemplate="*" let-call let-status="status">
    <my-tool-card [call]="call" [status]="status" />
  </ng-template>
</chat-tool-calls>

<chat-subagents> and <chat-subagent-card> track delegated subagent activity with live status.

Citations

The Citation interface provides structured source metadata for assistant messages:

interface Citation {
  id: string;
  index?: number;     // 1-based display index for inline superscript markers
  title?: string;
  url?: string;
  snippet?: string;
  extra?: unknown;    // adapter-specific fields
}

Use <chat-citations> to render a collapsible sources panel under assistant messages. Customize the card layout with the chatCitationCard template directive:

<chat-citations [message]="message">
  <ng-template chatCitationCard let-citation>
    <a [href]="citation.url">{{ citation.title }}</a>
    <p>{{ citation.snippet }}</p>
  </ng-template>
</chat-citations>

Inline citation markers are rendered automatically by MarkdownCitationReferenceComponent inside streaming markdown output — superscript indices link to the corresponding card in the sources panel.

CitationsResolverService resolves raw Citation references into ResolvedCitation objects with full source metadata.

Adapter integration:

  • LangGraph — reads from message.additional_kwargs.citations (preferred) or .sources (fallback).
  • AG-UIbridgeCitationsState reads state.citations[messageId] from the agent state on STATE_SNAPSHOT and STATE_DELTA events.

GenUI / A2UI surfaces

<chat-generative-ui> renders A2UI surface specs emitted by agents. <a2ui-surface> is the underlying host that maps the spec to Angular catalog components (A2uiButtonComponent, A2uiTextFieldComponent, A2uiCheckBoxComponent, etc.).

Agents can emit surface specs via buildA2uiActionMessage(...). Actions from catalog components flow back to the agent as structured messages.

The built-in catalog ships via a2uiBasicCatalog. Compose a custom catalog with withViews() and pass it to the surface.

Streaming markdown

<chat-streaming-md> renders markdown token-by-token as the agent streams. The cacheplaneMarkdownViews registry maps each CommonMark node type to an Angular component.

Override individual node renderers:

import { MARKDOWN_VIEW_REGISTRY, cacheplaneMarkdownViews } from '@threadplane/chat';
import { overrideViews } from '@threadplane/render';
import { MyCodeBlockComponent } from './my-code-block.component';

providers: [
  {
    provide: MARKDOWN_VIEW_REGISTRY,
    useValue: overrideViews(cacheplaneMarkdownViews, { 'code-block': MyCodeBlockComponent }),
  },
];

Per-instance, bind the registry on <chat-streaming-md [viewRegistry]="…" /> instead. Styling uses the existing --ngaf-chat-* / --a2ui-* tokens — see the Theming section.

The renderMarkdown(md, options?) function produces a parse tree for use outside streaming contexts.

Theming

<a2ui-surface> declares ~50 --a2ui-* CSS custom properties at :host with dark-theme defaults covering color, spacing, typography, shape radius, focus ring, motion, and elevation. Catalog components consume them via var(--a2ui-*).

Built-in presets — import one in your global stylesheet:

@import '@threadplane/chat/themes/default-dark.css';   /* lib defaults, explicit */
@import '@threadplane/chat/themes/default-light.css';  /* neutral light, blue accent */
@import '@threadplane/chat/themes/material-dark.css';  /* Material Design 3 dark */
@import '@threadplane/chat/themes/material-light.css'; /* Material Design 3 light */

Material presets map M3 color tokens to the --a2ui-* vocabulary with no @angular/material runtime dependency.

Agent-driven theming. Agents control two knobs per the A2UI v1 wire format, set via beginRendering.styles: font (font family string) and primaryColor (hex #RRGGBB). These flow to <a2ui-surface> as inline styles and take precedence over :root defaults for that surface.

Custom themes. Override any token at :root:

:root {
  --a2ui-primary: #FF6B35;
  --a2ui-shape-medium: 4px;
  --a2ui-spacing-3: 16px;
}

The full token vocabulary (--a2ui-primary, --a2ui-spacing-1..7, --a2ui-typography-*, --a2ui-shape-*, --a2ui-elevation-*, etc.) is documented at threadplane.ai/docs/chat.


Runtime adapters

Chat compositions consume the runtime-neutral Agent contract. Two adapters ship today:

  • @threadplane/langgraph — for LangGraph / LangGraph Platform backends.
  • @threadplane/ag-ui — for AG-UI-compatible backends (LangGraph, CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, AWS Strands, CopilotKit runtime).

Custom backends implement the Agent (or AgentWithHistory) interface directly with no library dependency.


Commercial use

Building a commercial product, SaaS application, internal business tool, agency deliverable, or paid client project with @threadplane/chat requires a Threadplane Commercial license.

Free under PolyForm Noncommercial:

  • Personal, hobby, student, academic, nonprofit, and public-demo use
  • Open-source applications released under an OSI-approved license
  • 30 calendar days of commercial evaluation from your first commercial use (good-faith — no tracking, no email required)

See COMMERCIAL-USE.md for the definition of commercial use, LICENSE-COMMERCIAL.md for the commercial license summary, and the Threadplane pricing page for plans.

Using a commercial license

After purchase, Threadplane emails a signed license token to the address on your receipt. The license is valid for 12 months. Pass the token to provideChat():

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideChat } from '@threadplane/chat';

export const appConfig: ApplicationConfig = {
  providers: [
    provideChat({
      license: 'eyJ…',  // Token from your purchase email.
    }),
  ],
};

The library verifies the token's signature on boot. A missing, expired, or tampered token logs a console.warn advisory but does not block rendering — chat continues to work either way. Tokens are validated offline; no calls to Threadplane are made at runtime.

The license string is safe to commit to source control for private repositories, or read from a build-time env var for public ones:

declare const THREADPLANE_LICENSE: string | undefined;

providers: [
  provideChat({
    license: typeof THREADPLANE_LICENSE === 'string' ? THREADPLANE_LICENSE : undefined,
  }),
],

Reliability

@threadplane/chat follows a patch-only release cadence (0.0.x). The runtime-neutral Agent contract is a stability boundary: adapter updates do not break chat UI code and vice versa. The package is covered by the monorepo's CI lint, test, and build pipeline on every commit.


Documentation

Full API reference, capability matrix, and examples: threadplane.ai/docs/chat.


License

@threadplane/chat is dual-licensed:

See COMMERCIAL-USE.md for the definition of commercial use.