Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6fe98f2
docs(specs): add chat runtime decoupling design
blove Apr 21, 2026
015c46b
docs(specs): define ChatContentBlock in decoupling design
blove Apr 21, 2026
2ff1c02
docs(plans): add Phase 1 implementation plan for chat runtime decoupling
blove Apr 21, 2026
622daed
feat(chat): add ChatAgent data types (message, tool call, content blo…
blove Apr 21, 2026
53d6ff1
feat(chat): add ChatInterrupt, ChatSubagent, submit input/options types
blove Apr 21, 2026
64b59eb
feat(chat): define ChatAgent runtime-neutral contract
blove Apr 21, 2026
52d878b
feat(chat): export ChatAgent contract from public-api
blove Apr 21, 2026
03edfa6
docs(chat): document runtime-neutral ChatAgent and adapters
blove Apr 21, 2026
acaadab
chore(chat): add SPDX header to agent spec files
blove Apr 21, 2026
08fb2fc
docs(chat): clarify ChatSubmitInput.message JSDoc
blove Apr 21, 2026
d17158a
feat(chat): add mockChatAgent() test helper
blove Apr 21, 2026
19c95c2
feat(chat): add ChatAgent conformance test suite
blove Apr 21, 2026
0341b29
refactor(chat): rename submit param to avoid shadowing in mockChatAgent
blove Apr 21, 2026
e0dbd88
feat(agent): add toChatAgent() adapter to runtime-neutral ChatAgent c…
blove Apr 21, 2026
c81e574
feat(agent): export toChatAgent
blove Apr 21, 2026
0a2e977
test(agent): verify toChatAgent satisfies ChatAgent conformance
blove Apr 21, 2026
ed78de9
refactor(agent): rename cryptoRandom to randomId; use for interrupt i…
blove Apr 21, 2026
15dc162
refactor: rename libs/agent to libs/langgraph; @cacheplane/angular to…
blove Apr 21, 2026
0512f24
refactor(chat): migrate chat-input to ChatAgent contract
blove Apr 21, 2026
4e94fb0
refactor(chat): migrate chat-messages to ChatAgent contract
blove Apr 21, 2026
34b4102
refactor(chat): migrate chat-tool-calls to ChatAgent contract
blove Apr 21, 2026
31ebba2
refactor(chat): migrate chat-typing-indicator to ChatAgent contract
blove Apr 21, 2026
fdd8108
refactor(chat): migrate chat-error to ChatAgent contract
blove Apr 21, 2026
718ffd8
refactor(chat): drop redundant tool_use cast; rely on discriminant na…
blove Apr 21, 2026
d7cea2f
refactor(chat): migrate chat composition core path to ChatAgent
blove Apr 21, 2026
c67a29c
chore(chat): mark remaining primitives as phase-2/phase-3 migration
blove Apr 21, 2026
1121b74
feat(chat): add ChatCustomEvent type and optional customEvents$ to Ch…
blove Apr 21, 2026
712fcb6
test(chat): extend mock + conformance for customEvents\$
blove Apr 21, 2026
6c79768
feat(langgraph): bridge customEvents signal to Observable in toChatAgent
blove Apr 21, 2026
c1d2a80
refactor(chat): migrate chat-interrupt from AgentRef to ChatAgent
blove Apr 21, 2026
889a605
refactor(chat): replace langgraphRef with ChatAgent.customEvents$ sub…
blove Apr 21, 2026
6f2de67
refactor(chat): migrate chat-subagents from AgentRef to ChatAgent
blove Apr 21, 2026
470c8f3
refactor(chat): migrate chat-subagent-card to ChatSubagent contract
blove Apr 21, 2026
c2b0503
refactor(chat): migrate chat-interrupt-panel to ChatAgent contract
blove Apr 21, 2026
bb9bd04
refactor(chat,langgraph): relocate LangGraph-specific primitives to @…
blove Apr 21, 2026
e58d503
refactor(chat): drop @cacheplane/langgraph peer-dep, breaking the cir…
blove Apr 21, 2026
2be46e7
refactor(cockpit): bind cockpit demos to ChatAgent via toChatAgent
blove Apr 21, 2026
599bc45
fix(chat,langgraph): final Phase-1 build fixes
blove Apr 21, 2026
d0bd796
refactor(chat,langgraph): polish Phase-1 review nits
blove Apr 22, 2026
73f7298
fix(langgraph): silence no-empty-function on AgentRef test stubs
blove Apr 22, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ jobs:
node-version: 22
cache: npm
- run: npm ci
- run: npx nx lint agent
- run: npx nx test agent --coverage
- run: npx nx build agent --configuration=production
- run: npx nx lint langgraph
- run: npx nx test langgraph --coverage
- run: npx nx build langgraph --configuration=production

website:
name: Website — lint / build
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npx nx test mcp --skip-nx-cache
- run: npx nx test agent
- run: npx nx build agent --configuration=production
- run: npx nx test langgraph
- run: npx nx build langgraph --configuration=production
- name: Publish to npm
run: npx nx-release-publish agent
env:
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ This file is for agents working in this repository. It is contributor-facing, no

## Repo Layout

- `libs/agent`: main Angular library (`@cacheplane/angular`).
- `libs/langgraph`: main Angular library (`@cacheplane/langgraph`).
- `apps/website`: docs and marketing site.
- `packages/mcp`: MCP server package (`@cacheplane/angular-mcp`).
- `packages/mcp`: MCP server package (`@cacheplane/langgraph-mcp`).
- `e2e/agent-e2e`: end-to-end coverage for the workspace.
- `apps/demo` and `apps/demo-e2e`: demo application and related end-to-end coverage.

Expand Down
2 changes: 1 addition & 1 deletion COMMERCIAL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Commercial Licensing

`@cacheplane/angular` is source-available software dual-licensed under:
`@cacheplane/langgraph` is source-available software dual-licensed under:

- **PolyForm Noncommercial 1.0.0** — free for noncommercial use (see [`LICENSE`](./LICENSE))
- **Angular Agent Framework Commercial License** — required for commercial use (see [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL))
Expand Down
2 changes: 1 addition & 1 deletion LICENSE-COMMERCIAL
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Commercial License
Copyright (c) 2026 Brian Love d/b/a cacheplane. All rights reserved.

This Commercial License ("License") governs commercial use of the
@cacheplane/angular software ("Software"). Use of the Software for
@cacheplane/langgraph software ("Software"). Use of the Software for
commercial purposes requires a valid license purchased from cacheplane.

--- LICENSE TIERS ---
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</p>

<p align="center">
<a href="https://www.npmjs.com/package/@cacheplane/angular">
<a href="https://www.npmjs.com/package/@cacheplane/langgraph">
<img alt="npm version" src="https://img.shields.io/npm/v/@cacheplane%2Fangular?color=6C8EFF&labelColor=080B14&style=flat-square" />
</a>
<a href="./LICENSE">
Expand All @@ -34,7 +34,7 @@
## Install

```bash
npm install @cacheplane/angular
npm install @cacheplane/langgraph
```

**Peer dependencies:** `@angular/core ^20.0.0 || ^21.0.0`, `@langchain/core ^1.1.0`, `@langchain/langgraph-sdk ^1.7.0`, `rxjs ~7.8.0`
Expand All @@ -45,7 +45,7 @@ npm install @cacheplane/angular

```typescript
import { Component } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({
Expand Down Expand Up @@ -145,7 +145,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp

## License

`@cacheplane/angular` is source-available software dual-licensed:
`@cacheplane/langgraph` is source-available software dual-licensed:

- **PolyForm Noncommercial 1.0.0** — free for noncommercial use (personal projects, academic, research, non-profit internal tooling). See [`LICENSE`](./LICENSE).
- **Angular Agent Framework Commercial License** — required for any for-profit or revenue-generating use. See [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL) and [`COMMERCIAL.md`](./COMMERCIAL.md).
Expand Down
2 changes: 1 addition & 1 deletion apps/demo/src/app/chat-demo/chat-demo.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input, OnInit, Injector, runInInjectionContext } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({
Expand Down
8 changes: 4 additions & 4 deletions apps/website/content/AGENTS.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
Angular agent framework for LangChain/LangGraph. Provides `agent()` — Signal-native streaming for Angular agents, built for LangGraph.

## Install
npm install @cacheplane/angular
npm install @cacheplane/langgraph

## Key requirement
`agent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context".

## Basic usage
```typescript
// app.config.ts
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';
export const appConfig: ApplicationConfig = {
providers: [provideAgent({ apiUrl: 'http://localhost:2024' })]
};

// chat.component.ts
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({ template: `
Expand All @@ -38,7 +38,7 @@ export class ChatComponent {

## MCP server (for tool access)
Add to ~/.claude/settings.json:
{"mcpServers":{"angular-agent":{"command":"npx","args":["@cacheplane/angular-mcp"]}}}
{"mcpServers":{"angular-agent":{"command":"npx","args":["@cacheplane/langgraph-mcp"]}}}

## Version check
If this file is stale, fetch the latest: https://cacheplane.ai/llms-full.txt
8 changes: 4 additions & 4 deletions apps/website/content/CLAUDE.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
Angular agent framework for LangChain/LangGraph. Provides `agent()` — Signal-native streaming for Angular agents, built for LangGraph.

## Install
npm install @cacheplane/angular
npm install @cacheplane/langgraph

## Key requirement
`agent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context".

## Basic usage
```typescript
// app.config.ts
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';
export const appConfig: ApplicationConfig = {
providers: [provideAgent({ apiUrl: 'http://localhost:2024' })]
};

// chat.component.ts
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({ template: `
Expand All @@ -38,7 +38,7 @@ export class ChatComponent {

## MCP server (for tool access)
Add to ~/.claude/settings.json:
{"mcpServers":{"angular-agent":{"command":"npx","args":["@cacheplane/angular-mcp"]}}}
{"mcpServers":{"angular-agent":{"command":"npx","args":["@cacheplane/langgraph-mcp"]}}}

## Version check
If this file is stale, fetch the latest: https://cacheplane.ai/llms-full.txt
2 changes: 1 addition & 1 deletion apps/website/content/docs/agent/api/agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
When the `url` signal changes, the resource tears down the previous connection and opens a fresh one automatically. You never write subscription management or cleanup logic yourself.

```ts
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

// Inside a component or service with injection context
const repo = agent<Repository>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In most apps you will never import or inject `FetchStreamTransport` by name —

```ts
import { inject } from '@angular/core';
import { agent, FetchStreamTransport } from '@cacheplane/angular';
import { agent, FetchStreamTransport } from '@cacheplane/langgraph';

// Override transport for a single resource
const events = agent<Event>({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
provideAgent,
MockAgentTransport,
agent,
} from '@cacheplane/angular';
} from '@cacheplane/langgraph';

@Component({ template: '' })
class RepoComponent {
Expand Down
2 changes: 1 addition & 1 deletion apps/website/content/docs/agent/api/provide-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { bootstrapApplication } from '@angular/platform-browser';
import {
provideAgent,
FetchStreamTransport,
} from '@cacheplane/angular';
} from '@cacheplane/langgraph';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agent Architecture

How AI agents work — the planning, execution, and tool-calling lifecycle that agent() connects your Angular app to. This page shows you the Python patterns that power modern agents and exactly how each pattern surfaces in Angular through `@cacheplane/angular`.
How AI agents work — the planning, execution, and tool-calling lifecycle that agent() connects your Angular app to. This page shows you the Python patterns that power modern agents and exactly how each pattern surfaces in Angular through `@cacheplane/langgraph`.

<Callout type="info" title="Python + Angular, both sides">
Every section below shows the Python backend code first, then the Angular frontend code that consumes it. You need both halves to build a production agent application — LangGraph handles the intelligence, agent() handles the reactivity.
Expand Down Expand Up @@ -149,7 +149,7 @@ graph = builder.compile()

```typescript
import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

interface AgentState {
messages: BaseMessage[];
Expand Down Expand Up @@ -401,7 +401,7 @@ graph = builder.compile()

```typescript
import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

interface OrchestratorState {
messages: BaseMessage[];
Expand Down
8 changes: 4 additions & 4 deletions apps/website/content/docs/agent/concepts/angular-signals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const status = toSignal(status$, { initialValue: 'idle' });
<Tab label="What you see">

```typescript
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

// You never touch BehaviorSubjects or toSignal() yourself.
// agent() hands you clean Signals:
Expand Down Expand Up @@ -154,7 +154,7 @@ console.log(chat.isLoading()); // false

```typescript
import { computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

const chat = agent<ChatState>({
assistantId: 'chat_agent',
Expand Down Expand Up @@ -259,7 +259,7 @@ Angular's new control flow syntax (`@if`, `@for`, `@switch`) works naturally wit

```typescript
import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, ViewChild } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

@Component({
selector: 'app-chat',
Expand Down Expand Up @@ -457,7 +457,7 @@ graph = builder.compile()

```typescript
import { ChangeDetectionStrategy, Component, computed, effect } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

@Component({
selector: 'app-chat',
Expand Down
4 changes: 2 additions & 2 deletions apps/website/content/docs/agent/concepts/state-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This inversion is intentional. Agent state can span multiple LLM calls, tool exe
Your Angular component calls `agent.submit({ messages: [userMsg] })`. No state is stored in the component.
</Step>
<Step title="agent() sends the request">
`@cacheplane/angular` forwards the input to `FetchStreamTransport`, which opens an HTTP POST and SSE connection to LangGraph Platform.
`@cacheplane/langgraph` forwards the input to `FetchStreamTransport`, which opens an HTTP POST and SSE connection to LangGraph Platform.
</Step>
<Step title="LangGraph Platform executes the graph">
The agent runs its nodes — calling the LLM, invoking tools, checking conditions — and streams SSE events back with incremental state updates.
Expand Down Expand Up @@ -419,7 +419,7 @@ def researcher_node(state: ResearchState) -> dict:

```typescript
import { BaseMessage } from '@langchain/core/messages';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

interface ResearchState {
messages: BaseMessage[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ A running LangGraph agent accessible via HTTP. Can be local (langgraph dev) or d
## Install the package

```bash
npm install @cacheplane/angular
npm install @cacheplane/langgraph
```

This installs the library and its peer dependencies including `@langchain/langgraph-sdk`.
Expand All @@ -31,7 +31,7 @@ Add `provideAgent()` to your application configuration. This sets global default
```typescript
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';
import { environment } from '../environments/environment';

export const appConfig: ApplicationConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Now connect your Angular app to the running agent using agent().
<Step title="Install the package">

```bash
npm install @cacheplane/angular
npm install @cacheplane/langgraph
```

</Step>
Expand All @@ -135,7 +135,7 @@ npm install @cacheplane/angular
```typescript
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -155,7 +155,7 @@ export const appConfig: ApplicationConfig = {
```typescript
// chat.component.ts
import { Component, signal, computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Angular 20+ project with Node.js 18+. If you need setup help, see the [Installat
<Step title="Install the package">

```bash
npm install @cacheplane/angular
npm install @cacheplane/langgraph
```

</Step>
Expand All @@ -20,7 +20,7 @@ Add `provideAgent()` to your application config with your LangGraph Platform URL

```typescript
// app.config.ts
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -42,7 +42,7 @@ Use `agent()` in a component field initializer. Every property on the returned r
```typescript
// chat.component.ts
import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';
import type { BaseMessage } from '@langchain/core/messages';

@Component({
Expand Down
4 changes: 2 additions & 2 deletions apps/website/content/docs/agent/guides/deployment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const environment = {
Wire the environment into `provideAgent()`:

```typescript
import { provideAgent } from '@cacheplane/angular';
import { provideAgent } from '@cacheplane/langgraph';
import { environment } from '../environments/environment';

export const appConfig: ApplicationConfig = {
Expand Down Expand Up @@ -202,7 +202,7 @@ Production apps need graceful error handling. Build a reactive error boundary us

```typescript
import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { agent } from '@cacheplane/angular';
import { agent } from '@cacheplane/langgraph';

@Component({
selector: 'app-chat',
Expand Down
6 changes: 3 additions & 3 deletions apps/website/content/docs/agent/guides/interrupts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ import {
signal,
ChangeDetectionStrategy,
} from '@angular/core';
import { agent, BaseMessage } from '@cacheplane/angular';
import { agent, BaseMessage } from '@cacheplane/langgraph';

interface ApprovalPayload {
action: string;
Expand Down Expand Up @@ -354,7 +354,7 @@ import {
computed,
ChangeDetectionStrategy,
} from '@angular/core';
import { agent, BaseMessage } from '@cacheplane/angular';
import { agent, BaseMessage } from '@cacheplane/langgraph';

interface StepApproval {
step_number: number;
Expand Down Expand Up @@ -454,7 +454,7 @@ By default, `interrupt()` returns an untyped object. The BagTemplate generic par
BagTemplate is a type parameter on the agent configuration that maps signal names to their types. When you specify an interrupt type through BagTemplate, the `interrupt()` signal returns a properly typed object instead of `unknown`. This means your template expressions, computed signals, and event handlers all benefit from compile-time checking.

```typescript
import { agent, BagTemplate } from '@cacheplane/angular';
import { agent, BagTemplate } from '@cacheplane/langgraph';

// Define the exact shape of your interrupt payload
interface DeployApproval {
Expand Down
Loading
Loading