Skip to content

Commit f70053d

Browse files
authored
feat: support Angular 22 consumers (#887)
* docs: specify Angular 22 consumer support * docs: plan Angular 22 consumer support * test(smoke): define Angular compatibility lanes * feat(smoke): generate strict versioned Angular consumers * test(smoke): add browser compatibility probes * fix(chat): preserve A2UI change detection across Angular versions * feat: add Angular 22 package peers * feat(website): mark Angular 22 supported * ci: test packaged libraries across Angular majors * docs: document Angular 22 support * docs: correct Angular Node guidance * test: verify Angular support badges * test: strengthen Angular badge fixtures
1 parent d1f77d1 commit f70053d

62 files changed

Lines changed: 4884 additions & 363 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
runs-on: ubuntu-latest
2323
outputs:
2424
library: ${{ steps.scope.outputs.library }}
25+
angular_compatibility: ${{ steps.scope.outputs.angular_compatibility }}
2526
website: ${{ steps.scope.outputs.website }}
2627
cockpit: ${{ steps.scope.outputs.cockpit }}
2728
cockpit_examples: ${{ steps.scope.outputs.cockpit_examples }}
@@ -79,7 +80,7 @@ jobs:
7980
library:
8081
name: Library — lint / test / build
8182
needs: ci-scope
82-
if: github.event_name == 'push' || needs.ci-scope.outputs.library == 'true'
83+
if: github.event_name == 'push' || needs.ci-scope.outputs.library == 'true' || needs.ci-scope.outputs.angular_compatibility == 'true'
8384
runs-on: ubuntu-latest
8485
env:
8586
LIBS: chat,langgraph,ag-ui,render,a2ui,telemetry
@@ -97,6 +98,60 @@ jobs:
9798
- run: node scripts/verify-release-versions.mjs
9899
- name: DX-coverage — public dev-facing functions must have a JSDoc summary
99100
run: node scripts/check-dx-coverage.mjs
101+
- run: node --test examples/chat/smoke/*.spec.mjs scripts/verify-angular-support.spec.mjs
102+
- run: node scripts/verify-angular-support.mjs
103+
- name: Upload production library artifact
104+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
105+
with:
106+
name: threadplane-library-dist
107+
path: dist/libs
108+
if-no-files-found: error
109+
retention-days: 1
110+
111+
angular-compatibility:
112+
name: 'Angular ${{ matrix.angular }} — packaged consumer'
113+
needs: [ci-scope, library]
114+
if: github.event_name == 'push' || needs.ci-scope.outputs.angular_compatibility == 'true'
115+
runs-on: ubuntu-latest
116+
timeout-minutes: 20
117+
strategy:
118+
fail-fast: false
119+
matrix:
120+
angular: [20, 21, 22]
121+
steps:
122+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
123+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
124+
with:
125+
node-version: 22.22.3
126+
cache: npm
127+
- run: npm ci
128+
- name: Download production library artifact
129+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
130+
with:
131+
name: threadplane-library-dist
132+
path: dist/libs
133+
- name: Install Chromium
134+
run: npx playwright install --with-deps chromium
135+
- name: Generate, install, build, and run consumer
136+
run: >-
137+
node examples/chat/smoke/cli.mjs
138+
--non-interactive --fresh
139+
--target "${{ runner.temp }}/threadplane-angular-${{ matrix.angular }}"
140+
--local-dist-root dist/libs
141+
--angular-major "${{ matrix.angular }}"
142+
--install --build --runtime
143+
- name: Upload compatibility diagnostics on failure
144+
if: failure()
145+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
146+
with:
147+
name: angular-${{ matrix.angular }}-compatibility-diagnostics
148+
path: |
149+
${{ runner.temp }}/threadplane-angular-${{ matrix.angular }}/package.json
150+
${{ runner.temp }}/threadplane-angular-${{ matrix.angular }}/package-lock.json
151+
${{ runner.temp }}/threadplane-angular-${{ matrix.angular }}/runtime-smoke.png
152+
${{ runner.temp }}/threadplane-angular-${{ matrix.angular }}/runtime-smoke-trace.zip
153+
if-no-files-found: warn
154+
retention-days: 7
100155

101156
website:
102157
name: Website — lint / test / build
@@ -240,7 +295,7 @@ jobs:
240295
- run: npx nx run examples-chat-python:smoke --skip-nx-cache
241296

242297
examples-chat-e2e:
243-
name: "examples/chat — e2e (${{ matrix.shard }}/4)"
298+
name: 'examples/chat — e2e (${{ matrix.shard }}/4)'
244299
needs: ci-scope
245300
if: github.event_name == 'push' || needs.ci-scope.outputs.examples_chat == 'true'
246301
runs-on: ubuntu-latest
@@ -287,7 +342,7 @@ jobs:
287342
retention-days: 7
288343

289344
examples-chat-e2e-summary:
290-
name: "examples/chat — e2e"
345+
name: 'examples/chat — e2e'
291346
needs: [ci-scope, examples-chat-e2e]
292347
if: always() && (github.event_name == 'push' || needs.ci-scope.outputs.examples_chat == 'true')
293348
runs-on: ubuntu-latest
@@ -301,7 +356,7 @@ jobs:
301356
echo "All examples-chat-e2e matrix expansions passed."
302357
303358
examples-ag-ui-e2e:
304-
name: "examples/ag-ui — e2e"
359+
name: 'examples/ag-ui — e2e'
305360
needs: ci-scope
306361
# No dedicated ci-scope output exists for examples/ag-ui yet, so this job
307362
# runs on every push and pull_request rather than being scope-gated. It is
@@ -383,7 +438,7 @@ jobs:
383438
--full-fleet "${{ steps.refs.outputs.full }}"
384439
385440
cockpit-e2e:
386-
name: "Cockpit — e2e (${{ matrix.cap.angular }})"
441+
name: 'Cockpit — e2e (${{ matrix.cap.angular }})'
387442
needs: [ci-scope, cockpit-e2e-dispatcher]
388443
if: github.event_name == 'push' || needs.ci-scope.outputs.cockpit_e2e == 'true'
389444
runs-on: ubuntu-latest
@@ -431,7 +486,7 @@ jobs:
431486
retention-days: 7
432487

433488
cockpit-e2e-summary:
434-
name: "Cockpit — e2e"
489+
name: 'Cockpit — e2e'
435490
needs: [ci-scope, cockpit-e2e]
436491
if: always() && (github.event_name == 'push' || needs.ci-scope.outputs.cockpit_e2e == 'true')
437492
runs-on: ubuntu-latest
@@ -471,6 +526,7 @@ jobs:
471526
needs:
472527
- ci-scope
473528
- library
529+
- angular-compatibility
474530
- website
475531
- cockpit
476532
- cockpit-examples-build
@@ -488,6 +544,7 @@ jobs:
488544
env:
489545
RESULT_CI_SCOPE: ${{ needs.ci-scope.result }}
490546
RESULT_LIBRARY: ${{ needs.library.result }}
547+
RESULT_ANGULAR_COMPATIBILITY: ${{ needs.angular-compatibility.result }}
491548
RESULT_WEBSITE: ${{ needs.website.result }}
492549
RESULT_COCKPIT: ${{ needs.cockpit.result }}
493550
RESULT_COCKPIT_EXAMPLES: ${{ needs.cockpit-examples-build.result }}
@@ -499,6 +556,7 @@ jobs:
499556
RESULT_WEBSITE_E2E: ${{ needs.website-e2e.result }}
500557
RESULT_POSTHOG: ${{ needs.posthog-sync-plan.result }}
501558
SCOPE_LIBRARY: ${{ needs.ci-scope.outputs.library }}
559+
SCOPE_ANGULAR_COMPATIBILITY: ${{ needs.ci-scope.outputs.angular_compatibility }}
502560
SCOPE_WEBSITE: ${{ needs.ci-scope.outputs.website }}
503561
SCOPE_COCKPIT: ${{ needs.ci-scope.outputs.cockpit }}
504562
SCOPE_COCKPIT_EXAMPLES: ${{ needs.ci-scope.outputs.cockpit_examples }}
@@ -545,6 +603,11 @@ jobs:
545603
546604
require_always "CI scope" "$RESULT_CI_SCOPE"
547605
require_scoped "library" "Library — lint / test / build" "$RESULT_LIBRARY" "$SCOPE_LIBRARY"
606+
require_scoped \
607+
"angular_compatibility" \
608+
"Angular compatibility matrix" \
609+
"$RESULT_ANGULAR_COMPATIBILITY" \
610+
"$SCOPE_ANGULAR_COMPATIBILITY"
548611
require_scoped "website" "Website — lint / test / build" "$RESULT_WEBSITE" "$SCOPE_WEBSITE"
549612
require_scoped "cockpit" "Cockpit — build / test" "$RESULT_COCKPIT" "$SCOPE_COCKPIT"
550613
require_scoped "cockpit_examples" "Cockpit — build all examples" "$RESULT_COCKPIT_EXAMPLES" "$SCOPE_COCKPIT_EXAMPLES"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<img alt="npm version" src="https://img.shields.io/npm/v/@threadplane%2Flanggraph?color=6C8EFF&labelColor=080B14&style=flat-square" />
1616
</a>
1717
<a href="https://angular.dev">
18-
<img alt="Angular 20+" src="https://img.shields.io/badge/Angular-20%2B-6C8EFF?labelColor=080B14&style=flat-square" />
18+
<img alt="Angular 20 | 21 | 22" src="https://img.shields.io/badge/Angular-20%20%7C%2021%20%7C%2022-6C8EFF?labelColor=080B14&style=flat-square" />
1919
</a>
2020
<a href="https://langchain-ai.github.io/langgraph/">
2121
<img alt="LangGraph" src="https://img.shields.io/badge/LangGraph-SDK-6C8EFF?labelColor=080B14&style=flat-square" />
@@ -45,7 +45,7 @@ Threadplane is a production-ready agent UI framework for Angular. `@threadplane/
4545
npm install @threadplane/langgraph @threadplane/chat
4646
```
4747

48-
**Peer dependencies:** `@angular/core ^20.0.0 || ^21.0.0`, `@langchain/core ^1.1.33`, `@langchain/langgraph-sdk ^1.7.4`, `rxjs ~7.8.0`
48+
**Peer dependencies:** `@angular/core ^20.0.0 || ^21.0.0 || ^22.0.0`, `@langchain/core ^1.1.33`, `@langchain/langgraph-sdk ^1.7.4`, `rxjs ~7.8.0`
4949

5050
---
5151

apps/website/content/docs/ag-ui/getting-started/installation.mdx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# Installation
22

3+
Supported Angular majors: 20, 21, and 22.
4+
5+
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).
6+
37
## Prerequisites
48

59
- Angular 20 or later
6-
- Node.js 22+
710
- 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`)
811

912
## Install packages
@@ -19,13 +22,13 @@ npm install @threadplane/chat @threadplane/ag-ui @ag-ui/client @ag-ui/core marke
1922

2023
`@threadplane/ag-ui` declares the following peer dependencies:
2124

22-
| Package | Version |
23-
|---|---|
24-
| `@threadplane/chat` | `*` |
25-
| `@angular/core` | `^20.0.0 \|\| ^21.0.0` |
26-
| `@ag-ui/client` | `*` |
27-
| `@ag-ui/core` | `*` |
28-
| `rxjs` | `~7.8.0` |
25+
| Package | Version |
26+
| ------------------- | ----------------------------------- |
27+
| `@threadplane/chat` | `*` |
28+
| `@angular/core` | `^20.0.0 \|\| ^21.0.0 \|\| ^22.0.0` |
29+
| `@ag-ui/client` | `*` |
30+
| `@ag-ui/core` | `*` |
31+
| `rxjs` | `~7.8.0` |
2932

3033
## Configure the provider
3134

@@ -38,20 +41,20 @@ import { provideAgent } from '@threadplane/ag-ui';
3841
export const appConfig: ApplicationConfig = {
3942
providers: [
4043
provideAgent({
41-
url: 'http://localhost:3000/agent', // your AG-UI backend
44+
url: 'http://localhost:3000/agent', // your AG-UI backend
4245
}),
4346
],
4447
};
4548
```
4649

4750
`provideAgent` accepts:
4851

49-
| Option | Type | Description |
50-
|---|---|---|
51-
| `url` | `string` | **Required.** AG-UI backend HTTP/SSE endpoint. |
52-
| `agentId` | `string` | Optional. Identifies a specific agent on the backend. |
53-
| `threadId` | `string` | Optional. Resume an existing conversation thread. |
54-
| `headers` | `Record<string, string>` | Optional. Custom request headers (auth, tracing). |
52+
| Option | Type | Description |
53+
| ----------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
54+
| `url` | `string` | **Required.** AG-UI backend HTTP/SSE endpoint. |
55+
| `agentId` | `string` | Optional. Identifies a specific agent on the backend. |
56+
| `threadId` | `string` | Optional. Resume an existing conversation thread. |
57+
| `headers` | `Record<string, string>` | Optional. Custom request headers (auth, tracing). |
5558
| `telemetry` | `AgentRuntimeTelemetrySink \| false` | Optional. App-owned telemetry sink — opt-in, emits nothing unless supplied. See [`@threadplane/telemetry`](/docs/telemetry/getting-started/introduction). |
5659

5760
## Use in a component
@@ -94,18 +97,22 @@ export const appConfig: ApplicationConfig = {
9497

9598
`provideFakeAgent` accepts:
9699

97-
| Option | Type | Description |
98-
|---|---|---|
99-
| `tokens` | `string[]` | Optional. Tokens streamed back as the assistant reply. |
100-
| `reasoningTokens` | `string[]` | Optional. Reasoning chunks emitted before the text reply (defaults to `[]`). |
101-
| `delayMs` | `number` | Optional. Milliseconds between successive token emissions (defaults to `60`). |
100+
| Option | Type | Description |
101+
| ----------------- | ---------- | ----------------------------------------------------------------------------- |
102+
| `tokens` | `string[]` | Optional. Tokens streamed back as the assistant reply. |
103+
| `reasoningTokens` | `string[]` | Optional. Reasoning chunks emitted before the text reply (defaults to `[]`). |
104+
| `delayMs` | `number` | Optional. Milliseconds between successive token emissions (defaults to `60`). |
102105

103106
## Custom transport
104107

105108
If you have a backend that speaks AG-UI but not over HTTP, subclass `AbstractAgent` directly and feed it to `toAgent`:
106109

107110
```ts
108-
import { AbstractAgent, type RunAgentInput, type BaseEvent } from '@ag-ui/client';
111+
import {
112+
AbstractAgent,
113+
type RunAgentInput,
114+
type BaseEvent,
115+
} from '@ag-ui/client';
109116
import { Observable } from 'rxjs';
110117
import { toAgent } from '@threadplane/ag-ui';
111118

apps/website/content/docs/chat/getting-started/installation.mdx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,25 @@ or runtime key.
66

77
## Prerequisites
88

9-
- Angular 20 or 21
10-
- Node.js 18 or later
11-
- An agent backend, or `mockAgent()` while you build the UI
9+
Supported Angular majors: 20, 21, and 22.
10+
11+
<Steps>
12+
<Step title="Angular 20 or later">
13+
`@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.
14+
</Step>
15+
<Step title="Node.js compatibility">
16+
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).
17+
</Step>
18+
<Step title="A running agent backend (or a mock)">
19+
The chat UI needs something to talk to. Two officially supported adapters cover virtually every backend:
20+
21+
- **`@threadplane/langgraph`** — pick this if your backend is LangGraph or LangGraph Platform.
22+
- **`@threadplane/ag-ui`** — pick this for an AG-UI-compatible backend such as CrewAI, Mastra, Microsoft Agent Framework, AG2, Pydantic AI, or AWS Strands.
23+
24+
Both adapters expose the same `Agent` contract to `@threadplane/chat`, so swapping later is a one-line change. If you don't have a backend yet, use `mockAgent()` from `@threadplane/chat` to wire up the UI first.
25+
26+
</Step>
27+
</Steps>
1228

1329
## 1. Install the packages
1430

@@ -24,10 +40,22 @@ npm install @threadplane/chat @threadplane/ag-ui @ag-ui/client @ag-ui/core marke
2440
`@json-render/core`, RxJS, and Zod as peer dependencies. npm 7 and later
2541
install required peers automatically. KaTeX is optional.
2642

43+
<Callout type="info" title="Full peer dependency list">
44+
`@threadplane/chat` declares peers on `@angular/core`, `@angular/common`,
45+
`@angular/platform-browser`, `@angular/router` (all `^20.0.0 || ^21.0.0 ||
46+
^22.0.0`), plus `@threadplane/render`, `@threadplane/a2ui`,
47+
`@json-render/core` (`^0.16.0`), `@langchain/core` (`^1.1.33`), `rxjs`
48+
(`~7.8.0`), `marked` (`^15 || ^16`), `zod` (`^3.25.0`), and optional `katex`
49+
(`^0.16.0 || ^0.17.0`). npm 7+ installs all required peers automatically.
50+
</Callout>
51+
2752
## 2. Configure the runtime and chat
2853

2954
```ts
30-
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core';
55+
import {
56+
ApplicationConfig,
57+
provideZonelessChangeDetection,
58+
} from '@angular/core';
3159
import { provideAgent } from '@threadplane/langgraph';
3260
import { provideChat } from '@threadplane/chat';
3361

apps/website/content/docs/langgraph/getting-started/installation.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ Detailed setup guide for `injectAgent()` in your Angular application.
44

55
## Requirements
66

7+
Supported Angular majors: 20, 21, and 22.
8+
79
<Steps>
810
<Step title="Angular 20+">
911
`injectAgent()` uses Angular Signals and the modern injection context API. Angular 20 or later is required.
1012
</Step>
11-
<Step title="Node.js 18+">
12-
Required for the build toolchain and package installation.
13+
<Step title="Node.js compatibility">
14+
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).
1315
</Step>
1416
<Step title="LangGraph Platform">
1517
A running LangGraph agent reachable over HTTP. Local (`langgraph dev`) or deployed (LangGraph Cloud) both work.
@@ -31,7 +33,7 @@ npm install @threadplane/langgraph @threadplane/chat @langchain/core @langchain/
3133
| Package | Version |
3234
|---------|---------|
3335
| `@threadplane/chat` | `*` |
34-
| `@angular/core` | `^20.0.0 \|\| ^21.0.0` |
36+
| `@angular/core` | `^20.0.0 \|\| ^21.0.0 \|\| ^22.0.0` |
3537
| `@langchain/core` | `^1.1.33` |
3638
| `@langchain/langgraph-sdk` | `^1.7.4` |
3739
| `rxjs` | `~7.8.0` |

apps/website/content/docs/render/getting-started/installation.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ Detailed setup guide for `@threadplane/render` in your Angular application.
44

55
## Requirements
66

7+
Supported Angular majors: 20, 21, and 22.
8+
79
<Steps>
810
<Step title="Angular 20+">
911
`@threadplane/render` uses Angular Signals, the `input()` function, and the `NgComponentOutlet` directive. Angular 20 or later is required.
1012
</Step>
11-
<Step title="Node.js 18+">
12-
Required for the build toolchain and package installation.
13+
<Step title="Node.js compatibility">
14+
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).
1315
</Step>
1416
</Steps>
1517

@@ -25,8 +27,8 @@ The library requires the following peer dependencies:
2527

2628
| Package | Version |
2729
|---------|---------|
28-
| `@angular/core` | `^20.0.0` or `^21.0.0` |
29-
| `@angular/common` | `^20.0.0` or `^21.0.0` |
30+
| `@angular/core` | `^20.0.0`, `^21.0.0`, or `^22.0.0` |
31+
| `@angular/common` | `^20.0.0`, `^21.0.0`, or `^22.0.0` |
3032
| `@json-render/core` | `^0.16.0` |
3133

3234
<Callout type="info" title="Angular packages">

0 commit comments

Comments
 (0)