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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

Threadplane is a production-ready agent UI framework for Angular. `@threadplane/chat` provides chat surfaces (headless primitives, opinionated compositions, interrupts, generative UI). `@threadplane/langgraph` adapts a LangGraph Platform endpoint into Angular Signals via `provideAgent()` + `injectAgent()`. `@threadplane/ag-ui` bridges any AG-UI-compatible backend into the same chat surface. `@threadplane/render` renders JSON specs to Angular components inside your design system.

`injectAgent()` is the Angular equivalent of LangGraph's React `useStream()` hook, projected through a runtime-neutral `Agent` contract that `@threadplane/chat` consumes. Configure it once with `provideAgent({...})`, inject it into any Angular 20+ component, and get signal-driven access to messages, status, tool calls, interrupts, subagents, history, and thread management — no subscriptions, no `async` pipe, no zone.js required.
`injectAgent()` is the Angular equivalent of LangGraph's React `useStream()` hook, projected through a runtime-neutral `Agent` contract that `@threadplane/chat` consumes. Configure it once with `provideAgent({...})`, inject it into any Angular 20–22 component, and get signal-driven access to messages, status, tool calls, interrupts, subagents, history, and thread management — no subscriptions, no `async` pipe, no zone.js required.

---

Expand Down Expand Up @@ -116,7 +116,7 @@ export class SupportChatComponent {
| Reload last submission | `reload()` | — |
| Custom transport (for testing) | `MockAgentTransport` | mock fetch |
| Angular `ResourceRef<T>` compatibility | Full duck-type parity | N/A |
| Angular 20+ Signals API | Native | N/A |
| Angular 20–22 Signals API | Native | N/A |
| SSR / Server Components | Client-side only | React Server Components (React) |

---
Expand Down
2 changes: 2 additions & 0 deletions apps/website/content/AGENTS.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Production-ready chat, thread/history/branch UI, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.

Supported Angular majors: 20, 21, and 22.

## License and deployment boundary
- Every Threadplane package is MIT-licensed and free for commercial and noncommercial use.
- Threadplane runs inside the customer's Angular application. Agent runtime, models, storage, checkpointing, retention, authorization, and hosting remain customer-operated.
Expand Down
2 changes: 2 additions & 0 deletions apps/website/content/CLAUDE.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Production-ready chat, thread/history/branch UI, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.

Supported Angular majors: 20, 21, and 22.

## License and deployment boundary
- Every Threadplane package is MIT-licensed and free for commercial and noncommercial use.
- Threadplane runs inside the customer's Angular application. Agent runtime, models, storage, checkpointing, retention, authorization, and hosting remain customer-operated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ AG-UI's event model maps onto Angular signals cleanly, which is what this post b

## Goals

- Wire an AG-UI-compatible backend to an Angular 20+ app using `@threadplane/ag-ui` and `@threadplane/chat`.
- Wire an AG-UI-compatible backend to an Angular 20–22 app using `@threadplane/ag-ui` and `@threadplane/chat`.
- See how 17 protocol events become a handful of signals you read from a template.
- Handle the parts that turn a demo into a product: tool calls, interrupts, threads, fallbacks.

Expand Down Expand Up @@ -78,7 +78,7 @@ The two are decoupled on purpose. We will get to why.

## Let's wire it up

Start with a fresh Angular 20+ app, or use an existing one — `ng new` if you need to spin one up.
Start with a fresh Angular 20–22 app, or use an existing one — `ng new` if you need to spin one up.

### Install the packages

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Now we can give the agent a UI.

## How do we connect the Angular agent UI?

The Threadplane adapter supports Angular 20 and 21; use Node.js 22 or later for the documented setup.
The Threadplane adapter supports Angular 20, 21, and 22. Use a Node.js version supported by your Angular major; Angular 22 requires Node.js ^22.22.3, ^24.15.0, or ^26.0.0. See the [Angular compatibility matrix](https://angular.dev/reference/versions).
Install the chat surface, AG-UI adapter, official AG-UI client packages, and markdown renderer:

<Callout type="info" title="MIT-licensed packages">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Use a Node.js version supported by the selected Angular major. Angular 22 suppor

## Prerequisites

- Angular 20 or later
- Angular 20, 21, or 22
- An AG-UI-compatible backend running locally or remotely (CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, AWS Strands, or your own subclass of `AbstractAgent`)

## Install packages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Let's bind `<chat>` from `@threadplane/chat` to an AG-UI backend in 5 minutes.

<Callout type="info" title="Prerequisites">
Angular 20+ project with Node.js 22+. If you need setup help, see the [Installation](/docs/ag-ui/getting-started/installation) guide.
Angular 20–22 project using a Node.js version supported by that Angular major. If you need setup help, see the [Installation](/docs/ag-ui/getting-started/installation) guide.
</Callout>

<Callout type="tip" title="Try it first">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ or runtime key.
Supported Angular majors: 20, 21, and 22.

<Steps>
<Step title="Angular 20 or later">
`@threadplane/chat` uses Angular Signals, `input()`, and `contentChildren()`. Run `ng version` to confirm. Upgrade with `ng update @angular/core @angular/cli` if you're below 20.
<Step title="Angular 20–22">
`@threadplane/chat` uses Angular Signals, `input()`, and `contentChildren()`. Run `ng version` to confirm that your project uses Angular 20, 21, or 22.
</Step>
<Step title="Node.js compatibility">
Use a Node.js version supported by the selected Angular major. Angular 22 supports Node.js ^22.22.3, ^24.15.0, or ^26.0.0. See the [Angular compatibility matrix](https://angular.dev/reference/versions).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Introduction

`@threadplane/chat` is the Angular UI component library for building chat interfaces on top of a runtime-neutral `Agent` contract. It's a set of composable, Signal-driven components that render messages, handle user input, display tool calls, manage interrupts, and support generative UI -- all styled with CSS custom properties and built for Angular 20+.
`@threadplane/chat` is the Angular UI component library for building chat interfaces on top of a runtime-neutral `Agent` contract. It's a set of composable, Signal-driven components that render messages, handle user input, display tool calls, manage interrupts, and support generative UI -- all styled with CSS custom properties and built for Angular 20–22.

<Callout type="info" title="What you'll learn">
This guide explains the library's two-tier architecture, how it relates to the rest of the Threadplane stack, and when to reach for the all-in-one composition versus assembling primitives yourself.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Let's build a streaming chat UI with `@threadplane/chat` in 5 minutes.

<Callout type="info" title="Prerequisites">
Angular 20+ project with an agent provider configured. See [Agent Installation](/docs/langgraph/getting-started/installation) if you need help.
Angular 20–22 project with an agent provider configured. See [Agent Installation](/docs/langgraph/getting-started/installation) if you need help.
</Callout>

<Callout type="info" title="No backend yet?">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ Want to distribute your adapter as an npm package? Keep the following in mind.
```json
{
"peerDependencies": {
"@angular/core": "^20.0.0",
"@angular/core": "^20.0.0 || ^21.0.0 || ^22.0.0",
"@threadplane/chat": "^0.0.2",
"rxjs": "^7.0.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Detailed setup guide for `injectAgent()` in your Angular application.
Supported Angular majors: 20, 21, and 22.

<Steps>
<Step title="Angular 20+">
`injectAgent()` uses Angular Signals and the modern injection context API. Angular 20 or later is required.
<Step title="Angular 20–22">
`injectAgent()` uses Angular Signals and the modern injection context API. Angular 20, 21, or 22 is required.
</Step>
<Step title="Node.js compatibility">
Use a Node.js version supported by the selected Angular major. Angular 22 supports Node.js ^22.22.3, ^24.15.0, or ^26.0.0. See the [Angular compatibility matrix](https://angular.dev/reference/versions).
Expand Down Expand Up @@ -120,7 +120,7 @@ export class TestComponent {

<Callout type="warning" title="Common issues">

**Version mismatch** -- If you see errors about missing APIs or unknown decorators, confirm your Angular version is 20 or later. Run `ng version` to check. Earlier versions do not support the injection context APIs that `injectAgent()` relies on.
**Version mismatch** -- If you see errors about missing APIs or unknown decorators, confirm your Angular version is 20, 21, or 22. Run `ng version` to check. Versions outside this range are not supported.

**CORS errors** -- If the browser console shows `Access-Control-Allow-Origin` errors, your LangGraph server is not configured for cross-origin requests. The LangGraph dev server allows all origins by default. For production, make sure your deployment's CORS policy includes your Angular app's domain.

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

> **Picking an adapter?** This guide covers `@threadplane/langgraph`, the LangChain/LangGraph adapter. If your backend speaks the AG-UI protocol (CrewAI, Mastra, Microsoft Agent Framework, and so on), reach for [`@threadplane/ag-ui`](/ag-ui) instead. [Choosing an adapter](/docs/choosing-an-adapter) puts them side by side.

`@threadplane/langgraph` is the Angular adapter layer for production agent UI surfaces: chat, durable threads, interrupts, subagents, planning, memory, and generative UI. You build the whole Angular 20+ app with Signals, wire it to LangGraph agents, and keep the UI inside Angular templates, dependency injection, and your design system.
`@threadplane/langgraph` is the Angular adapter layer for production agent UI surfaces: chat, durable threads, interrupts, subagents, planning, memory, and generative UI. You build the whole Angular 20–22 app with Signals, wire it to LangGraph agents, and keep the UI inside Angular templates, dependency injection, and your design system.

<Callout type="info" title="What you'll learn">
This guide walks you through the complete workflow: build a LangGraph agent in Python, run it locally, connect it to an Angular app with `injectAgent()`, and deploy to production.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Build a streaming chat component with `injectAgent()` in 5 minutes.

<Callout type="info" title="Prerequisites">
Angular 20+ project with Node.js 18+. If you need setup help, see the [Installation](/docs/langgraph/getting-started/installation) guide.
Angular 20–22 project using a Node.js version supported by that Angular major. If you need setup help, see the [Installation](/docs/langgraph/getting-started/installation) guide.
</Callout>

<Steps>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Detailed setup guide for `@threadplane/render` in your Angular application.
Supported Angular majors: 20, 21, and 22.

<Steps>
<Step title="Angular 20+">
`@threadplane/render` uses Angular Signals, the `input()` function, and the `NgComponentOutlet` directive. Angular 20 or later is required.
<Step title="Angular 20–22">
`@threadplane/render` uses Angular Signals, the `input()` function, and the `NgComponentOutlet` directive. Angular 20, 21, or 22 is required.
</Step>
<Step title="Node.js compatibility">
Use a Node.js version supported by the selected Angular major. Angular 22 supports Node.js ^22.22.3, ^24.15.0, or ^26.0.0. See the [Angular compatibility matrix](https://angular.dev/reference/versions).
Expand All @@ -32,7 +32,7 @@ The library requires the following peer dependencies:
| `@json-render/core` | `^0.16.0` |

<Callout type="info" title="Angular packages">
`@angular/core` and `@angular/common` are already part of any Angular 20+ project. You only need to install `@json-render/core` yourself if your package manager doesn't install peer dependencies automatically.
`@angular/core` and `@angular/common` are already part of any Angular 20–22 project. You only need to install `@json-render/core` yourself if your package manager doesn't install peer dependencies automatically.
</Callout>

## Configure the Provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Render a JSON spec as a live Angular component tree in 5 minutes.

<Callout type="info" title="Prerequisites">
Angular 20+ project with `@threadplane/render` installed. See the [Installation](/docs/render/getting-started/installation) guide if you need setup help.
Angular 20–22 project with `@threadplane/render` installed. See the [Installation](/docs/render/getting-started/installation) guide if you need setup help.
</Callout>

<Steps>
Expand Down
2 changes: 1 addition & 1 deletion apps/website/content/prompts/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Add angular to my Angular 20+ application.
Add angular to my Angular 20–22 application.

Install: npm install @threadplane/chat @threadplane/langgraph @langchain/core @langchain/langgraph-sdk marked

Expand Down
4 changes: 3 additions & 1 deletion apps/website/public/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Threadplane v0.0.62
# Threadplane v0.0.64

Production-ready chat, thread/history/branch UI, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.

Supported Angular majors: 20, 21, and 22.

## License and deployment boundary
- Every Threadplane package is MIT-licensed and free for commercial and noncommercial use.
- Threadplane runs inside the customer's Angular application. Agent runtime, models, storage, checkpointing, retention, authorization, and hosting remain customer-operated.
Expand Down
4 changes: 3 additions & 1 deletion apps/website/public/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Threadplane v0.0.62
# Threadplane v0.0.64

Production-ready chat, thread/history/branch UI, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.

Supported Angular majors: 20, 21, and 22.

## License and deployment boundary
- Every Threadplane package is MIT-licensed and free for commercial and noncommercial use.
- Threadplane runs inside the customer's Angular application. Agent runtime, models, storage, checkpointing, retention, authorization, and hosting remain customer-operated.
Expand Down
2 changes: 1 addition & 1 deletion apps/website/src/app/ag-ui/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default async function AgUiPage() {
</p>
<div className="ag-ui-page-hero-pills">
<Pill variant="accent">MIT</Pill>
<Pill variant="angular">Angular 20+</Pill>
<Pill variant="angular">Angular 20–22</Pill>
<Pill variant="neutral">AG-UI protocol</Pill>
</div>
<p className="ag-ui-page-langgraph-note">
Expand Down
4 changes: 2 additions & 2 deletions apps/website/src/app/langgraph/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default async function LangGraphPage() {
LangGraph agent UI for Angular.
</h1>
<p className="langgraph-page-hero-subtitle">
Ship LangGraph agents inside your Angular 20+ app with headless chat, durable threads, interrupts, branch/history, tool progress, and generative UI.
Ship LangGraph agents inside your Angular 20–22 app with headless chat, durable threads, interrupts, branch/history, tool progress, and generative UI.
</p>
<div className="langgraph-page-hero-buttons">
<Button variant="primary" size="lg" href="/docs/langgraph/getting-started/introduction">Get started</Button>
Expand All @@ -40,7 +40,7 @@ export default async function LangGraphPage() {
</p>
<div className="langgraph-page-hero-pills">
<Pill variant="accent">MIT</Pill>
<Pill variant="angular">Angular 20+</Pill>
<Pill variant="angular">Angular 20–22</Pill>
<Pill variant="neutral">LangGraph + AG-UI</Pill>
</div>
</div>
Expand Down
93 changes: 93 additions & 0 deletions apps/website/src/lib/angular-support-copy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: MIT
import fs from 'node:fs';
import path from 'node:path';
import { describe, expect, it } from 'vitest';
import { resolveWebsiteDir } from './website-dir';

const SUPPORTED_ANGULAR_COPY = 'Supported Angular majors: 20, 21, and 22.';
const SUPPORTED_ANGULAR_PEER_RANGE = '^20.0.0 || ^21.0.0 || ^22.0.0';

function walkFiles(dir: string, extensions: ReadonlySet<string>): string[] {
const files: string[] = [];
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...walkFiles(fullPath, extensions));
} else if (entry.isFile() && extensions.has(path.extname(entry.name))) {
files.push(fullPath);
}
}
return files;
}

function publicCopyFiles(): string[] {
const websiteDir = resolveWebsiteDir();
const workspaceDir = path.resolve(websiteDir, '..', '..');
const libraryReadmes = fs
.readdirSync(path.join(workspaceDir, 'libs'), { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => path.join(workspaceDir, 'libs', entry.name, 'README.md'))
.filter((file) => fs.existsSync(file));

return [
path.join(workspaceDir, 'README.md'),
...libraryReadmes,
...walkFiles(path.join(websiteDir, 'content'), new Set(['.md', '.mdx'])),
...walkFiles(path.join(websiteDir, 'src', 'app'), new Set(['.ts', '.tsx'])),
];
}

describe('Angular support copy', () => {
it('does not publish stale or open-ended Angular and Node support claims', () => {
const staleClaims = [
/Angular 20\+/g,
/Angular 20 or later/g,
/Angular 20 and 21(?!,? and 22)/g,
/Node\.js 18\+/g,
/Node\.js 22\+/g,
/Node\.js 22 or later/g,
];
const workspaceDir = path.resolve(resolveWebsiteDir(), '..', '..');
const offenders: string[] = [];

for (const file of publicCopyFiles()) {
const source = fs.readFileSync(file, 'utf8');
for (const staleClaim of staleClaims) {
if (staleClaim.test(source)) {
offenders.push(`${path.relative(workspaceDir, file)}: ${staleClaim.source}`);
}
staleClaim.lastIndex = 0;
}
}

expect(offenders).toEqual([]);
});

it('teaches adapter authors the complete supported Angular peer range', () => {
const guide = fs.readFileSync(
path.join(resolveWebsiteDir(), 'content', 'docs', 'chat', 'guides', 'writing-an-adapter.mdx'),
'utf8'
);

expect(guide).toContain(`"@angular/core": "${SUPPORTED_ANGULAR_PEER_RANGE}"`);
});

it('keeps generated agent guidance on the current release and support range', () => {
const websiteDir = resolveWebsiteDir();
const workspaceDir = path.resolve(websiteDir, '..', '..');
const packageVersion = JSON.parse(
fs.readFileSync(path.join(workspaceDir, 'libs', 'langgraph', 'package.json'), 'utf8')
) as { version: string };

for (const file of ['AGENTS.md.template', 'CLAUDE.md.template']) {
const source = fs.readFileSync(path.join(websiteDir, 'content', file), 'utf8');
expect(source).toContain(SUPPORTED_ANGULAR_COPY);
}

for (const file of ['AGENTS.md', 'CLAUDE.md']) {
const source = fs.readFileSync(path.join(websiteDir, 'public', file), 'utf8');
expect(source).toContain(`# Threadplane v${packageVersion.version}`);
expect(source).toContain(SUPPORTED_ANGULAR_COPY);
}
});
});
2 changes: 1 addition & 1 deletion libs/chat/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @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.
Drop-in agent chat UI for Angular 20–22. 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](https://github.com/cacheplane/angular-agent-framework).

Expand Down
Loading