diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ee36d470..6380fa31d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,9 +17,9 @@ jobs: node-version: 22 cache: npm - run: npm ci - - run: npx nx lint stream-resource - - run: npx nx test stream-resource --coverage - - run: npx nx build stream-resource --configuration=production + - run: npx nx lint angular + - run: npx nx test angular --coverage + - run: npx nx build angular --configuration=production website: name: Website — lint / build @@ -224,7 +224,7 @@ jobs: run: | mkdir -p .vercel cat > .vercel/project.json < Angular Stream Resource — The Enterprise Streaming Resource for LangChain and Angular

@@ -11,13 +11,13 @@

- - npm version + + npm version License: PolyForm Noncommercial + Commercial - + Angular 20+ @@ -27,14 +27,14 @@ --- -`streamResource()` is the Angular equivalent of LangGraph's React `useStream()` hook — a full-parity implementation built on Angular Signals and the Angular Resource API. It gives enterprise Angular teams the same production-grade streaming primitives available to React developers on LangChain, without compromises or workarounds. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get reactive, signal-driven access to streaming state, messages, tool calls, interrupts, and thread history. +`agent()` is the Angular equivalent of LangGraph's React `useStream()` hook — a full-parity implementation built on Angular Signals and the Angular Resource API. It gives enterprise Angular teams the same production-grade streaming primitives available to React developers on LangChain, without compromises or workarounds. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get reactive, signal-driven access to streaming state, messages, tool calls, interrupts, and thread history. --- ## Install ```bash -npm install @cacheplane/stream-resource +npm install @cacheplane/angular ``` **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` @@ -45,7 +45,7 @@ npm install @cacheplane/stream-resource ```typescript import { Component } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -65,7 +65,7 @@ import type { BaseMessage } from '@langchain/core/messages'; `, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ apiUrl: 'https://your-langgraph-platform.com', assistantId: 'my-agent', messagesKey: 'messages', @@ -83,7 +83,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp ## Feature Comparison -| Feature | `streamResource()` (Angular) | `useStream()` (React) | +| Feature | `agent()` (Angular) | `useStream()` (React) | |---|---|---| | Streaming state as reactive primitives | Angular Signals | React state | | Messages signal | `messages()` | `messages` | @@ -99,7 +99,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp | Submit | `submit(values, opts?)` | `submit(values, opts?)` | | Stop | `stop()` | `stop()` | | Reload last submission | `reload()` | — | -| Custom transport (for testing) | `MockStreamTransport` | mock fetch | +| Custom transport (for testing) | `MockAgentTransport` | mock fetch | | Angular `ResourceRef` compatibility | Full duck-type parity | N/A | | Angular 20+ Signals API | Native | N/A | | SSR / Server Components | Client-side only | React Server Components (React) | @@ -111,12 +111,12 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp

Angular Stream Resource architecture: Angular Component → streamResource() → StreamManager Bridge → LangGraph Platform, with signals returned reactively

-`streamResource()` creates 12 `BehaviorSubject`s at injection-context time — once, at component construction. The `StreamManager` bridge (the only file that touches `@langchain/langgraph-sdk` internals) pushes stream events into those subjects. `toSignal()` converts each subject to an Angular Signal, also at construction time. Dynamic actions (`submit`, `stop`, `switchThread`) push into the existing subjects — no new subjects are ever created after construction. This architecture is required because `toSignal()` must be called in an injection context and cannot be called again later. +`agent()` creates 12 `BehaviorSubject`s at injection-context time — once, at component construction. The `StreamManager` bridge (the only file that touches `@langchain/langgraph-sdk` internals) pushes stream events into those subjects. `toSignal()` converts each subject to an Angular Signal, also at construction time. Dynamic actions (`submit`, `stop`, `switchThread`) push into the existing subjects — no new subjects are ever created after construction. This architecture is required because `toSignal()` must be called in an injection context and cannot be called again later. --- @@ -137,7 +137,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp - [Getting Started](https://stream-resource.dev/docs/getting-started) - [API Reference](https://stream-resource.dev/api-reference) -- [Testing with MockStreamTransport](https://stream-resource.dev/docs/testing) +- [Testing with MockAgentTransport](https://stream-resource.dev/docs/testing) - [Human-in-the-Loop / Interrupts](https://stream-resource.dev/docs/interrupts) - [Subagent Streaming](https://stream-resource.dev/docs/subagents) @@ -145,9 +145,9 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp ## License -`@cacheplane/stream-resource` is source-available software dual-licensed: +`@cacheplane/angular` 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 Stream Resource Commercial License** — required for any for-profit or revenue-generating use. See [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL) and [`COMMERCIAL.md`](./COMMERCIAL.md). +- **Angular Agent Framework Commercial License** — required for any for-profit or revenue-generating use. See [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL) and [`COMMERCIAL.md`](./COMMERCIAL.md). This is **not** an open-source license. Commercial use — including use in a for-profit product, service, or organization — requires a paid commercial license. See [pricing](https://stream-resource.dev/pricing). diff --git a/apps/demo/src/app/chat-demo/chat-demo.component.ts b/apps/demo/src/app/chat-demo/chat-demo.component.ts index 227596ab9..996de2734 100644 --- a/apps/demo/src/app/chat-demo/chat-demo.component.ts +++ b/apps/demo/src/app/chat-demo/chat-demo.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit, Injector, runInInjectionContext } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -34,14 +34,14 @@ export class ChatDemoComponent implements OnInit { @Input() apiUrl = 'http://localhost:2024'; @Input() assistantId = 'chat_agent'; - chat: ReturnType> | null = null; + chat: ReturnType> | null = null; constructor(private injector: Injector) {} ngOnInit() { // @Input() values are available in ngOnInit, so use runInInjectionContext runInInjectionContext(this.injector, () => { - this.chat = streamResource<{ messages: BaseMessage[] }>({ + this.chat = agent<{ messages: BaseMessage[] }>({ apiUrl: this.apiUrl, assistantId: this.assistantId, }); diff --git a/apps/website/content/docs-v2/api/stream-resource.mdx b/apps/website/content/docs-v2/api/agent.mdx similarity index 79% rename from apps/website/content/docs-v2/api/stream-resource.mdx rename to apps/website/content/docs-v2/api/agent.mdx index fb4135410..7475f7595 100644 --- a/apps/website/content/docs-v2/api/stream-resource.mdx +++ b/apps/website/content/docs-v2/api/agent.mdx @@ -1,14 +1,14 @@ -# streamResource() +# agent() -`streamResource` is the core primitive of the library. It creates a reactive resource that opens a server-sent event stream, tracks loading and error states, and exposes the latest emitted value — all within Angular's signal-based reactivity model. +`agent` is the core primitive of the library. It creates a reactive resource that opens a server-sent event stream, tracks loading and error states, and exposes the latest emitted value — all within Angular's signal-based reactivity model. 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 { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; // Inside a component or service with injection context -const repo = streamResource({ +const repo = agent({ url: () => `/api/repos/${this.repoId()}`, transport: inject(FetchStreamTransport), }); @@ -31,7 +31,7 @@ const repo = streamResource({ ## When to use -Use `streamResource` whenever your UI needs to react to a live data stream from the server: +Use `agent` whenever your UI needs to react to a live data stream from the server: - **AI / LLM responses** — stream tokens into a chat bubble as they arrive - **Live feeds** — stock tickers, activity logs, or progress updates @@ -40,7 +40,7 @@ Use `streamResource` whenever your UI needs to react to a live data stream from For plain HTTP requests that return a single value and complete, Angular's built-in `resource()` or `httpResource()` is a better fit. - `streamResource` must be called during construction, inside an injection + `agent` must be called during construction, inside an injection context (e.g. a component constructor, field initializer, or a function passed to `runInInjectionContext`). Calling it outside an injection context will throw. @@ -68,7 +68,7 @@ For plain HTTP requests that return a single value and complete, Angular's built icon="bolt" href="/docs-v2/concepts/angular-signals" > - Understand how stream-resource integrates with Angular's reactivity model. + Understand how angular integrates with Angular's reactivity model. diff --git a/apps/website/content/docs-v2/api/api-docs.json b/apps/website/content/docs-v2/api/api-docs.json index 1f96975a4..3297086c2 100644 --- a/apps/website/content/docs-v2/api/api-docs.json +++ b/apps/website/content/docs-v2/api/api-docs.json @@ -87,7 +87,7 @@ ] }, { - "name": "MockStreamTransport", + "name": "MockAgentTransport", "kind": "class", "description": "Test transport for deterministic agent testing without a real LangGraph server.\n\nScript event batches upfront, then emit them manually or step through them\nin your test specs. Supports error injection and close control.", "params": [ @@ -99,7 +99,7 @@ } ], "examples": [ - "```typescript\nconst transport = new MockStreamTransport([\n [{ type: 'values', data: { messages: [aiMsg('Hello')] } }],\n [{ type: 'values', data: { status: 'done' } }],\n]);\n```" + "```typescript\nconst transport = new MockAgentTransport([\n [{ type: 'values', data: { messages: [aiMsg('Hello')] } }],\n [{ type: 'values', data: { status: 'done' } }],\n]);\n```" ], "properties": [], "methods": [ @@ -233,9 +233,9 @@ "examples": [] }, { - "name": "StreamResourceConfig", + "name": "AgentConfig", "kind": "interface", - "description": "Global configuration for streamResource instances.\nProperties set here serve as defaults that can be overridden per-call.", + "description": "Global configuration for agent instances.\nProperties set here serve as defaults that can be overridden per-call.", "properties": [ { "name": "apiUrl", @@ -245,7 +245,7 @@ }, { "name": "transport", - "type": "StreamResourceTransport", + "type": "AgentTransport", "description": "Custom transport implementation. Defaults to FetchStreamTransport.", "optional": true } @@ -253,9 +253,9 @@ "examples": [] }, { - "name": "StreamResourceOptions", + "name": "AgentOptions", "kind": "interface", - "description": "Options for creating a streaming resource via streamResource.", + "description": "Options for creating a streaming resource via agent.", "properties": [ { "name": "apiUrl", @@ -319,7 +319,7 @@ }, { "name": "transport", - "type": "StreamResourceTransport", + "type": "AgentTransport", "description": "Custom transport. Defaults to FetchStreamTransport.", "optional": true } @@ -327,9 +327,9 @@ "examples": [] }, { - "name": "StreamResourceRef", + "name": "AgentRef", "kind": "interface", - "description": "Reactive reference returned by streamResource. All properties are Angular Signals.", + "description": "Reactive reference returned by agent. All properties are Angular Signals.", "properties": [ { "name": "activeSubagents", @@ -473,7 +473,7 @@ "examples": [] }, { - "name": "StreamResourceTransport", + "name": "AgentTransport", "kind": "interface", "description": "Transport interface for connecting to a LangGraph agent.", "properties": [ @@ -718,14 +718,14 @@ "examples": [] }, { - "name": "provideStreamResource", + "name": "provideAgent", "kind": "function", - "description": "Angular provider factory that registers global defaults for all\nstreamResource instances in the application.\n\nAdd to your `app.config.ts` or module providers array.", - "signature": "provideStreamResource(config: StreamResourceConfig): Provider", + "description": "Angular provider factory that registers global defaults for all\nagent instances in the application.\n\nAdd to your `app.config.ts` or module providers array.", + "signature": "provideAgent(config: AgentConfig): Provider", "params": [ { "name": "config", - "type": "StreamResourceConfig", + "type": "AgentConfig", "description": "Global configuration merged with per-call options", "optional": false } @@ -735,28 +735,28 @@ "description": "" }, "examples": [ - "```typescript\n// app.config.ts\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideStreamResource({ apiUrl: 'http://localhost:2024' }),\n ],\n};\n```" + "```typescript\n// app.config.ts\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideAgent({ apiUrl: 'http://localhost:2024' }),\n ],\n};\n```" ] }, { - "name": "streamResource", + "name": "agent", "kind": "function", "description": "Creates a streaming resource connected to a LangGraph agent.\n\nMust be called within an Angular injection context (component constructor,\nfield initializer, or `runInInjectionContext`). Returns a ref object whose\nproperties are Angular Signals that update in real-time as the agent streams.", - "signature": "streamResource(options: StreamResourceOptions>): StreamResourceRef>", + "signature": "agent(options: AgentOptions>): AgentRef>", "params": [ { "name": "options", - "type": "StreamResourceOptions>", + "type": "AgentOptions>", "description": "Configuration for the streaming resource", "optional": false } ], "returns": { - "type": "StreamResourceRef>", + "type": "AgentRef>", "description": "" }, "examples": [ - "```typescript\n// In a component field initializer\nconst chat = streamResource<{ messages: BaseMessage[] }>({\n assistantId: 'chat_agent',\n apiUrl: 'http://localhost:2024',\n threadId: signal(this.savedThreadId),\n onThreadId: (id) => localStorage.setItem('threadId', id),\n});\n\n// Access signals in template\n// chat.messages(), chat.status(), chat.error()\n```" + "```typescript\n// In a component field initializer\nconst chat = agent<{ messages: BaseMessage[] }>({\n assistantId: 'chat_agent',\n apiUrl: 'http://localhost:2024',\n threadId: signal(this.savedThreadId),\n onThreadId: (id) => localStorage.setItem('threadId', id),\n});\n\n// Access signals in template\n// chat.messages(), chat.status(), chat.error()\n```" ] } ] \ No newline at end of file diff --git a/apps/website/content/docs-v2/api/fetch-stream-transport.mdx b/apps/website/content/docs-v2/api/fetch-stream-transport.mdx index 790698e84..0cdcb409a 100644 --- a/apps/website/content/docs-v2/api/fetch-stream-transport.mdx +++ b/apps/website/content/docs-v2/api/fetch-stream-transport.mdx @@ -1,20 +1,20 @@ # FetchStreamTransport -`FetchStreamTransport` is the production-ready transport that opens a real server-sent event connection using the browser's `fetch` API and reads a `ReadableStream` response body. It is the default transport you register with `provideStreamResource` in production builds. +`FetchStreamTransport` is the production-ready transport that opens a real server-sent event connection using the browser's `fetch` API and reads a `ReadableStream` response body. It is the default transport you register with `provideAgent` in production builds. ## When you interact with it directly -In most apps you will never import or inject `FetchStreamTransport` by name — you register it once in `provideStreamResource` and forget about it. The two cases where you reach for it explicitly are: +In most apps you will never import or inject `FetchStreamTransport` by name — you register it once in `provideAgent` and forget about it. The two cases where you reach for it explicitly are: 1. **Per-resource override** — you want one resource to use a different transport than the global default while everything else stays on `FetchStreamTransport`. 2. **Outside the DI tree** — you are constructing a resource in a context where global providers are not available and you need to supply the transport manually. ```ts import { inject } from '@angular/core'; -import { streamResource, FetchStreamTransport } from '@cacheplane/stream-resource'; +import { agent, FetchStreamTransport } from '@cacheplane/angular'; // Override transport for a single resource -const events = streamResource({ +const events = agent({ url: () => '/api/events', transport: inject(FetchStreamTransport), }); @@ -54,7 +54,7 @@ The transport handles: Server configuration for SSE: headers, timeouts, and edge runtime considerations. diff --git a/apps/website/content/docs-v2/api/mock-stream-transport.mdx b/apps/website/content/docs-v2/api/mock-stream-transport.mdx index 31fbb93fd..1885a0d45 100644 --- a/apps/website/content/docs-v2/api/mock-stream-transport.mdx +++ b/apps/website/content/docs-v2/api/mock-stream-transport.mdx @@ -1,6 +1,6 @@ -# MockStreamTransport +# MockAgentTransport -`MockStreamTransport` is a test-friendly transport that replaces real network calls with an in-memory event emitter. Use it in unit and component tests to push values on demand and assert against your component's reactive state without a running server. +`MockAgentTransport` is a test-friendly transport that replaces real network calls with an in-memory event emitter. Use it in unit and component tests to push values on demand and assert against your component's reactive state without a running server. ## Complete test example @@ -10,27 +10,27 @@ The pattern below covers the full lifecycle: configure the transport in `TestBed import { Component, inject } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { - provideStreamResource, - MockStreamTransport, - streamResource, -} from '@cacheplane/stream-resource'; + provideAgent, + MockAgentTransport, + agent, +} from '@cacheplane/angular'; @Component({ template: '' }) class RepoComponent { - readonly repo = streamResource<{ name: string }>({ + readonly repo = agent<{ name: string }>({ url: () => '/api/repos/42', }); } describe('RepoComponent', () => { - let transport: MockStreamTransport; + let transport: MockAgentTransport; beforeEach(() => { TestBed.configureTestingModule({ imports: [RepoComponent], - providers: [provideStreamResource({ transport: MockStreamTransport })], + providers: [provideAgent({ transport: MockAgentTransport })], }); - transport = TestBed.inject(MockStreamTransport); + transport = TestBed.inject(MockAgentTransport); }); it('reflects the streamed value', () => { @@ -58,7 +58,7 @@ describe('RepoComponent', () => { }); ``` -## MockStreamTransport API +## MockAgentTransport API | Method | Description | |--------|-------------| @@ -67,7 +67,7 @@ describe('RepoComponent', () => { | `complete(url)` | Closes the stream cleanly, as if the server sent the final event. | - Because `MockStreamTransport` is synchronous by default, you can emit values + Because `MockAgentTransport` is synchronous by default, you can emit values and assert state changes in the same test tick — no `fakeAsync` or `tick` required. @@ -87,12 +87,12 @@ describe('RepoComponent', () => { icon="globe" href="/docs-v2/api/fetch-stream-transport" > - The production transport that MockStreamTransport replaces in tests. + The production transport that MockAgentTransport replaces in tests. Full reference for the primitive you are testing against. diff --git a/apps/website/content/docs-v2/api/provide-stream-resource.mdx b/apps/website/content/docs-v2/api/provide-agent.mdx similarity index 61% rename from apps/website/content/docs-v2/api/provide-stream-resource.mdx rename to apps/website/content/docs-v2/api/provide-agent.mdx index 3375f0b2f..4ef91f911 100644 --- a/apps/website/content/docs-v2/api/provide-stream-resource.mdx +++ b/apps/website/content/docs-v2/api/provide-agent.mdx @@ -1,20 +1,20 @@ -# provideStreamResource() +# provideAgent() -`provideStreamResource` is the provider factory that registers `stream-resource` in Angular's dependency injection system. Call it once inside `bootstrapApplication` (or an `ApplicationConfig`) to configure the transport and any global defaults used by every `streamResource` in your app. +`provideAgent` is the provider factory that registers `angular` in Angular's dependency injection system. Call it once inside `bootstrapApplication` (or an `ApplicationConfig`) to configure the transport and any global defaults used by every `agent` in your app. -This is the single configuration point for the entire library. Rather than configuring each resource individually, you declare your transport here and every `streamResource` call throughout the app inherits it automatically. +This is the single configuration point for the entire library. Rather than configuring each resource individually, you declare your transport here and every `agent` call throughout the app inherits it automatically. ```ts import { bootstrapApplication } from '@angular/platform-browser'; import { - provideStreamResource, + provideAgent, FetchStreamTransport, -} from '@cacheplane/stream-resource'; +} from '@cacheplane/angular'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, { providers: [ - provideStreamResource({ + provideAgent({ transport: FetchStreamTransport, }), ], @@ -29,18 +29,18 @@ bootstrapApplication(AppComponent, { ## Swapping transports by environment -Because `provideStreamResource` accepts a class token, you can vary the transport based on your environment without touching any component code: +Because `provideAgent` accepts a class token, you can vary the transport based on your environment without touching any component code: ```ts // main.ts — production -provideStreamResource({ transport: FetchStreamTransport }) +provideAgent({ transport: FetchStreamTransport }) // main.spec.ts / TestBed — tests -provideStreamResource({ transport: MockStreamTransport }) +provideAgent({ transport: MockAgentTransport }) ``` - Swap `FetchStreamTransport` for `MockStreamTransport` (or any custom class + Swap `FetchStreamTransport` for `MockAgentTransport` (or any custom class implementing the `StreamTransport` interface) to change the transport for all resources at once — useful for testing or SSR. @@ -63,9 +63,9 @@ provideStreamResource({ transport: MockStreamTransport }) Configure transports for production, SSR, and edge runtimes. Full reference for the core primitive you configure here. diff --git a/apps/website/content/docs-v2/concepts/agent-architecture.mdx b/apps/website/content/docs-v2/concepts/agent-architecture.mdx index 2571643ed..21c8dea42 100644 --- a/apps/website/content/docs-v2/concepts/agent-architecture.mdx +++ b/apps/website/content/docs-v2/concepts/agent-architecture.mdx @@ -1,14 +1,14 @@ # Agent Architecture -How AI agents work — the planning, execution, and tool-calling lifecycle that streamResource() 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/stream-resource`. +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`. -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, streamResource() handles the reactivity. +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. ## The Agent Loop -Every agent follows a five-phase cycle. Understanding this cycle is critical because each phase maps to a specific streamResource() signal in your Angular app. +Every agent follows a five-phase cycle. Understanding this cycle is critical because each phase maps to a specific agent() signal in your Angular app. @@ -52,7 +52,7 @@ tool_node = ToolNode(tools) -After tools finish (or if no tools were needed), the agent streams its final response token by token. streamResource() updates the `messages()` signal in real time so your Angular template re-renders incrementally. +After tools finish (or if no tools were needed), the agent streams its final response token by token. agent() updates the `messages()` signal in real time so your Angular template re-renders incrementally. ```typescript // Angular side — messages update as tokens arrive @@ -149,7 +149,7 @@ graph = builder.compile() ```typescript import { ChangeDetectionStrategy, Component, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; interface AgentState { messages: BaseMessage[]; @@ -173,7 +173,7 @@ interface AgentState { `, }) export class ReactAgentComponent { - agent = streamResource({ + agent = agent({ assistantId: 'react_agent', }); @@ -235,7 +235,7 @@ The LLM reads the docstring to decide when to call a tool. A vague docstring lik ### How Tools Surface in Angular -When the agent calls a tool, streamResource() exposes the execution lifecycle through two signals: +When the agent calls a tool, agent() exposes the execution lifecycle through two signals: @@ -244,7 +244,7 @@ When the agent calls a tool, streamResource() exposes the execution lifecycle th // toolProgress() — tools currently executing // Updates in real time as tools start and complete -const agent = streamResource({ +const agent = agent({ assistantId: 'react_agent', }); @@ -325,7 +325,7 @@ The `should_continue` conditional edge detects `tool_calls` and routes to the `t LangGraph Platform streams the tool call and result as SSE events to the Angular client. - + `toolProgress()` updates during execution. `toolCalls()` updates when the tool completes. Both trigger OnPush change detection. @@ -401,7 +401,7 @@ graph = builder.compile() ```typescript import { ChangeDetectionStrategy, Component, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; interface OrchestratorState { messages: BaseMessage[]; @@ -437,7 +437,7 @@ interface OrchestratorState { `, }) export class MultiAgentComponent { - orchestrator = streamResource({ + orchestrator = agent({ assistantId: 'orchestrator', subagentToolNames: ['researcher', 'analyst', 'writer'], }); @@ -464,7 +464,7 @@ export class MultiAgentComponent { -The `subagentToolNames` option tells streamResource() which graph nodes are subagents. Without it, subagent execution looks like regular tool calls. With it, `activeSubagents()` and `subagents()` provide dedicated tracking with isolated message histories. +The `subagentToolNames` option tells agent() which graph nodes are subagents. Without it, subagent execution looks like regular tool calls. With it, `activeSubagents()` and `subagents()` provide dedicated tracking with isolated message histories. ## Error Handling and Recovery @@ -493,7 +493,7 @@ When `handle_tool_error=True` is set, LangGraph catches `ToolException` and feed ### How Errors Surface in Angular ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'react_agent', }); @@ -535,7 +535,7 @@ LangGraph defaults to 25 recursion steps. If your agent loops between `model` an ## Checkpointing and Debugging -Every time a node completes, LangGraph saves a checkpoint — a full snapshot of the agent's state at that moment. streamResource() exposes this checkpoint timeline to Angular, giving you time-travel debugging for free. +Every time a node completes, LangGraph saves a checkpoint — a full snapshot of the agent's state at that moment. agent() exposes this checkpoint timeline to Angular, giving you time-travel debugging for free. ### How Checkpoints Work @@ -554,7 +554,7 @@ graph = builder.compile(checkpointer=checkpointer) ### Exposing Checkpoints in Angular ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'react_agent', threadId: signal('thread_abc123'), }); @@ -696,6 +696,6 @@ Begin with a single agent and tools. Add human-in-the-loop when you need approva Debug agents by stepping through checkpoint history and branching. - How Signals power the reactive model behind streamResource(). + How Signals power the reactive model behind agent(). diff --git a/apps/website/content/docs-v2/concepts/angular-signals.mdx b/apps/website/content/docs-v2/concepts/angular-signals.mdx index d476ee891..440c6aebb 100644 --- a/apps/website/content/docs-v2/concepts/angular-signals.mdx +++ b/apps/website/content/docs-v2/concepts/angular-signals.mdx @@ -1,6 +1,6 @@ # Angular Signals -Angular Signals are the reactive primitive that powers streamResource(). If you're coming from a Python AI/agent background and wondering how Angular handles real-time streaming data, this page is your guide. Every property on a StreamResourceRef is a Signal, which means your templates update automatically as tokens arrive — no manual subscriptions, no async pipes, no RxJS boilerplate. +Angular Signals are the reactive primitive that powers agent(). If you're coming from a Python AI/agent background and wondering how Angular handles real-time streaming data, this page is your guide. Every property on a AgentRef is a Signal, which means your templates update automatically as tokens arrive — no manual subscriptions, no async pipes, no RxJS boilerplate. Think of Signals like a Python property with built-in change notification. When the value changes, every consumer — templates, computed values, effects — re-evaluates automatically. If you've used Pydantic models with validators that react to field changes, Signals are the Angular equivalent but deeply integrated into the rendering engine. @@ -30,15 +30,15 @@ console.log(doubled()); // 4 The key insight: Angular knows which Signals a template reads. When those Signals change, Angular re-renders only the affected parts of the DOM. No diffing the entire tree, no zone.js overhead. -## How streamResource Uses Signals Internally +## How agent Uses Signals Internally -Under the hood, streamResource() receives Server-Sent Events (SSE) over HTTP and feeds them into RxJS BehaviorSubjects. It then converts those BehaviorSubjects into Angular Signals using `toSignal()`. This is the bridge between the async streaming world and Angular's synchronous reactivity model. +Under the hood, agent() receives Server-Sent Events (SSE) over HTTP and feeds them into RxJS BehaviorSubjects. It then converts those BehaviorSubjects into Angular Signals using `toSignal()`. This is the bridge between the async streaming world and Angular's synchronous reactivity model. ```typescript -// Simplified view of what streamResource does internally: +// Simplified view of what agent does internally: // 1. SSE events arrive as an observable stream const messages$ = new BehaviorSubject([]); @@ -60,11 +60,11 @@ const status = toSignal(status$, { initialValue: 'idle' }); ```typescript -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; // You never touch BehaviorSubjects or toSignal() yourself. -// streamResource() hands you clean Signals: -const chat = streamResource({ +// agent() hands you clean Signals: +const chat = agent({ assistantId: 'chat_agent', }); @@ -84,14 +84,14 @@ The BehaviorSubject-to-Signal conversion means you get the best of both worlds: ## The Streaming Lifecycle as Signals -Every streamResource() instance moves through a lifecycle: **idle**, **loading**, tokens arriving, then **resolved** (or **error**). The `status()` Signal reflects each transition in real time. +Every agent() instance moves through a lifecycle: **idle**, **loading**, tokens arriving, then **resolved** (or **error**). The `status()` Signal reflects each transition in real time. The resource has been created but no request has been submitted yet. All Signals hold their initial values. ```typescript -const chat = streamResource({ +const chat = agent({ assistantId: 'chat_agent', }); @@ -150,13 +150,13 @@ console.log(chat.isLoading()); // false ## Composing Derived State with computed() -`computed()` lets you derive new Signals from streamResource Signals. These derived Signals update automatically whenever their dependencies change — during streaming, that means every time a new token arrives. +`computed()` lets you derive new Signals from agent Signals. These derived Signals update automatically whenever their dependencies change — during streaming, that means every time a new token arrives. ```typescript import { computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; -const chat = streamResource({ +const chat = agent({ assistantId: 'chat_agent', }); @@ -216,7 +216,7 @@ import { effect } from '@angular/core'; effect(() => { const err = chat.error(); if (err) { - console.error('[StreamResource] Agent error:', err); + console.error('[Agent] Agent error:', err); this.analytics.track('agent_error', { error: err }); } }); @@ -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 { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -331,7 +331,7 @@ import { streamResource } from '@cacheplane/stream-resource'; export class ChatComponent { @ViewChild('chatContainer') chatContainer!: ElementRef; - chat = streamResource({ + chat = agent({ assistantId: 'chat_agent', }); @@ -377,7 +377,7 @@ export class ChatComponent { ## OnPush Change Detection -Every component using streamResource() should use `ChangeDetectionStrategy.OnPush`. Here's why it works and why it's efficient. +Every component using agent() should use `ChangeDetectionStrategy.OnPush`. Here's why it works and why it's efficient. With the default change detection strategy, Angular checks every component in the tree on every browser event — clicks, timers, HTTP responses. For a streaming agent emitting dozens of tokens per second, that means hundreds of unnecessary checks across your entire app. @@ -387,11 +387,11 @@ With OnPush, Angular only checks a component when: 2. An event fires inside the component's template 3. A **Signal** that the template reads changes -Since streamResource() exposes Signals, condition 3 handles everything. When a new token arrives and `messages()` updates, Angular marks only the components reading that Signal for check — not the entire tree. +Since agent() exposes Signals, condition 3 handles everything. When a new token arrives and `messages()` updates, Angular marks only the components reading that Signal for check — not the entire tree. ```typescript @Component({ - // Always use OnPush with streamResource + // Always use OnPush with agent changeDetection: ChangeDetectionStrategy.OnPush, template: `

{{ chat.messages().length }} messages

@@ -401,7 +401,7 @@ Since streamResource() exposes Signals, condition 3 handles everything. When a n `, }) export class ChatComponent { - chat = streamResource({ assistantId: 'chat_agent' }); + chat = agent({ assistantId: 'chat_agent' }); } ``` @@ -411,7 +411,7 @@ With older Observable-based patterns, you had to call `ChangeDetectorRef.markFor ## Python Agent to Angular Signals -The real power of streamResource() is how it pairs a Python LangGraph agent with Angular Signals. The agent defines the logic; Signals surface the results in real time. +The real power of agent() is how it pairs a Python LangGraph agent with Angular Signals. The agent defines the logic; Signals surface the results in real time. @@ -457,7 +457,7 @@ graph = builder.compile() ```typescript import { ChangeDetectionStrategy, Component, computed, effect } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -488,7 +488,7 @@ import { streamResource } from '@cacheplane/stream-resource'; `, }) export class ChatComponent { - chat = streamResource({ + chat = agent({ assistantId: 'chat_agent', }); @@ -532,7 +532,7 @@ For a typical chat UI receiving 30-50 tokens per second: - **Observable + async pipe**: Works correctly but creates and destroys subscriptions each time an `@if` or `@for` block re-evaluates, adding GC pressure during rapid streaming. -Signals use referential equality (`===`) by default. streamResource() creates new array references for `messages()` only when the array actually changes (a new token arrives). Between updates, reading `messages()` returns the same reference and skips downstream recomputation. For custom equality, pass an `equal` function when creating a `computed()`. +Signals use referential equality (`===`) by default. agent() creates new array references for `messages()` only when the array actually changes (a new token arrives). Between updates, reading `messages()` returns the same reference and skips downstream recomputation. For custom equality, pass an `equal` function when creating a `computed()`. ## What's Next @@ -547,8 +547,8 @@ Signals use referential equality (`===`) by default. streamResource() creates ne Understand the Python agent patterns that produce the events Signals consume. - - Full reference for every Signal, method, and option on StreamResourceRef. + + Full reference for every Signal, method, and option on AgentRef. Build human-in-the-loop approval flows that pause and resume the agent. diff --git a/apps/website/content/docs-v2/concepts/langgraph-basics.mdx b/apps/website/content/docs-v2/concepts/langgraph-basics.mdx index 7e9e10536..3c0ba4b34 100644 --- a/apps/website/content/docs-v2/concepts/langgraph-basics.mdx +++ b/apps/website/content/docs-v2/concepts/langgraph-basics.mdx @@ -1,6 +1,6 @@ # LangGraph Basics -LangGraph is a framework for building stateful AI agents as directed graphs. If you're an Angular developer building AI-powered applications, this page teaches you how LangGraph agents work and why streamResource() is the natural bridge between your frontend and your agent backend. +LangGraph is a framework for building stateful AI agents as directed graphs. If you're an Angular developer building AI-powered applications, this page teaches you how LangGraph agents work and why agent() is the natural bridge between your frontend and your agent backend. Graphs give you explicit control over agent behavior. Instead of a black-box prompt-and-pray approach, you define exactly how your agent reasons, when it calls tools, and where it pauses for human input. Every step is visible, testable, and debuggable. @@ -65,7 +65,7 @@ class State(TypedDict): results: dict # Tool results ``` -This state is exactly what streamResource() exposes to your Angular app through Signals. +This state is exactly what agent() exposes to your Angular app through Signals. ## Building Your First Agent @@ -112,7 +112,7 @@ graph = builder.compile() ```typescript // This is all you need on the Angular side -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -125,7 +125,7 @@ const chat = streamResource<{ messages: BaseMessage[] }>({ ## Agent Patterns -The power of LangGraph is in the patterns you can build. Each pattern maps to specific streamResource() signals. +The power of LangGraph is in the patterns you can build. Each pattern maps to specific agent() signals. ### Pattern 1: ReAct Agent (Tool Calling) @@ -162,7 +162,7 @@ graph = builder.compile() **Angular connection:** Track tool execution in real-time: ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'react_agent', }); @@ -195,7 +195,7 @@ def execute_action(state: State) -> dict: **Angular connection:** The interrupt surfaces automatically: ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'approval_agent', }); @@ -229,7 +229,7 @@ builder.add_conditional_edges("supervisor", lambda s: s["next_agent"]) **Angular connection:** Track each sub-agent independently: ```typescript -const orchestrator = streamResource({ +const orchestrator = agent({ assistantId: 'orchestrator', subagentToolNames: ['researcher', 'analyst', 'writer'], }); @@ -256,21 +256,21 @@ result = graph.invoke( ) ``` -**Angular connection:** Thread persistence is built into streamResource: +**Angular connection:** Thread persistence is built into agent: ```typescript -const chat = streamResource({ +const chat = agent({ assistantId: 'chat_agent', threadId: signal(localStorage.getItem('threadId')), onThreadId: (id) => localStorage.setItem('threadId', id), }); // User returns tomorrow — same thread, full history restored -// No code needed — streamResource handles it +// No code needed — agent handles it ``` -## How streamResource() Bridges the Gap +## How agent() Bridges the Gap -Here's why streamResource() is the natural Angular companion for LangGraph: +Here's why agent() is the natural Angular companion for LangGraph: @@ -279,7 +279,7 @@ Here's why streamResource() is the natural Angular companion for LangGraph: Calls `submit({ messages: [userMsg] })` to send user input - + Passes input to the transport layer @@ -291,7 +291,7 @@ Executes graph nodes, calls tools, streams SSE events back Parses SSE chunks into BehaviorSubjects - + Converts BehaviorSubjects to Angular Signals via `toSignal()` @@ -332,7 +332,7 @@ agent.toolCalls() // Signal — tool results -You don't configure SSE, parse events, manage WebSocket connections, or handle reconnection. streamResource() does all of that. You call `submit()` and read Signals — that's the entire API surface for your Angular code. +You don't configure SSE, parse events, manage WebSocket connections, or handle reconnection. agent() does all of that. You call `submit()` and read Signals — that's the entire API surface for your Angular code. ## Graph API vs Functional API @@ -357,7 +357,7 @@ async def agent(messages): return response ``` -Both APIs produce the same output and work identically with streamResource(). Choose the Graph API when you need conditional routing, subgraphs, or interrupts. Choose the Functional API for simple, linear workflows. +Both APIs produce the same output and work identically with agent(). Choose the Graph API when you need conditional routing, subgraphs, or interrupts. Choose the Functional API for simple, linear workflows. ## What's Next @@ -378,6 +378,6 @@ Both APIs produce the same output and work identically with streamResource(). Ch Thread-based conversation persistence - How Signals power streamResource's reactive model + How Signals power agent's reactive model diff --git a/apps/website/content/docs-v2/concepts/state-management.mdx b/apps/website/content/docs-v2/concepts/state-management.mdx index 68397a602..0253be9b4 100644 --- a/apps/website/content/docs-v2/concepts/state-management.mdx +++ b/apps/website/content/docs-v2/concepts/state-management.mdx @@ -3,7 +3,7 @@ How agent state flows from LangGraph's server-side state machine into Angular Signals — and why the separation between server state and UI state makes your app simpler, not more complex. -LangGraph Platform owns the state. Angular owns the view. `streamResource()` is the read-only bridge between them. You never manually sync, serialize, or manage agent state in your Angular code. +LangGraph Platform owns the state. Angular owns the view. `agent()` is the read-only bridge between them. You never manually sync, serialize, or manage agent state in your Angular code. ## State Lives on the Server @@ -16,8 +16,8 @@ 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. - -`@cacheplane/stream-resource` forwards the input to `FetchStreamTransport`, which opens an HTTP POST and SSE connection to LangGraph Platform. + +`@cacheplane/angular` forwards the input to `FetchStreamTransport`, which opens an HTTP POST and SSE connection to LangGraph Platform. The agent runs its nodes — calling the LLM, invoking tools, checking conditions — and streams SSE events back with incremental state updates. @@ -25,7 +25,7 @@ The agent runs its nodes — calling the LLM, invoking tools, checking condition Incoming SSE chunks are parsed and pushed into BehaviorSubjects — one per signal type. - + BehaviorSubjects are converted to Angular Signals via `toSignal()`. Every update triggers Angular's change detection automatically. @@ -35,7 +35,7 @@ Components using `OnPush` re-render only when signal values change. No manual `d ## Python State Design -On the Python side, your agent's state is a `TypedDict`. The fields you define here are exactly what `streamResource()` exposes in TypeScript. Getting the Python state design right is the most important architectural decision in your agent. +On the Python side, your agent's state is a `TypedDict`. The fields you define here are exactly what `agent()` exposes in TypeScript. Getting the Python state design right is the most important architectural decision in your agent. ### The TypedDict Pattern @@ -128,7 +128,7 @@ Nodes return only the fields they change. LangGraph merges partial updates into ## TypeScript Interface Mapping -The TypeScript interface you pass to `streamResource()` is your contract with the Python state. Every Python state field maps to a TypeScript property. The types don't need to match exactly — they just need to be compatible with the JSON that LangGraph streams back. +The TypeScript interface you pass to `agent()` is your contract with the Python state. Every Python state field maps to a TypeScript property. The types don't need to match exactly — they just need to be compatible with the JSON that LangGraph streams back. @@ -165,7 +165,7 @@ interface ProjectState { error: string | null; } -const agent = streamResource({ +const agent = agent({ assistantId: 'project_agent', }); ``` @@ -212,7 +212,7 @@ The agent doesn't wait until it's finished to send state updates. It streams par LangGraph streams in `values` mode by default — each SSE event contains the full state snapshot after a node completes. In `messages` mode, you get individual message tokens as they're generated. ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'project_agent', // Default: values mode — full state after each node // streamMode: 'messages' — token-by-token for text fields @@ -245,7 +245,7 @@ Because every state update is a new signal value, your templates reflect the age ` }) export class ProjectComponent { - readonly agent = streamResource({ + readonly agent = agent({ assistantId: 'project_agent', }); } @@ -272,14 +272,14 @@ const score = computed(() => agent.value().analysis?.score ?? 0); ``` -`streamResource()` uses `toSignal()` internally with `requireSync: false`. Signals always have a value — even before the first stream update. You never need to handle `undefined` explicitly for the signal itself, though individual state fields may be `null` until the agent populates them. +`agent()` uses `toSignal()` internally with `requireSync: false`. Signals always have a value — even before the first stream update. You never need to handle `undefined` explicitly for the signal itself, though individual state fields may be `null` until the agent populates them. ## Thread State vs Application State There are two kinds of state in a LangGraph Angular app, and keeping them separate makes your code much easier to reason about. -**Thread state** is owned by LangGraph Platform. You read it through `streamResource()` signals. You never write to it directly — you only send new input via `.submit()`. +**Thread state** is owned by LangGraph Platform. You read it through `agent()` signals. You never write to it directly — you only send new input via `.submit()`. **Application state** is owned by your Angular component or service. It's UI-only: sidebar visibility, active tab, selected message, form input values. It has nothing to do with the agent. @@ -289,7 +289,7 @@ There are two kinds of state in a LangGraph Angular app, and keeping them separa }) export class ChatComponent { // --- Thread state (from agent, read-only) --- - readonly agent = streamResource({ + readonly agent = agent({ assistantId: 'chat_agent', }); @@ -337,14 +337,14 @@ Thread: "user_123_session" ### What This Means for Your Angular App -**Resumable threads** — If the user refreshes the page or closes the browser, the thread is still there. Pass the same `threadId` and `streamResource()` will restore the full conversation history automatically. +**Resumable threads** — If the user refreshes the page or closes the browser, the thread is still there. Pass the same `threadId` and `agent()` will restore the full conversation history automatically. **Time travel** — You can fork a thread at any checkpoint and replay it with different input. This powers the time-travel debugging guides. **Interrupt persistence** — When the agent raises an `Interrupt`, the checkpoint captures everything. The agent can be resumed hours or days later. ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'chat_agent', // Same threadId = restored conversation history @@ -419,7 +419,7 @@ def researcher_node(state: ResearchState) -> dict: ```typescript import { BaseMessage } from '@langchain/core/messages'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; interface ResearchState { messages: BaseMessage[]; @@ -437,7 +437,7 @@ interface ResearchState { } // In your component: -readonly agent = streamResource({ +readonly agent = agent({ assistantId: 'research_agent', }); ``` @@ -485,7 +485,7 @@ readonly agent = streamResource({ ` }) export class ResearchComponent { - readonly agent = streamResource({ + readonly agent = agent({ assistantId: 'research_agent', }); @@ -505,7 +505,7 @@ export class ResearchComponent { You rarely need to consume `agent.value()` raw in your template. Use `computed()` to derive clean, focused values: ```typescript -readonly agent = streamResource({ +readonly agent = agent({ assistantId: 'research_agent', }); @@ -521,7 +521,7 @@ readonly reportTitle = computed(() => this.agent.value().report?.title ?? ''); - How streamResource() uses Angular Signals for zero-subscription reactive rendering. + How agent() uses Angular Signals for zero-subscription reactive rendering. Configure stream modes — values, messages, events — for different use cases. diff --git a/apps/website/content/docs-v2/getting-started/installation.mdx b/apps/website/content/docs-v2/getting-started/installation.mdx index 83ff4fe0f..5c898edf6 100644 --- a/apps/website/content/docs-v2/getting-started/installation.mdx +++ b/apps/website/content/docs-v2/getting-started/installation.mdx @@ -1,12 +1,12 @@ # Installation -Detailed setup guide for streamResource() in your Angular application. +Detailed setup guide for agent() in your Angular application. ## Requirements -streamResource() uses Angular Signals and the modern injection context API. Angular 20 or later is required. +agent() uses Angular Signals and the modern injection context API. Angular 20 or later is required. Required for the build toolchain and package installation. @@ -19,24 +19,24 @@ A running LangGraph agent accessible via HTTP. Can be local (langgraph dev) or d ## Install the package ```bash -npm install @cacheplane/stream-resource +npm install @cacheplane/angular ``` This installs the library and its peer dependencies including `@langchain/langgraph-sdk`. ## Configure the provider -Add `provideStreamResource()` to your application configuration. This sets global defaults for all streamResource instances. +Add `provideAgent()` to your application configuration. This sets global defaults for all agent instances. ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: environment.langgraphUrl, }), ], @@ -44,7 +44,7 @@ export const appConfig: ApplicationConfig = { ``` -Any option passed to `streamResource()` directly overrides the global provider config. You can set a default `apiUrl` globally and override it for specific agents. +Any option passed to `agent()` directly overrides the global provider config. You can set a default `apiUrl` globally and override it for specific agents. ## Environment setup @@ -85,11 +85,11 @@ export const environment = { ## Verify installation -Create a minimal component to verify the setup works. `streamResource()` must be called in an injection context (a component field initializer or inside `inject()`). +Create a minimal component to verify the setup works. `agent()` must be called in an injection context (a component field initializer or inside `inject()`). ```typescript // In a component field initializer (injection context) -const test = streamResource({ assistantId: 'chat_agent' }); +const test = agent({ assistantId: 'chat_agent' }); console.log(test.status()); // 'idle' — setup is correct ``` @@ -97,13 +97,13 @@ console.log(test.status()); // 'idle' — setup is correct -**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 streamResource() relies on. +**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 agent() relies on. **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. **Connection refused** -- If you see `ERR_CONNECTION_REFUSED`, verify your LangGraph server is running and that the `apiUrl` matches the correct host and port. Run `langgraph dev` and confirm the server starts at the expected address (default `http://localhost:2024`). -**"NullInjectorError: No provider for StreamResourceConfig"** -- You forgot to add `provideStreamResource()` to your `appConfig` providers array. See the [Configure the provider](#configure-the-provider) section above. +**"NullInjectorError: No provider for AgentConfig"** -- You forgot to add `provideAgent()` to your `appConfig` providers array. See the [Configure the provider](#configure-the-provider) section above. @@ -114,12 +114,12 @@ console.log(test.status()); // 'idle' — setup is correct Build your first chat component in 5 minutes - Understand how Signals power streamResource + Understand how Signals power agent Graphs, nodes, edges, and state for Angular developers - - Complete streamResource() function reference + + Complete agent() function reference diff --git a/apps/website/content/docs-v2/getting-started/introduction.mdx b/apps/website/content/docs-v2/getting-started/introduction.mdx index e1c35bc0d..434cd2300 100644 --- a/apps/website/content/docs-v2/getting-started/introduction.mdx +++ b/apps/website/content/docs-v2/getting-started/introduction.mdx @@ -1,17 +1,17 @@ # Introduction -StreamResource is the Signal-native streaming library for Angular 20+ — built natively for LangGraph, without React translation layers. Build streaming AI applications with Angular Signals, connect to LangGraph agents, and ship production-ready frontends for your AI products. +Agent is the Signal-native streaming library for Angular 20+ — built natively for LangGraph, without React translation layers. Build streaming AI applications with Angular Signals, connect to LangGraph agents, and ship production-ready frontends for your AI products. -This guide walks you through the complete workflow: build a LangGraph agent in Python, run it locally, connect it to an Angular app with streamResource(), and deploy to production. +This guide walks you through the complete workflow: build a LangGraph agent in Python, run it locally, connect it to an Angular app with agent(), and deploy to production. -## What is streamResource()? +## What is agent()? -`streamResource()` is an Angular function that creates a reactive, streaming connection to a LangGraph agent. It returns an object whose properties are Angular Signals — meaning your templates update automatically as the agent streams responses, token by token. +`agent()` is an Angular function that creates a reactive, streaming connection to a LangGraph agent. It returns an object whose properties are Angular Signals — meaning your templates update automatically as the agent streams responses, token by token. ```typescript -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -120,13 +120,13 @@ Your agent is now running at `http://localhost:2024`. You can test it in LangGra ## Connect with Angular -Now connect your Angular app to the running agent using streamResource(). +Now connect your Angular app to the running agent using agent(). ```bash -npm install @cacheplane/stream-resource +npm install @cacheplane/angular ``` @@ -135,11 +135,11 @@ npm install @cacheplane/stream-resource ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'http://localhost:2024', }), ], @@ -155,7 +155,7 @@ export const appConfig: ApplicationConfig = { ```typescript // chat.component.ts import { Component, signal, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -167,7 +167,7 @@ export class ChatComponent { input = signal(''); // Create the streaming resource — this is the core API - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: signal(localStorage.getItem('threadId')), onThreadId: (id) => localStorage.setItem('threadId', id), @@ -242,7 +242,7 @@ Open `http://localhost:4200` and start chatting with your agent. Messages stream ## Key Concepts -Everything streamResource() gives you out of the box — click any to learn more: +Everything agent() gives you out of the box — click any to learn more: @@ -284,7 +284,7 @@ export const environment = { }; // app.config.ts -provideStreamResource({ +provideAgent({ apiUrl: environment.langgraphUrl, }) ``` @@ -292,7 +292,7 @@ provideStreamResource({ -Deploy your Angular frontend to any hosting platform — Vercel, Netlify, AWS, or your own infrastructure. Since streamResource() is a stateless client, your frontend has no server-side state requirements. +Deploy your Angular frontend to any hosting platform — Vercel, Netlify, AWS, or your own infrastructure. Since agent() is a stateless client, your frontend has no server-side state requirements. ```bash ng build --configuration production @@ -322,15 +322,15 @@ Your Angular app is a stateless client. All agent state — threads, checkpoints Human-in-the-loop approval and confirmation flows - Deterministic testing with MockStreamTransport + Deterministic testing with MockAgentTransport - Deep dive into how Signals power streamResource + Deep dive into how Signals power agent Graphs, nodes, edges, and state for Angular developers - - Complete streamResource() function reference + + Complete agent() function reference diff --git a/apps/website/content/docs-v2/getting-started/quickstart.mdx b/apps/website/content/docs-v2/getting-started/quickstart.mdx index 90cce9b3b..10d2616bc 100644 --- a/apps/website/content/docs-v2/getting-started/quickstart.mdx +++ b/apps/website/content/docs-v2/getting-started/quickstart.mdx @@ -1,6 +1,6 @@ # Quick Start -Build a streaming chat component with streamResource() in 5 minutes. +Build a streaming chat component with agent() in 5 minutes. Angular 20+ project with Node.js 18+. If you need setup help, see the [Installation](/docs/getting-started/installation) guide. @@ -10,21 +10,21 @@ Angular 20+ project with Node.js 18+. If you need setup help, see the [Installat ```bash -npm install @cacheplane/stream-resource +npm install @cacheplane/angular ``` -Add `provideStreamResource()` to your application config with your LangGraph Platform URL. +Add `provideAgent()` to your application config with your LangGraph Platform URL. ```typescript // app.config.ts -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'http://localhost:2024', }), ], @@ -34,7 +34,7 @@ export const appConfig: ApplicationConfig = { -Use `streamResource()` in a component field initializer. Every property on the returned ref is an Angular Signal. +Use `agent()` in a component field initializer. Every property on the returned ref is an Angular Signal. @@ -42,7 +42,7 @@ Use `streamResource()` in a component field initializer. Every property on the r ```typescript // chat.component.ts import { Component, ChangeDetectionStrategy, signal, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -54,7 +54,7 @@ export class ChatComponent { input = signal(''); // 'chat_agent' maps to the key in your langgraph.json "graphs" config - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: signal(localStorage.getItem('threadId')), onThreadId: (id) => localStorage.setItem('threadId', id), @@ -140,12 +140,12 @@ Open `http://localhost:4200` and start chatting with your agent. Add human-in-the-loop approval flows - Deep dive into how Signals power streamResource + Deep dive into how Signals power agent Graphs, nodes, edges, and state for Angular developers - - Complete streamResource() function reference + + Complete agent() function reference diff --git a/apps/website/content/docs-v2/guides/deployment.mdx b/apps/website/content/docs-v2/guides/deployment.mdx index 79e0faea7..28510e880 100644 --- a/apps/website/content/docs-v2/guides/deployment.mdx +++ b/apps/website/content/docs-v2/guides/deployment.mdx @@ -16,7 +16,7 @@ Your agent code needs a `langgraph.json` manifest at the project root. This file } ``` -The `graphs` key maps an assistant ID (used by `streamResource()` on the Angular side) to the Python module path and graph variable. The `env` key points to a file with secrets like `OPENAI_API_KEY` that will be injected at runtime. +The `graphs` key maps an assistant ID (used by `agent()` on the Angular side) to the Python module path and graph variable. The `env` key points to a file with secrets like `OPENAI_API_KEY` that will be injected at runtime. ### Agent entry point @@ -105,15 +105,15 @@ export const environment = { -Wire the environment into `provideStreamResource()`: +Wire the environment into `provideAgent()`: ```typescript -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: environment.langgraphUrl, }), ], @@ -154,7 +154,7 @@ import { langGraphAuthInterceptor } from './auth.interceptor'; export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withInterceptors([langGraphAuthInterceptor])), - provideStreamResource({ + provideAgent({ apiUrl: environment.langgraphUrl, }), ], @@ -198,11 +198,11 @@ During local development with `langgraph dev`, CORS is permissive by default. Yo ## Error boundaries -Production apps need graceful error handling. Build a reactive error boundary using `streamResource()` signals. +Production apps need graceful error handling. Build a reactive error boundary using `agent()` signals. ```typescript import { ChangeDetectionStrategy, Component, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -217,7 +217,7 @@ import { streamResource } from '@cacheplane/stream-resource'; `, }) export class ChatComponent { - chat = streamResource({ + chat = agent({ assistantId: 'chat_agent', }); @@ -248,7 +248,7 @@ For automated retries (network blips, transient 5xx errors), wrap `.submit()` wi ```typescript export async function retrySubmit( - chat: ReturnType, + chat: ReturnType, input: Record, maxAttempts = 3, ): Promise { @@ -283,7 +283,7 @@ if (savedRunId) { `joinStream()` replays any events the client missed, then switches to live streaming. This works because all state lives on the LangGraph Platform, and the SSE endpoint supports event ID-based resumption. -`streamResource()` is a stateless client. All state lives on the LangGraph Platform. This means your Angular app can be deployed anywhere (CDN, edge, SSR) without state management concerns. Scale your frontend independently of your agent infrastructure. +`agent()` is a stateless client. All state lives on the LangGraph Platform. This means your Angular app can be deployed anywhere (CDN, edge, SSR) without state management concerns. Scale your frontend independently of your agent infrastructure. ## CI/CD pipeline @@ -371,7 +371,7 @@ effect(() => { -Point `provideStreamResource({ apiUrl })` to your LangGraph Cloud deployment URL via `environment.prod.ts`. +Point `provideAgent({ apiUrl })` to your LangGraph Cloud deployment URL via `environment.prod.ts`. Add an HTTP interceptor to attach `x-api-key` headers to all LangGraph requests. @@ -420,8 +420,8 @@ Confirm LangSmith traces are arriving and set up alerts for error rate spikes an Understand the agent patterns your deployment will serve. - - Full reference for provideStreamResource configuration options. + + Full reference for provideAgent configuration options. Deep dive into error recovery patterns beyond basic error boundaries. diff --git a/apps/website/content/docs-v2/guides/interrupts.mdx b/apps/website/content/docs-v2/guides/interrupts.mdx index bb3bb7a2a..12fc94955 100644 --- a/apps/website/content/docs-v2/guides/interrupts.mdx +++ b/apps/website/content/docs-v2/guides/interrupts.mdx @@ -1,6 +1,6 @@ # Interrupts -Interrupts let your LangGraph agent pause mid-execution and hand control to a human. The agent proposes an action, the graph freezes, your Angular UI shows an approval dialog, the user decides, and the agent resumes with the human's decision. streamResource() surfaces interrupts as Angular Signals, so building approval flows, confirmation dialogs, and multi-step review experiences requires no manual event wiring. +Interrupts let your LangGraph agent pause mid-execution and hand control to a human. The agent proposes an action, the graph freezes, your Angular UI shows an approval dialog, the user decides, and the agent resumes with the human's decision. agent() surfaces interrupts as Angular Signals, so building approval flows, confirmation dialogs, and multi-step review experiences requires no manual event wiring. Use interrupts when an agent action is irreversible (sending an email, placing an order, deleting data), when the agent needs a human decision it cannot make on its own, or when compliance requires explicit approval before execution. @@ -18,7 +18,7 @@ The agent reasons about the user's request and determines an action that require The agent node calls `raise Interrupt(value={...})`, which freezes the graph. The interrupt payload is persisted in the checkpoint and streamed to the client. -streamResource() updates the `interrupt()` signal. Your Angular template detects the change through OnPush change detection and renders an approval dialog with the interrupt payload. +agent() updates the `interrupt()` signal. Your Angular template detects the change through OnPush change detection and renders an approval dialog with the interrupt payload. The user reviews the proposed action and clicks Approve or Reject. Your component calls `agent.submit()` with a resume payload containing the decision. @@ -131,7 +131,7 @@ Place the `raise Interrupt()` call in its own dedicated node. This gives you a c ## Angular: Building an Approval Component -When the agent raises an interrupt, streamResource() populates the `interrupt()` signal with the interrupt payload. Your component reads this signal to render a dialog and calls `submit()` to resume. +When the agent raises an interrupt, agent() populates the `interrupt()` signal with the interrupt payload. Your component reads this signal to render a dialog and calls `submit()` to resume. @@ -143,7 +143,7 @@ import { signal, ChangeDetectionStrategy, } from '@angular/core'; -import { streamResource, BaseMessage } from '@cacheplane/stream-resource'; +import { agent, BaseMessage } from '@cacheplane/angular'; interface ApprovalPayload { action: string; @@ -164,7 +164,7 @@ interface AgentState { changeDetection: ChangeDetectionStrategy.OnPush, }) export class ApprovalComponent { - agent = streamResource({ + agent = agent({ assistantId: 'approval_agent', }); @@ -354,7 +354,7 @@ import { computed, ChangeDetectionStrategy, } from '@angular/core'; -import { streamResource, BaseMessage } from '@cacheplane/stream-resource'; +import { agent, BaseMessage } from '@cacheplane/angular'; interface StepApproval { step_number: number; @@ -370,7 +370,7 @@ interface StepApproval { changeDetection: ChangeDetectionStrategy.OnPush, }) export class DeployApprovalComponent { - agent = streamResource<{ + agent = agent<{ messages: BaseMessage[]; plan: { step: string; description: string }[]; current_step: number; @@ -449,12 +449,12 @@ export class DeployApprovalComponent { ## Typed Interrupt Payloads with BagTemplate -By default, `interrupt()` returns an untyped object. The BagTemplate generic parameter on streamResource() lets you define the exact shape of your interrupt payloads, giving you full TypeScript safety throughout your component. +By default, `interrupt()` returns an untyped object. The BagTemplate generic parameter on agent() lets you define the exact shape of your interrupt payloads, giving you full TypeScript safety throughout your component. -BagTemplate is a type parameter on the streamResource 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. +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 { streamResource, BagTemplate } from '@cacheplane/stream-resource'; +import { agent, BagTemplate } from '@cacheplane/angular'; // Define the exact shape of your interrupt payload interface DeployApproval { @@ -466,7 +466,7 @@ interface DeployApproval { } // Pass the interrupt type via BagTemplate -const agent = streamResource< +const agent = agent< DeployState, BagTemplate<{ interrupt: DeployApproval }> >({ @@ -556,6 +556,6 @@ Because interrupts are checkpointed, the user can close their browser, come back Stream token-by-token responses alongside interrupt events. - Script interrupt events deterministically with MockStreamTransport. + Script interrupt events deterministically with MockAgentTransport. diff --git a/apps/website/content/docs-v2/guides/memory.mdx b/apps/website/content/docs-v2/guides/memory.mdx index ca507fdcc..f2484ca68 100644 --- a/apps/website/content/docs-v2/guides/memory.mdx +++ b/apps/website/content/docs-v2/guides/memory.mdx @@ -1,6 +1,6 @@ # Memory -Memory gives your LangGraph agent the ability to recall past interactions, user preferences, and learned facts. There are two distinct kinds: short-term memory scoped to a single thread (conversation), and long-term memory that persists across threads using the LangGraph Store API. streamResource() surfaces both through Angular Signals so your components stay reactive without manual state wiring. +Memory gives your LangGraph agent the ability to recall past interactions, user preferences, and learned facts. There are two distinct kinds: short-term memory scoped to a single thread (conversation), and long-term memory that persists across threads using the LangGraph Store API. agent() surfaces both through Angular Signals so your components stay reactive without manual state wiring. Short-term memory lives within a thread — it is the conversation history plus any custom state fields your agent accumulates during a run. Long-term memory lives in the LangGraph Store and survives across threads, users, and sessions. Think of short-term as "what happened in this conversation" and long-term as "what the agent knows about this user." @@ -75,7 +75,7 @@ graph = builder.compile() ```typescript import { Component, computed, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource, BaseMessage } from '@cacheplane/stream-resource'; +import { agent, BaseMessage } from '@cacheplane/angular'; interface AgentState { messages: BaseMessage[]; @@ -90,7 +90,7 @@ interface AgentState { changeDetection: ChangeDetectionStrategy.OnPush, }) export class MemoryChatComponent { - agent = streamResource({ + agent = agent({ assistantId: 'memory_agent', threadId: signal(localStorage.getItem('memory-thread')), onThreadId: (id) => localStorage.setItem('memory-thread', id), @@ -186,7 +186,7 @@ result = graph.invoke( On the Angular side, thread-scoped memory requires no extra code. The `threadId` signal handles it: ```typescript -const chat = streamResource({ +const chat = agent({ assistantId: 'memory_agent', threadId: signal(userId()), // Same user = same thread = same memory }); @@ -267,7 +267,7 @@ graph = builder.compile() ```typescript import { Component, computed, signal, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource, BaseMessage } from '@cacheplane/stream-resource'; +import { agent, BaseMessage } from '@cacheplane/angular'; @Component({ selector: 'app-longterm-chat', @@ -277,7 +277,7 @@ import { streamResource, BaseMessage } from '@cacheplane/stream-resource'; export class LongTermChatComponent { // Each conversation gets a new thread, but the agent // remembers the user across all of them via the Store. - agent = streamResource<{ messages: BaseMessage[] }>({ + agent = agent<{ messages: BaseMessage[] }>({ assistantId: 'memory_agent', config: { configurable: { user_id: 'user_42' } }, }); diff --git a/apps/website/content/docs-v2/guides/persistence.mdx b/apps/website/content/docs-v2/guides/persistence.mdx index 73b62cc72..305eb9c4d 100644 --- a/apps/website/content/docs-v2/guides/persistence.mdx +++ b/apps/website/content/docs-v2/guides/persistence.mdx @@ -1,9 +1,9 @@ # Persistence -Thread persistence keeps conversations alive across page refreshes, browser restarts, and server deployments. This guide covers configuring checkpointers on the Python side and wiring up thread management in your Angular components with streamResource(). +Thread persistence keeps conversations alive across page refreshes, browser restarts, and server deployments. This guide covers configuring checkpointers on the Python side and wiring up thread management in your Angular components with agent(). -LangGraph checkpoints agent state at every super-step. Each checkpoint is keyed by a thread ID. streamResource() connects to these checkpoints automatically, so your users resume exactly where they left off — even if your server restarted between sessions. +LangGraph checkpoints agent state at every super-step. Each checkpoint is keyed by a thread ID. agent() connects to these checkpoints automatically, so your users resume exactly where they left off — even if your server restarted between sessions. ## Python: Checkpointer Setup @@ -103,7 +103,7 @@ Use stable, user-scoped identifiers for thread IDs. A common pattern is `f"{user ## Angular: Basic Thread Persistence -Save the thread ID to localStorage so conversations survive page refreshes. streamResource() handles thread creation and restoration automatically. +Save the thread ID to localStorage so conversations survive page refreshes. agent() handles thread creation and restoration automatically. @@ -111,7 +111,7 @@ Save the thread ID to localStorage so conversations survive page refreshes. stre ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core'; import { signal } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -119,7 +119,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', // Restore thread from localStorage on mount threadId: signal(localStorage.getItem('threadId')), @@ -161,7 +161,7 @@ A real chat application needs a sidebar showing all conversations. Here is a ful ```typescript import { ChangeDetectionStrategy, Component, signal, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; interface Thread { id: string; @@ -178,7 +178,7 @@ export class ThreadListComponent { threads = signal(this.loadThreads()); activeThreadId = signal(null); - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: this.activeThreadId, onThreadId: (id) => { @@ -252,12 +252,12 @@ export class ThreadListComponent { ## Reactive Thread Switching -When you pass a Signal as `threadId`, streamResource() reacts to every change. Set the signal and the conversation switches automatically — no imperative calls needed. +When you pass a Signal as `threadId`, agent() reacts to every change. Set the signal and the conversation switches automatically — no imperative calls needed. ```typescript activeThreadId = signal(null); -chat = streamResource<{ messages: BaseMessage[] }>({ +chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: this.activeThreadId, // Signal — switches reactively onThreadId: (id) => this.activeThreadId.set(id), @@ -266,13 +266,13 @@ chat = streamResource<{ messages: BaseMessage[] }>({ // Clicking a thread in the sidebar triggers a reactive switch selectThread(id: string) { this.activeThreadId.set(id); - // streamResource detects the signal change, fetches the thread's + // agent detects the signal change, fetches the thread's // checkpoint from the server, and updates all derived signals } ``` -Use the `isThreadLoading()` signal to show a skeleton UI while streamResource() fetches checkpoint state from the server. This avoids a flash of empty content when switching threads. +Use the `isThreadLoading()` signal to show a skeleton UI while agent() fetches checkpoint state from the server. This avoids a flash of empty content when switching threads. ## Manual Thread Switching @@ -310,17 +310,17 @@ await chat.joinStream(runId, lastEventId); ``` -In most cases streamResource() handles reconnection internally. Use `joinStream()` directly only when you need explicit control — for example, when restoring a run ID from a URL parameter after a full page reload. +In most cases agent() handles reconnection internally. Use `joinStream()` directly only when you need explicit control — for example, when restoring a run ID from a URL parameter after a full page reload. ## Thread Lifecycle -streamResource() reads the `threadId` signal. If it contains a value, the existing thread's checkpoint is fetched from the server. +agent() reads the `threadId` signal. If it contains a value, the existing thread's checkpoint is fetched from the server. -If `threadId` is null, streamResource() creates a new thread via the LangGraph API and fires `onThreadId` with the new ID. +If `threadId` is null, agent() creates a new thread via the LangGraph API and fires `onThreadId` with the new ID. Each super-step is checkpointed server-side. The `messages()` signal updates in real time as events arrive. @@ -346,6 +346,6 @@ Setting the `threadId` signal (or calling `switchThread()`) loads the target thr Stream token-by-token responses and tool progress in real time. - Test thread persistence and switching deterministically with MockStreamTransport. + Test thread persistence and switching deterministically with MockAgentTransport. diff --git a/apps/website/content/docs-v2/guides/streaming.mdx b/apps/website/content/docs-v2/guides/streaming.mdx index 3e10aec03..2ec8b66d1 100644 --- a/apps/website/content/docs-v2/guides/streaming.mdx +++ b/apps/website/content/docs-v2/guides/streaming.mdx @@ -1,6 +1,6 @@ # Streaming -StreamResource provides token-by-token streaming from LangGraph agents via Server-Sent Events (SSE). Every update lands directly in Angular Signals — no subscriptions, no manual change detection. +Agent provides token-by-token streaming from LangGraph agents via Server-Sent Events (SSE). Every update lands directly in Angular Signals — no subscriptions, no manual change detection. Make sure you've completed the Installation guide first. @@ -8,7 +8,7 @@ Make sure you've completed the Installation guide first. ## How streaming works -Streaming starts on the agent side. LangGraph's `astream()` method controls what data is sent over the SSE connection. On the Angular side, `streamResource()` consumes those events and maps them to Signals. +Streaming starts on the agent side. LangGraph's `astream()` method controls what data is sent over the SSE connection. On the Angular side, `agent()` consumes those events and maps them to Signals. @@ -59,7 +59,7 @@ async for event in graph.astream_events( ```typescript import { Component, computed, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -68,7 +68,7 @@ import { BaseMessage } from '@langchain/core/messages'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - readonly chat = streamResource<{ messages: BaseMessage[] }>({ + readonly chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -126,7 +126,7 @@ LangGraph supports three stream modes. Pass `streamMode` to control what each SS ```typescript // Receives the full agent state after every node execution. // Best for message-based chat interfaces. -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', streamMode: 'values', }); @@ -140,7 +140,7 @@ const chat = streamResource<{ messages: BaseMessage[] }>({ ```typescript // Streams individual message tokens as they are generated. // Best for token-by-token rendering with lowest perceived latency. -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', streamMode: 'messages', }); @@ -152,7 +152,7 @@ const chat = streamResource<{ messages: BaseMessage[] }>({ ```typescript // Emits raw LangGraph run events (on_chain_start, on_llm_stream, etc.). // Best for advanced observability or custom progress indicators. -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', streamMode: 'events', }); @@ -174,7 +174,7 @@ If the SSE connection drops or the agent throws, `status()` transitions to `'err ```typescript import { Component, computed, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -183,7 +183,7 @@ import { BaseMessage } from '@langchain/core/messages'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - readonly chat = streamResource<{ messages: BaseMessage[] }>({ + readonly chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -217,10 +217,10 @@ export class ChatComponent { ## Throttle configuration -By default StreamResource emits a signal update for every incoming SSE chunk. On fast connections this can trigger hundreds of renders per second. Use the `throttle` option to coalesce updates. +By default Agent emits a signal update for every incoming SSE chunk. On fast connections this can trigger hundreds of renders per second. Use the `throttle` option to coalesce updates. ```typescript -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', // Batch incoming chunks and flush at most once every 50 ms throttle: 50, @@ -249,9 +249,9 @@ Each call to `chat.submit()` opens a new SSE connection. Connections are automat Pause agent execution mid-stream to collect human input before continuing. - Unit-test components that use streamResource with the built-in test harness. + Unit-test components that use agent with the built-in test harness. - - Full option reference for streamResource(), including all configuration keys. + + Full option reference for agent(), including all configuration keys. diff --git a/apps/website/content/docs-v2/guides/subgraphs.mdx b/apps/website/content/docs-v2/guides/subgraphs.mdx index 3c0f114fa..f816f6c8a 100644 --- a/apps/website/content/docs-v2/guides/subgraphs.mdx +++ b/apps/website/content/docs-v2/guides/subgraphs.mdx @@ -1,9 +1,9 @@ # Subgraphs -Subgraphs let you compose complex agents from smaller, focused units. streamResource() tracks subagent execution through dedicated signals, giving you visibility into delegated work. +Subgraphs let you compose complex agents from smaller, focused units. agent() tracks subagent execution through dedicated signals, giving you visibility into delegated work. -LangGraph calls them subgraphs (modular graph composition). Deep Agents calls them subagents (task delegation). streamResource() supports both patterns through the same API. +LangGraph calls them subgraphs (modular graph composition). Deep Agents calls them subagents (task delegation). agent() supports both patterns through the same API. ## How subgraph composition works @@ -75,7 +75,7 @@ graph = builder.compile() ```typescript import { Component, computed, inject, effect, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-orchestrator', @@ -83,7 +83,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class OrchestratorComponent { - readonly orchestrator = streamResource({ + readonly orchestrator = agent({ assistantId: 'orchestrator', subagentToolNames: ['research', 'analyze'], }); @@ -107,7 +107,7 @@ export class OrchestratorComponent { The `subagents()` signal contains a Map of active subagent streams. Use it to inspect the full set of delegated tasks and their current state. ```typescript -const orchestrator = streamResource({ +const orchestrator = agent({ assistantId: 'orchestrator', subagentToolNames: ['research', 'analyze', 'summarize'], }); @@ -146,7 +146,7 @@ const researchError = computed(() => researchAgent()?.error()); The orchestrator pattern delegates specialised work to subagents and merges their results. Each subagent runs its own graph independently while the parent coordinates. ```typescript -const pipeline = streamResource({ +const pipeline = agent({ assistantId: 'pipeline-orchestrator', subagentToolNames: ['fetch-data', 'transform', 'validate', 'publish'], filterSubagentMessages: true, @@ -217,7 +217,7 @@ export class SubagentProgressComponent { By default, subagent messages appear in the parent's `messages()` signal. Filter them out for a cleaner parent view. ```typescript -const orchestrator = streamResource({ +const orchestrator = agent({ assistantId: 'orchestrator', filterSubagentMessages: true, // Hide subagent messages from parent subagentToolNames: ['research', 'analyze'], @@ -228,7 +228,7 @@ const parentMessages = computed(() => orchestrator.messages()); ``` -Set `subagentToolNames` to the tool names that spawn subagents. streamResource() uses this to identify which tool calls create subagent streams. +Set `subagentToolNames` to the tool names that spawn subagents. agent() uses this to identify which tool calls create subagent streams. ## Error handling per subagent @@ -270,7 +270,7 @@ Use **subagents** when tasks are independent and can run in parallel, when each - Understand how streamResource() surfaces tokens, status, and errors in real time. + Understand how agent() surfaces tokens, status, and errors in real time. Inspect earlier states and replay alternate execution paths with checkpoint history. @@ -278,7 +278,7 @@ Use **subagents** when tasks are independent and can run in parallel, when each Write unit and integration tests for orchestrator graphs and subagent interactions. - - Full reference for streamResource() options, signals, and subagent configuration. + + Full reference for agent() options, signals, and subagent configuration. diff --git a/apps/website/content/docs-v2/guides/testing.mdx b/apps/website/content/docs-v2/guides/testing.mdx index 453bd54ce..482a226cb 100644 --- a/apps/website/content/docs-v2/guides/testing.mdx +++ b/apps/website/content/docs-v2/guides/testing.mdx @@ -1,9 +1,9 @@ # Testing -MockStreamTransport lets you test agent interactions deterministically without a running LangGraph server. Script exact event sequences, step through streaming lifecycles, and verify every signal transition in your Angular test specs. +MockAgentTransport lets you test agent interactions deterministically without a running LangGraph server. Script exact event sequences, step through streaming lifecycles, and verify every signal transition in your Angular test specs. -MockStreamTransport eliminates network dependencies, timing issues, and server state. Every test run produces identical results. Your CI pipeline stays green. +MockAgentTransport eliminates network dependencies, timing issues, and server state. Every test run produces identical results. Your CI pipeline stays green. ## Python: Testing the Agent @@ -39,24 +39,24 @@ async def test_agent_uses_tools(): With MemorySaver and a mocked LLM, agent tests run in milliseconds. Use `langchain_core.language_models.FakeListChatModel` to remove the LLM dependency entirely. -## MockStreamTransport: Basic Setup +## MockAgentTransport: Basic Setup -On the Angular side, MockStreamTransport replaces the real HTTP transport. Create it inside `TestBed.runInInjectionContext` so streamResource() has access to Angular's dependency injection. +On the Angular side, MockAgentTransport replaces the real HTTP transport. Create it inside `TestBed.runInInjectionContext` so agent() has access to Angular's dependency injection. ```typescript import { TestBed } from '@angular/core/testing'; -import { MockStreamTransport, streamResource } from '@cacheplane/stream-resource'; -import type { BaseMessage } from '@cacheplane/stream-resource'; +import { MockAgentTransport, agent } from '@cacheplane/angular'; +import type { BaseMessage } from '@cacheplane/angular'; describe('ChatComponent', () => { it('should display agent messages', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -81,7 +81,7 @@ describe('ChatComponent', () => { ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -89,7 +89,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -107,7 +107,7 @@ export class ChatComponent { Pass event batches to the constructor for sequential playback. Each call to `nextBatch()` advances one step — giving you frame-by-frame control over what the component sees. ```typescript -const transport = new MockStreamTransport([ +const transport = new MockAgentTransport([ // Batch 1: Agent starts thinking [{ type: 'values', messages: [{ role: 'assistant', content: 'Analyzing...' }] }], // Batch 2: Agent finishes @@ -115,7 +115,7 @@ const transport = new MockStreamTransport([ ]); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -140,17 +140,17 @@ The most common test pattern verifies the full submit-to-resolved lifecycle: sub ```typescript import { TestBed } from '@angular/core/testing'; -import { MockStreamTransport, streamResource } from '@cacheplane/stream-resource'; +import { MockAgentTransport, agent } from '@cacheplane/angular'; describe('streaming lifecycle', () => { it('should transition through loading → values → resolved', () => { - const transport = new MockStreamTransport([ + const transport = new MockAgentTransport([ [{ type: 'values', messages: [{ role: 'assistant', content: 'Thinking...' }] }], [{ type: 'values', messages: [{ role: 'assistant', content: 'Done!' }] }], ]); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -187,7 +187,7 @@ describe('streaming lifecycle', () => { ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -202,7 +202,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); @@ -224,14 +224,14 @@ Script an interrupt event to test human-in-the-loop flows. Verify the interrupt ```typescript import { TestBed } from '@angular/core/testing'; -import { MockStreamTransport, streamResource } from '@cacheplane/stream-resource'; +import { MockAgentTransport, agent } from '@cacheplane/angular'; describe('interrupt handling', () => { it('should surface interrupt and resume on approval', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { - const agent = streamResource<{ messages: BaseMessage[] }>({ + const agent = agent<{ messages: BaseMessage[] }>({ assistantId: 'approval_agent', transport, }); @@ -272,7 +272,7 @@ describe('interrupt handling', () => { ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-approval', @@ -289,7 +289,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ApprovalComponent { - agent = streamResource<{ messages: BaseMessage[] }>({ + agent = agent<{ messages: BaseMessage[] }>({ assistantId: 'approval_agent', }); @@ -315,14 +315,14 @@ Inject errors with `emitError()` to verify your component handles failures grace ```typescript import { TestBed } from '@angular/core/testing'; -import { MockStreamTransport, streamResource } from '@cacheplane/stream-resource'; +import { MockAgentTransport, agent } from '@cacheplane/angular'; describe('error handling', () => { it('should surface errors and set error status', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -340,10 +340,10 @@ describe('error handling', () => { }); it('should recover from errors on retry', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -374,7 +374,7 @@ describe('error handling', () => { ```typescript import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; @Component({ selector: 'app-chat', @@ -389,7 +389,7 @@ import { streamResource } from '@cacheplane/stream-resource'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); private lastMessage = ''; @@ -415,12 +415,12 @@ Verify that switching threads loads the correct conversation state and clears th ```typescript describe('thread switching', () => { it('should load new thread state on switch', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { const threadId = signal('thread_A'); - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', threadId, transport, @@ -450,10 +450,10 @@ describe('thread switching', () => { }); it('should create a new thread when switching to null', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { - const chat = streamResource<{ messages: BaseMessage[] }>({ + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test_agent', transport, }); @@ -478,16 +478,16 @@ describe('thread switching', () => { -Make sure `@cacheplane/stream-resource` is available in your test environment. MockStreamTransport ships with the main package — no extra install needed. +Make sure `@cacheplane/angular` is available in your test environment. MockAgentTransport ships with the main package — no extra install needed. -Instantiate `MockStreamTransport` with optional pre-scripted batches for sequential playback, or leave it empty for imperative `emit()` calls. +Instantiate `MockAgentTransport` with optional pre-scripted batches for sequential playback, or leave it empty for imperative `emit()` calls. -Call `TestBed.runInInjectionContext(() => { ... })` so streamResource() can access Angular's injector for signal creation and cleanup. +Call `TestBed.runInInjectionContext(() => { ... })` so agent() can access Angular's injector for signal creation and cleanup. -Pass the transport to streamResource() via the `transport` option. All other options (assistantId, threadId, onThreadId) work identically to production code. +Pass the transport to agent() via the `transport` option. All other options (assistantId, threadId, onThreadId) work identically to production code. Use `transport.emit()` for ad-hoc events, `transport.nextBatch()` for pre-scripted sequences, or `transport.emitError()` for failure scenarios. @@ -505,12 +505,12 @@ For end-to-end confidence, run tests against a real LangGraph dev server. The La # Start the dev server langgraph dev --config langgraph.json -# Run Angular tests against it (no MockStreamTransport needed) +# Run Angular tests against it (no MockAgentTransport needed) ng test --watch=false ``` -Integration tests hit a real server and (potentially) a real LLM. Reserve them for CI pipelines or pre-release smoke tests. Use MockStreamTransport for the vast majority of your test suite — it runs in milliseconds with zero external dependencies. +Integration tests hit a real server and (potentially) a real LLM. Reserve them for CI pipelines or pre-release smoke tests. Use MockAgentTransport for the vast majority of your test suite — it runs in milliseconds with zero external dependencies. ## What's Next @@ -526,6 +526,6 @@ Integration tests hit a real server and (potentially) a real LLM. Reserve them f Thread persistence patterns that pair with thread-switching tests. - Full reference for MockStreamTransport options and methods. + Full reference for MockAgentTransport options and methods. diff --git a/apps/website/content/docs-v2/guides/time-travel.mdx b/apps/website/content/docs-v2/guides/time-travel.mdx index 570c1c084..84ffd8666 100644 --- a/apps/website/content/docs-v2/guides/time-travel.mdx +++ b/apps/website/content/docs-v2/guides/time-travel.mdx @@ -1,6 +1,6 @@ # Time Travel -Time travel lets you inspect earlier states and replay alternate execution paths. `streamResource()` exposes the full checkpoint history and branch navigation through Angular Signals. Use it to debug agent decisions, explore alternate paths, and build undo/redo experiences. +Time travel lets you inspect earlier states and replay alternate execution paths. `agent()` exposes the full checkpoint history and branch navigation through Angular Signals. Use it to debug agent decisions, explore alternate paths, and build undo/redo experiences. Debug agent decisions, explore alternate paths, and build undo/redo experiences for your users. Time travel works with any LangGraph agent that persists checkpoints to a thread. @@ -61,7 +61,7 @@ past_state = graph.get_state(past_config) ```typescript import { Component, inject, computed, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { AgentService } from './agent.service'; @Component({ @@ -102,7 +102,7 @@ export class HistoryViewerComponent { The `history()` signal contains an array of `ThreadState` checkpoints ordered from oldest to newest. Each checkpoint captures the complete agent state at that point in execution, including messages, intermediate results, and any custom state fields. ```typescript -const agent = streamResource({ +const agent = agent({ assistantId: 'agent', threadId: signal(threadId), }); @@ -171,7 +171,7 @@ Expose checkpoint history directly in your component to let users scrub through ```typescript import { Component, inject, computed, ChangeDetectionStrategy } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { AgentService } from './agent.service'; @Component({ @@ -292,12 +292,12 @@ Time travel is most useful during development. Inspect why an agent chose a part Configure thread storage so checkpoints survive page reloads and are available across sessions. - Understand how streamResource() surfaces incremental updates and how history integrates with live streaming state. + Understand how agent() surfaces incremental updates and how history integrates with live streaming state. Compose multi-agent systems with orchestrators and track subagent execution. - - Full reference for streamResource() options, signals, and the submit() API including checkpoint parameters. + + Full reference for agent() options, signals, and the submit() API including checkpoint parameters. diff --git a/apps/website/content/docs/getting-started.mdx b/apps/website/content/docs/getting-started.mdx index 13760418e..fcf86b3d0 100644 --- a/apps/website/content/docs/getting-started.mdx +++ b/apps/website/content/docs/getting-started.mdx @@ -1,23 +1,23 @@ # Getting Started -Add stream-resource to your Angular 20+ application. +Add angular to your Angular 20+ application. ## Installation ```bash -npm install stream-resource@latest +npm install angular@latest ``` ## Setup -In `app.config.ts`, add `provideStreamResource` to your providers: +In `app.config.ts`, add `provideAgent` to your providers: ```typescript -import { provideStreamResource } from 'stream-resource'; +import { provideAgent } from 'angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: 'http://localhost:2024' }), + provideAgent({ apiUrl: 'http://localhost:2024' }), ], }; ``` @@ -25,7 +25,7 @@ export const appConfig: ApplicationConfig = { ## Your first component ```typescript -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; @Component({ template: ` @@ -38,10 +38,10 @@ import { streamResource } from 'stream-resource'; `, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); } ``` -`streamResource()` MUST be called in an Angular injection context (component field initializer or constructor). Never call it in `ngOnInit`. +`agent()` MUST be called in an Angular injection context (component field initializer or constructor). Never call it in `ngOnInit`. diff --git a/apps/website/content/docs/introduction.mdx b/apps/website/content/docs/introduction.mdx index 9f43dcac1..7a55ed4ee 100644 --- a/apps/website/content/docs/introduction.mdx +++ b/apps/website/content/docs/introduction.mdx @@ -1,19 +1,19 @@ # Introduction -StreamResource is the Angular streaming library for LangChain and LangGraph. +Agent is the Angular streaming library for LangChain and LangGraph. ## Installation ```bash -npm install stream-resource +npm install angular ``` ## Quick start ```typescript -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; -const chat = streamResource({ +const chat = agent({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024', }); diff --git a/apps/website/content/prompts/configuration.md b/apps/website/content/prompts/configuration.md index 9ce9f812e..34dab8085 100644 --- a/apps/website/content/prompts/configuration.md +++ b/apps/website/content/prompts/configuration.md @@ -1,13 +1,13 @@ -Configure stream-resource globally and per-component in my Angular application. +Configure angular globally and per-component in my Angular application. -Global config (applies to all streamResource() calls in the app): -In app.config.ts, provideStreamResource({ apiUrl: 'https://my-langgraph-server.com', }) — import provideStreamResource from '@cacheplane/stream-resource'. +Global config (applies to all agent() calls in the app): +In app.config.ts, provideAgent({ apiUrl: 'https://my-langgraph-server.com', }) — import provideAgent from '@cacheplane/angular'. Per-call override (overrides global config for one component): -Pass apiUrl directly to streamResource({ apiUrl: 'https://other-server.com', assistantId: 'my-agent' }) — per-call options take precedence over global config. +Pass apiUrl directly to agent({ apiUrl: 'https://other-server.com', assistantId: 'my-agent' }) — per-call options take precedence over global config. Custom transport (for auth headers, logging, or testing): -Implement StreamResourceTransport interface — it has one method: stream(input, options). Pass it as transport: myTransport to either provideStreamResource or streamResource(). FetchStreamTransport is the default. +Implement AgentTransport interface — it has one method: stream(input, options). Pass it as transport: myTransport to either provideAgent or agent(). FetchStreamTransport is the default. To pass a system prompt to the LangGraph agent per-thread, use the config option: -streamResource({ config: { configurable: { system_prompt: 'You are a helpful assistant.' } } }) +agent({ config: { configurable: { system_prompt: 'You are a helpful assistant.' } } }) diff --git a/apps/website/content/prompts/getting-started.md b/apps/website/content/prompts/getting-started.md index 06e3dd724..eca0e3756 100644 --- a/apps/website/content/prompts/getting-started.md +++ b/apps/website/content/prompts/getting-started.md @@ -1,13 +1,13 @@ -Add stream-resource to my Angular 20+ application. +Add angular to my Angular 20+ application. -Install: npm install @cacheplane/stream-resource@latest +Install: npm install @cacheplane/angular@latest -1. In app.config.ts, add provideStreamResource({ apiUrl: 'http://localhost:2024' }) to the providers array. Import it from '@cacheplane/stream-resource'. +1. In app.config.ts, add provideAgent({ apiUrl: 'http://localhost:2024' }) to the providers array. Import it from '@cacheplane/angular'. -2. Create a ChatComponent that calls streamResource<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }) in the constructor or as a field initializer. streamResource() MUST be called inside an Angular injection context — constructor or field initializer is correct; ngOnInit is not. +2. Create a ChatComponent that calls agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }) in the constructor or as a field initializer. agent() MUST be called inside an Angular injection context — constructor or field initializer is correct; ngOnInit is not. 3. The component template should loop over chat.messages() using @for and render each message's content. Add an input field and a button that calls chat.submit({ messages: [{ role: 'human', content: inputValue }] }). -4. In app.config.ts provideStreamResource call, the apiUrl should point to the LangGraph server. For local dev this is http://localhost:2024. For production use the LangGraph Platform URL from environment.ts. +4. In app.config.ts provideAgent call, the apiUrl should point to the LangGraph server. For local dev this is http://localhost:2024. For production use the LangGraph Platform URL from environment.ts. The library is framework-integrated: no subscriptions, no async pipe needed — chat.messages() is an Angular Signal that updates token by token as the LLM responds. diff --git a/apps/website/content/prompts/streaming.md b/apps/website/content/prompts/streaming.md index 9ffc7c423..dce537582 100644 --- a/apps/website/content/prompts/streaming.md +++ b/apps/website/content/prompts/streaming.md @@ -1,12 +1,12 @@ -Configure token-by-token streaming in my Angular component that uses stream-resource. +Configure token-by-token streaming in my Angular component that uses angular. -The component already has streamResource() set up. Now: +The component already has agent() set up. Now: 1. In the template, bind to chat.messages() with @for — each BaseMessage has a .content property. The template re-renders automatically as tokens arrive because messages() is a Signal. 2. Show a loading indicator while streaming: use chat.isLoading() in an @if block. -3. To throttle rapid re-renders (if performance is a concern), pass throttle: 50 to streamResource() options — this throttles Signal updates to at most one per 50ms while preserving the final value. +3. To throttle rapid re-renders (if performance is a concern), pass throttle: 50 to agent() options — this throttles Signal updates to at most one per 50ms while preserving the final value. 4. To show the stream status more precisely, bind to chat.status() which returns 'idle' | 'loading' | 'resolved' | 'error'. diff --git a/apps/website/content/prompts/testing.md b/apps/website/content/prompts/testing.md index 22eac0fc3..650ae4367 100644 --- a/apps/website/content/prompts/testing.md +++ b/apps/website/content/prompts/testing.md @@ -1,10 +1,10 @@ -Write unit tests for my Angular component that uses stream-resource, without hitting a real LangGraph server. +Write unit tests for my Angular component that uses angular, without hitting a real LangGraph server. -Use MockStreamTransport from '@cacheplane/stream-resource'. It implements StreamResourceTransport and lets you script exactly what events the stream emits. +Use MockAgentTransport from '@cacheplane/angular'. It implements AgentTransport and lets you script exactly what events the stream emits. Test setup: -const transport = new MockStreamTransport(); -const chat = streamResource({ transport, assistantId: 'test', apiUrl: '' }); +const transport = new MockAgentTransport(); +const chat = agent({ transport, assistantId: 'test', apiUrl: '' }); To emit a streaming response: transport.emit([ @@ -21,4 +21,4 @@ transport.emitError(new Error('Network failure')); expect(chat.status()).toBe('error'); expect(chat.error()).toBeInstanceOf(Error); -Never mock streamResource() itself — always use MockStreamTransport and test through the real function. +Never mock agent() itself — always use MockAgentTransport and test through the real function. diff --git a/apps/website/content/prompts/thread-persistence.md b/apps/website/content/prompts/thread-persistence.md index cba9b2496..7be3acc45 100644 --- a/apps/website/content/prompts/thread-persistence.md +++ b/apps/website/content/prompts/thread-persistence.md @@ -1,13 +1,13 @@ -Add thread persistence to my Angular component that uses stream-resource, so conversations survive page refresh. +Add thread persistence to my Angular component that uses angular, so conversations survive page refresh. 1. On component init, read the stored thread ID: const storedId = localStorage.getItem('chat-thread-id'). 2. Create a signal: threadId = signal(storedId). -3. Pass it to streamResource: streamResource({ ..., threadId: this.threadId, onThreadId: (id) => { this.threadId.set(id); localStorage.setItem('chat-thread-id', id); } }). +3. Pass it to agent: agent({ ..., threadId: this.threadId, onThreadId: (id) => { this.threadId.set(id); localStorage.setItem('chat-thread-id', id); } }). 4. The onThreadId callback fires once when the server creates a new thread. After that, the same thread ID is reused and the full conversation history is restored from the LangGraph server. -5. To start a new conversation, call this.threadId.set(null) — this causes streamResource to create a fresh thread on the next submit. +5. To start a new conversation, call this.threadId.set(null) — this causes agent to create a fresh thread on the next submit. No changes to the template are needed. diff --git a/apps/website/e2e/website.spec.ts b/apps/website/e2e/website.spec.ts index 5638573b3..847230842 100644 --- a/apps/website/e2e/website.spec.ts +++ b/apps/website/e2e/website.spec.ts @@ -14,7 +14,7 @@ test('landing page renders architecture section', async ({ page }) => { test('landing page renders fair comparison section', async ({ page }) => { await page.goto('/'); - await expect(page.getByText('What Angular Stream Resource adds').first()).toBeVisible(); + await expect(page.getByText('What Angular Agent Framework adds').first()).toBeVisible(); }); test('pricing page shows 4 plan cards', async ({ page }) => { @@ -38,8 +38,8 @@ test('docs page renders sidebar and content', async ({ page }) => { }); test('api reference renders in docs', async ({ page }) => { - await page.goto('/docs/api/stream-resource'); - await expect(page.getByText('streamResource()').first()).toBeVisible(); + await page.goto('/docs/api/angular'); + await expect(page.getByText('agent()').first()).toBeVisible(); }); test('nav has pricing link', async ({ page }) => { diff --git a/apps/website/emails/newsletter-welcome.ts b/apps/website/emails/newsletter-welcome.ts index 2873ca725..d90d28dac 100644 --- a/apps/website/emails/newsletter-welcome.ts +++ b/apps/website/emails/newsletter-welcome.ts @@ -2,11 +2,11 @@ export function newsletterWelcomeHtml(): string { return `
-

Angular Stream Resource

-

Welcome to Angular Stream Resource updates

+

Angular Agent Framework

+

Welcome to Angular Agent Framework updates

You'll receive updates on new capabilities, production patterns, and Angular agent best practices. We keep it focused and infrequent — no spam.

Explore the Docs
-

Angular Stream Resource — Signal-native streaming for LangGraph.

+

Angular Agent Framework — Signal-native streaming for LangGraph.

`; } diff --git a/apps/website/emails/whitepaper-download.ts b/apps/website/emails/whitepaper-download.ts index 6b8ff2eeb..c57487368 100644 --- a/apps/website/emails/whitepaper-download.ts +++ b/apps/website/emails/whitepaper-download.ts @@ -4,14 +4,14 @@ export function whitepaperDownloadHtml(name?: string): string { return `
-

Angular Stream Resource

+

Angular Agent Framework

Your Angular Agent Readiness Guide

${name ? `Hi ${esc(name)}, t` : 'T'}he guide covers six production-readiness dimensions: streaming state, thread persistence, tool-call rendering, human approval flows, generative UI, and deterministic testing.

Download the Guide

-

Angular Stream Resource — Signal-native streaming for LangGraph.

+

Angular Agent Framework — Signal-native streaming for LangGraph.

`; } diff --git a/apps/website/lib/resend.ts b/apps/website/lib/resend.ts index 2279f4359..85e60cf69 100644 --- a/apps/website/lib/resend.ts +++ b/apps/website/lib/resend.ts @@ -11,7 +11,7 @@ function getResend(): Resend | null { } export const AUDIENCE_ID = process.env.RESEND_AUDIENCE_ID || ''; -export const FROM = process.env.RESEND_FROM || 'Angular Stream Resource '; +export const FROM = process.env.RESEND_FROM || 'Angular Agent Framework '; export const NOTIFY_TO = process.env.RESEND_NOTIFY_TO || 'hello@cacheplane.io'; /** Send an email via Resend. No-ops when API key is missing. */ diff --git a/apps/website/next-env.d.ts b/apps/website/next-env.d.ts index fdbfe5258..c4b7818fb 100644 --- a/apps/website/next-env.d.ts +++ b/apps/website/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./../../dist/apps/website/.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/website/public/AGENTS.md b/apps/website/public/AGENTS.md index c0f0ccbb9..7e9ff976a 100644 --- a/apps/website/public/AGENTS.md +++ b/apps/website/public/AGENTS.md @@ -1,23 +1,23 @@ -# Angular Stream Resource v0.0.1 +# Angular Agent Framework v0.0.1 -Angular streaming library for LangChain/LangGraph. Provides `streamResource()` — full parity with React's `useStream()`. +Angular streaming library for LangChain/LangGraph. Provides `agent()` — full parity with React's `useStream()`. ## Install -npm install stream-resource +npm install angular ## Key requirement -`streamResource()` 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". +`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 { provideStreamResource } from 'stream-resource'; +import { provideAgent } from 'angular'; export const appConfig: ApplicationConfig = { - providers: [provideStreamResource({ apiUrl: 'http://localhost:2024' })] + providers: [provideAgent({ apiUrl: 'http://localhost:2024' })] }; // chat.component.ts -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ template: ` @@ -25,20 +25,20 @@ import type { BaseMessage } from '@langchain/core/messages'; `}) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); send() { this.chat.submit({ messages: [{ role: 'human', content: 'Hello' }] }); } } ``` ## Key patterns - Thread persistence: `threadId: signal(localStorage.getItem('t'))` + `onThreadId: (id) => localStorage.setItem('t', id)` -- Global config: `provideStreamResource({ apiUrl })` in app.config.ts -- Per-call override: pass `apiUrl` directly to `streamResource()` -- Testing: use `MockStreamTransport` — never mock `streamResource()` itself +- Global config: `provideAgent({ apiUrl })` in app.config.ts +- Per-call override: pass `apiUrl` directly to `agent()` +- Testing: use `MockAgentTransport` — never mock `agent()` itself ## MCP server (for tool access) Add to ~/.claude/settings.json: -{"mcpServers":{"stream-resource":{"command":"npx","args":["@stream-resource/mcp"]}}} +{"mcpServers":{"angular":{"command":"npx","args":["@angular/mcp"]}}} ## Version check If this file is stale, fetch the latest: https://stream-resource.dev/llms-full.txt diff --git a/apps/website/public/CLAUDE.md b/apps/website/public/CLAUDE.md index c0f0ccbb9..7e9ff976a 100644 --- a/apps/website/public/CLAUDE.md +++ b/apps/website/public/CLAUDE.md @@ -1,23 +1,23 @@ -# Angular Stream Resource v0.0.1 +# Angular Agent Framework v0.0.1 -Angular streaming library for LangChain/LangGraph. Provides `streamResource()` — full parity with React's `useStream()`. +Angular streaming library for LangChain/LangGraph. Provides `agent()` — full parity with React's `useStream()`. ## Install -npm install stream-resource +npm install angular ## Key requirement -`streamResource()` 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". +`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 { provideStreamResource } from 'stream-resource'; +import { provideAgent } from 'angular'; export const appConfig: ApplicationConfig = { - providers: [provideStreamResource({ apiUrl: 'http://localhost:2024' })] + providers: [provideAgent({ apiUrl: 'http://localhost:2024' })] }; // chat.component.ts -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ template: ` @@ -25,20 +25,20 @@ import type { BaseMessage } from '@langchain/core/messages'; `}) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); send() { this.chat.submit({ messages: [{ role: 'human', content: 'Hello' }] }); } } ``` ## Key patterns - Thread persistence: `threadId: signal(localStorage.getItem('t'))` + `onThreadId: (id) => localStorage.setItem('t', id)` -- Global config: `provideStreamResource({ apiUrl })` in app.config.ts -- Per-call override: pass `apiUrl` directly to `streamResource()` -- Testing: use `MockStreamTransport` — never mock `streamResource()` itself +- Global config: `provideAgent({ apiUrl })` in app.config.ts +- Per-call override: pass `apiUrl` directly to `agent()` +- Testing: use `MockAgentTransport` — never mock `agent()` itself ## MCP server (for tool access) Add to ~/.claude/settings.json: -{"mcpServers":{"stream-resource":{"command":"npx","args":["@stream-resource/mcp"]}}} +{"mcpServers":{"angular":{"command":"npx","args":["@angular/mcp"]}}} ## Version check If this file is stale, fetch the latest: https://stream-resource.dev/llms-full.txt diff --git a/apps/website/public/api-docs.json b/apps/website/public/api-docs.json index 687f2d54b..17e9f7d66 100644 --- a/apps/website/public/api-docs.json +++ b/apps/website/public/api-docs.json @@ -1,7 +1,7 @@ { "schemaVersion": "2.0", "id": 0, - "name": "stream-resource", + "name": "angular", "variant": "project", "kind": 1, "flags": {}, @@ -21,7 +21,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 8, "character": 2 } @@ -35,7 +35,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 8, "character": 2 } @@ -102,7 +102,7 @@ "type": "reference", "target": 206, "name": "FetchStreamTransport", - "package": "stream-resource" + "package": "angular" } } ] @@ -115,7 +115,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 41, "character": 9 } @@ -137,7 +137,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 41, "character": 9 } @@ -215,7 +215,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } ], "name": "AsyncIterable", @@ -224,14 +224,14 @@ "implementationOf": { "type": "reference", "target": 92, - "name": "StreamResourceTransport.joinStream" + "name": "AgentTransport.joinStream" } } ], "implementationOf": { "type": "reference", "target": 91, - "name": "StreamResourceTransport.joinStream" + "name": "AgentTransport.joinStream" } }, { @@ -242,7 +242,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 13, "character": 9 } @@ -256,7 +256,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 13, "character": 9 } @@ -334,7 +334,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } ], "name": "AsyncIterable", @@ -343,14 +343,14 @@ "implementationOf": { "type": "reference", "target": 86, - "name": "StreamResourceTransport.stream" + "name": "AgentTransport.stream" } } ], "implementationOf": { "type": "reference", "target": 85, - "name": "StreamResourceTransport.stream" + "name": "AgentTransport.stream" } } ], @@ -371,7 +371,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/fetch-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/fetch-stream.transport.ts", "line": 4, "character": 13 } @@ -380,14 +380,14 @@ { "type": "reference", "target": 84, - "name": "StreamResourceTransport", - "package": "stream-resource" + "name": "AgentTransport", + "package": "angular" } ] }, { "id": 173, - "name": "MockStreamTransport", + "name": "MockAgentTransport", "variant": "declaration", "kind": 128, "flags": {}, @@ -400,7 +400,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 13, "character": 2 } @@ -408,13 +408,13 @@ "signatures": [ { "id": 175, - "name": "MockStreamTransport", + "name": "MockAgentTransport", "variant": "signature", "kind": 16384, "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 13, "character": 2 } @@ -434,7 +434,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } } }, @@ -444,8 +444,8 @@ "type": { "type": "reference", "target": 173, - "name": "MockStreamTransport", - "package": "stream-resource" + "name": "MockAgentTransport", + "package": "angular" } } ] @@ -458,7 +458,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 32, "character": 2 } @@ -472,7 +472,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 32, "character": 2 } @@ -492,7 +492,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 22, "character": 2 } @@ -506,7 +506,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 22, "character": 2 } @@ -524,7 +524,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } } } @@ -544,7 +544,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 27, "character": 2 } @@ -558,7 +558,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 27, "character": 2 } @@ -597,7 +597,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 37, "character": 2 } @@ -611,7 +611,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 37, "character": 2 } @@ -631,7 +631,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 17, "character": 2 } @@ -645,7 +645,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 17, "character": 2 } @@ -656,7 +656,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } } } @@ -670,7 +670,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 41, "character": 9 } @@ -684,7 +684,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 41, "character": 9 } @@ -762,7 +762,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } ], "name": "AsyncIterable", @@ -771,14 +771,14 @@ "implementationOf": { "type": "reference", "target": 86, - "name": "StreamResourceTransport.stream" + "name": "AgentTransport.stream" } } ], "implementationOf": { "type": "reference", "target": 85, - "name": "StreamResourceTransport.stream" + "name": "AgentTransport.stream" } } ], @@ -803,7 +803,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/transport/mock-stream.transport.ts", + "fileName": "libs/angular/src/lib/transport/mock-stream.transport.ts", "line": 3, "character": 13 } @@ -812,8 +812,8 @@ { "type": "reference", "target": 84, - "name": "StreamResourceTransport", - "package": "stream-resource" + "name": "AgentTransport", + "package": "angular" } ] }, @@ -1100,7 +1100,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 40, "character": 2 } @@ -1174,7 +1174,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 39, "character": 17 } @@ -1188,7 +1188,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 43, "character": 2 } @@ -1215,7 +1215,7 @@ }, { "id": 10, - "name": "StreamResourceConfig", + "name": "AgentConfig", "variant": "declaration", "kind": 256, "flags": {}, @@ -1230,7 +1230,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 5, "character": 2 } @@ -1250,7 +1250,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 6, "character": 2 } @@ -1258,8 +1258,8 @@ "type": { "type": "reference", "target": 84, - "name": "StreamResourceTransport", - "package": "stream-resource" + "name": "AgentTransport", + "package": "angular" } } ], @@ -1274,7 +1274,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 4, "character": 17 } @@ -1282,7 +1282,7 @@ }, { "id": 13, - "name": "StreamResourceOptions", + "name": "AgentOptions", "variant": "declaration", "kind": 256, "flags": {}, @@ -1295,7 +1295,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 66, "character": 2 } @@ -1313,7 +1313,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 67, "character": 2 } @@ -1333,7 +1333,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 75, "character": 2 } @@ -1353,7 +1353,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 70, "character": 2 } @@ -1370,8 +1370,8 @@ "type": "reference", "target": 14, "name": "T", - "package": "stream-resource", - "qualifiedName": "StreamResourceOptions.T", + "package": "angular", + "qualifiedName": "AgentOptions.T", "refersToTypeParameter": true } ], @@ -1389,7 +1389,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 71, "character": 2 } @@ -1409,7 +1409,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 69, "character": 2 } @@ -1461,7 +1461,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 76, "character": 2 } @@ -1484,7 +1484,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 68, "character": 2 } @@ -1538,7 +1538,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 72, "character": 2 } @@ -1567,7 +1567,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 73, "character": 2 } @@ -1625,7 +1625,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 74, "character": 2 } @@ -1633,8 +1633,8 @@ "type": { "type": "reference", "target": 84, - "name": "StreamResourceTransport", - "package": "stream-resource" + "name": "AgentTransport", + "package": "angular" } } ], @@ -1658,7 +1658,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 65, "character": 17 } @@ -1688,7 +1688,7 @@ }, { "id": 33, - "name": "StreamResourceRef", + "name": "AgentRef", "variant": "declaration", "kind": 256, "flags": {}, @@ -1701,7 +1701,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 113, "character": 2 } @@ -1720,7 +1720,7 @@ "type": "reference", "target": 101, "name": "SubagentStreamRef", - "package": "stream-resource" + "package": "angular" } } ], @@ -1736,7 +1736,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 107, "character": 2 } @@ -1766,7 +1766,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 95, "character": 2 } @@ -1796,7 +1796,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 121, "character": 2 } @@ -1902,7 +1902,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 122, "character": 2 } @@ -1967,7 +1967,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 96, "character": 2 } @@ -1997,7 +1997,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 108, "character": 2 } @@ -2020,8 +2020,8 @@ "type": "reference", "target": 34, "name": "T", - "package": "stream-resource", - "qualifiedName": "StreamResourceRef.T", + "package": "angular", + "qualifiedName": "AgentRef.T", "refersToTypeParameter": true } ], @@ -2042,7 +2042,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 101, "character": 2 } @@ -2072,8 +2072,8 @@ "type": "reference", "target": 35, "name": "ResolvedBag", - "package": "stream-resource", - "qualifiedName": "StreamResourceRef.ResolvedBag", + "package": "angular", + "qualifiedName": "AgentRef.ResolvedBag", "refersToTypeParameter": true } } @@ -2100,7 +2100,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 102, "character": 2 } @@ -2129,8 +2129,8 @@ "type": "reference", "target": 35, "name": "ResolvedBag", - "package": "stream-resource", - "qualifiedName": "StreamResourceRef.ResolvedBag", + "package": "angular", + "qualifiedName": "AgentRef.ResolvedBag", "refersToTypeParameter": true } } @@ -2152,7 +2152,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 94, "character": 2 } @@ -2182,7 +2182,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 109, "character": 2 } @@ -2212,7 +2212,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 119, "character": 2 } @@ -2287,7 +2287,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 100, "character": 2 } @@ -2360,7 +2360,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 97, "character": 2 } @@ -2397,7 +2397,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 120, "character": 2 } @@ -2447,7 +2447,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 93, "character": 2 } @@ -2483,7 +2483,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 117, "character": 2 } @@ -2532,7 +2532,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 112, "character": 2 } @@ -2561,7 +2561,7 @@ "type": "reference", "target": 101, "name": "SubagentStreamRef", - "package": "stream-resource" + "package": "angular" } ], "name": "Map", @@ -2580,7 +2580,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 116, "character": 2 } @@ -2620,8 +2620,8 @@ "type": "reference", "target": 35, "name": "ResolvedBag", - "package": "stream-resource", - "qualifiedName": "StreamResourceRef.ResolvedBag", + "package": "angular", + "qualifiedName": "AgentRef.ResolvedBag", "refersToTypeParameter": true } }, @@ -2719,7 +2719,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 118, "character": 2 } @@ -2778,7 +2778,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 104, "character": 2 } @@ -2817,7 +2817,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 103, "character": 2 } @@ -2856,7 +2856,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 92, "character": 2 } @@ -2873,8 +2873,8 @@ "type": "reference", "target": 34, "name": "T", - "package": "stream-resource", - "qualifiedName": "StreamResourceRef.T", + "package": "angular", + "qualifiedName": "AgentRef.T", "refersToTypeParameter": true } ], @@ -2915,7 +2915,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 90, "character": 17 } @@ -2945,7 +2945,7 @@ }, { "id": 84, - "name": "StreamResourceTransport", + "name": "AgentTransport", "variant": "declaration", "kind": 256, "flags": {}, @@ -2960,7 +2960,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 55, "character": 2 } @@ -2982,7 +2982,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 55, "character": 2 } @@ -3060,7 +3060,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } ], "name": "AsyncIterable", @@ -3077,7 +3077,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 47, "character": 2 } @@ -3091,7 +3091,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 47, "character": 2 } @@ -3169,7 +3169,7 @@ "type": "reference", "target": 97, "name": "StreamEvent", - "package": "stream-resource" + "package": "angular" } ], "name": "AsyncIterable", @@ -3190,7 +3190,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 46, "character": 17 } @@ -3204,7 +3204,7 @@ { "type": "reference", "target": 173, - "name": "MockStreamTransport" + "name": "MockAgentTransport" } ] }, @@ -3223,7 +3223,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 85, "character": 2 } @@ -3296,7 +3296,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 83, "character": 2 } @@ -3343,7 +3343,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 82, "character": 2 } @@ -3361,7 +3361,7 @@ "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 84, "character": 2 } @@ -3413,7 +3413,7 @@ ], "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 81, "character": 17 } @@ -5034,12 +5034,12 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 26, "character": 13 }, { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 35, "character": 12 } @@ -5074,12 +5074,12 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 26, "character": 13 }, { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 35, "character": 12 } @@ -5103,7 +5103,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 31, "character": 2 } @@ -5124,7 +5124,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 27, "character": 2 } @@ -5145,7 +5145,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 28, "character": 2 } @@ -5166,7 +5166,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 32, "character": 2 } @@ -5187,7 +5187,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 29, "character": 2 } @@ -5208,7 +5208,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.types.ts", + "fileName": "libs/angular/src/lib/angular.types.ts", "line": 30, "character": 2 } @@ -5247,7 +5247,7 @@ }, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 9, "character": 13 } @@ -5263,8 +5263,8 @@ { "type": "reference", "target": 10, - "name": "StreamResourceConfig", - "package": "stream-resource" + "name": "AgentConfig", + "package": "angular" } ], "name": "InjectionToken", @@ -5274,13 +5274,13 @@ }, { "id": 6, - "name": "provideStreamResource", + "name": "provideAgent", "variant": "declaration", "kind": 64, "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 12, "character": 16 } @@ -5288,13 +5288,13 @@ "signatures": [ { "id": 7, - "name": "provideStreamResource", + "name": "provideAgent", "variant": "signature", "kind": 4096, "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.provider.ts", + "fileName": "libs/angular/src/lib/angular.provider.ts", "line": 12, "character": 16 } @@ -5309,8 +5309,8 @@ "type": { "type": "reference", "target": 10, - "name": "StreamResourceConfig", - "package": "stream-resource" + "name": "AgentConfig", + "package": "angular" } } ], @@ -5329,13 +5329,13 @@ }, { "id": 1, - "name": "streamResource", + "name": "agent", "variant": "declaration", "kind": 64, "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.fn.ts", + "fileName": "libs/angular/src/lib/angular.fn.ts", "line": 26, "character": 16 } @@ -5343,13 +5343,13 @@ "signatures": [ { "id": 2, - "name": "streamResource", + "name": "agent", "variant": "signature", "kind": 4096, "flags": {}, "sources": [ { - "fileName": "libs/stream-resource/src/lib/stream-resource.fn.ts", + "fileName": "libs/angular/src/lib/angular.fn.ts", "line": 26, "character": 16 } @@ -5417,7 +5417,7 @@ "type": "reference", "target": 3, "name": "T", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true }, { @@ -5428,14 +5428,14 @@ "type": "reference", "target": 3, "name": "T", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true }, { "type": "reference", "target": 4, "name": "Bag", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true } ], @@ -5443,8 +5443,8 @@ "package": "@langchain/langgraph-sdk" } ], - "name": "StreamResourceOptions", - "package": "stream-resource" + "name": "AgentOptions", + "package": "angular" } } ], @@ -5456,7 +5456,7 @@ "type": "reference", "target": 3, "name": "T", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true }, { @@ -5467,14 +5467,14 @@ "type": "reference", "target": 3, "name": "T", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true }, { "type": "reference", "target": 4, "name": "Bag", - "package": "stream-resource", + "package": "angular", "refersToTypeParameter": true } ], @@ -5482,8 +5482,8 @@ "package": "@langchain/langgraph-sdk" } ], - "name": "StreamResourceRef", - "package": "stream-resource" + "name": "AgentRef", + "package": "angular" } } ] @@ -5534,537 +5534,537 @@ ] } ], - "packageName": "stream-resource", + "packageName": "angular", "readme": [ { "kind": "text", - "text": "# stream-resource\n\nThis library was generated with [Nx](https://nx.dev)." + "text": "# angular\n\nThis library was generated with [Nx](https://nx.dev)." } ], "symbolIdMap": { "0": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/public-api.ts", "qualifiedName": "" }, "1": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.fn.ts", - "qualifiedName": "streamResource" + "packageName": "angular", + "packagePath": "src/lib/angular.fn.ts", + "qualifiedName": "agent" }, "2": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.fn.ts", - "qualifiedName": "streamResource" + "packageName": "angular", + "packagePath": "src/lib/angular.fn.ts", + "qualifiedName": "agent" }, "3": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.fn.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.fn.ts", "qualifiedName": "T" }, "4": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.fn.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.fn.ts", "qualifiedName": "Bag" }, "5": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.fn.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.fn.ts", "qualifiedName": "options" }, "6": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", - "qualifiedName": "provideStreamResource" + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", + "qualifiedName": "provideAgent" }, "7": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", - "qualifiedName": "provideStreamResource" + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", + "qualifiedName": "provideAgent" }, "8": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", "qualifiedName": "config" }, "9": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", "qualifiedName": "STREAM_RESOURCE_CONFIG" }, "10": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", - "qualifiedName": "StreamResourceConfig" + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", + "qualifiedName": "AgentConfig" }, "11": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", - "qualifiedName": "StreamResourceConfig.apiUrl" + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", + "qualifiedName": "AgentConfig.apiUrl" }, "12": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.provider.ts", - "qualifiedName": "StreamResourceConfig.transport" + "packageName": "angular", + "packagePath": "src/lib/angular.provider.ts", + "qualifiedName": "AgentConfig.transport" }, "13": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions" }, "14": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.T" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.T" }, "15": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.ResolvedBag" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.ResolvedBag" }, "16": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.apiUrl" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.apiUrl" }, "17": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.assistantId" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.assistantId" }, "18": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.threadId" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.threadId" }, "19": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.onThreadId" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.onThreadId" }, "20": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "21": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "22": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "id" }, "23": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.initialValues" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.initialValues" }, "24": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.messagesKey" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.messagesKey" }, "25": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.throttle" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.throttle" }, "26": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.toMessage" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.toMessage" }, "27": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "28": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "29": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "msg" }, "30": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.transport" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.transport" }, "31": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.filterSubagentMessages" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.filterSubagentMessages" }, "32": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceOptions.subagentToolNames" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentOptions.subagentToolNames" }, "33": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef" }, "34": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.T" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.T" }, "35": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.ResolvedBag" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.ResolvedBag" }, "36": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.value" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.value" }, "37": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.status" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.status" }, "38": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.isLoading" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.isLoading" }, "39": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.error" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.error" }, "40": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.hasValue" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.hasValue" }, "41": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.reload" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.reload" }, "42": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "43": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "44": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.messages" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.messages" }, "45": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.interrupt" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.interrupt" }, "46": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.interrupts" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.interrupts" }, "47": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.toolProgress" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.toolProgress" }, "48": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.toolCalls" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.toolCalls" }, "49": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.branch" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.branch" }, "50": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.history" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.history" }, "51": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.isThreadLoading" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.isThreadLoading" }, "52": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.subagents" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.subagents" }, "53": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.activeSubagents" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.activeSubagents" }, "54": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.submit" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.submit" }, "55": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "56": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "57": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "values" }, "58": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "opts" }, "59": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.stop" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.stop" }, "60": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "61": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "62": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.switchThread" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.switchThread" }, "63": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "64": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "65": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "threadId" }, "66": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.joinStream" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.joinStream" }, "67": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "68": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "69": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "runId" }, "70": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "lastEventId" }, "71": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.setBranch" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.setBranch" }, "72": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "73": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "74": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "branch" }, "75": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.getMessagesMetadata" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.getMessagesMetadata" }, "76": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "77": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "78": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "msg" }, "79": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "idx" }, "80": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceRef.getToolCalls" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentRef.getToolCalls" }, "81": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "82": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__type" }, "83": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "msg" }, "84": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceTransport" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentTransport" }, "85": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceTransport.stream" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentTransport.stream" }, "86": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceTransport.stream" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentTransport.stream" }, "87": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "assistantId" }, "88": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "threadId" }, "89": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "payload" }, "90": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "signal" }, "91": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceTransport.joinStream" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentTransport.joinStream" }, "92": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", - "qualifiedName": "StreamResourceTransport.joinStream" + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", + "qualifiedName": "AgentTransport.joinStream" }, "93": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "threadId" }, "94": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "runId" }, "95": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "lastEventId" }, "96": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "signal" }, "97": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "StreamEvent" }, "98": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "StreamEvent.type" }, "99": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "StreamEvent.__index" }, "101": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "SubagentStreamRef" }, "102": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "SubagentStreamRef.toolCallId" }, "103": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "SubagentStreamRef.status" }, "104": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "SubagentStreamRef.values" }, "105": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "SubagentStreamRef.messages" }, "106": { @@ -6148,7 +6148,7 @@ "qualifiedName": "Interrupt.when" }, "123": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "", "qualifiedName": "__type" }, @@ -6353,266 +6353,266 @@ "qualifiedName": "run" }, "164": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "ResourceStatus" }, "165": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object" }, "166": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Idle" }, "167": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Loading" }, "168": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Reloading" }, "169": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Resolved" }, "170": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Error" }, "171": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "__object.Local" }, "172": { - "packageName": "stream-resource", - "packagePath": "src/lib/stream-resource.types.ts", + "packageName": "angular", + "packagePath": "src/lib/angular.types.ts", "qualifiedName": "ResourceStatus" }, "173": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport" + "qualifiedName": "MockAgentTransport" }, "174": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.__constructor" + "qualifiedName": "MockAgentTransport.__constructor" }, "175": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport" + "qualifiedName": "MockAgentTransport" }, "176": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "script" }, "186": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.nextBatch" + "qualifiedName": "MockAgentTransport.nextBatch" }, "187": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.nextBatch" + "qualifiedName": "MockAgentTransport.nextBatch" }, "188": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.emit" + "qualifiedName": "MockAgentTransport.emit" }, "189": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.emit" + "qualifiedName": "MockAgentTransport.emit" }, "190": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "events" }, "191": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.emitError" + "qualifiedName": "MockAgentTransport.emitError" }, "192": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.emitError" + "qualifiedName": "MockAgentTransport.emitError" }, "193": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "err" }, "194": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.close" + "qualifiedName": "MockAgentTransport.close" }, "195": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.close" + "qualifiedName": "MockAgentTransport.close" }, "196": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.isStreaming" + "qualifiedName": "MockAgentTransport.isStreaming" }, "197": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.isStreaming" + "qualifiedName": "MockAgentTransport.isStreaming" }, "198": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.stream" + "qualifiedName": "MockAgentTransport.stream" }, "199": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", - "qualifiedName": "MockStreamTransport.stream" + "qualifiedName": "MockAgentTransport.stream" }, "200": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "_assistantId" }, "201": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "_threadId" }, "202": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "_payload" }, "203": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/mock-stream.transport.ts", "qualifiedName": "signal" }, "206": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport" }, "207": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport.__constructor" }, "208": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport" }, "209": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "apiUrl" }, "210": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "onThreadId" }, "211": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "__type" }, "212": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "__type" }, "213": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "id" }, "219": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport.stream" }, "220": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport.stream" }, "221": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "assistantId" }, "222": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "threadId" }, "223": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "payload" }, "224": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "signal" }, "225": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport.joinStream" }, "226": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "FetchStreamTransport.joinStream" }, "227": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "threadId" }, "228": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "runId" }, "229": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "lastEventId" }, "230": { - "packageName": "stream-resource", + "packageName": "angular", "packagePath": "src/lib/transport/fetch-stream.transport.ts", "qualifiedName": "signal" } }, "files": { "entries": { - "1": "libs/stream-resource/src/public-api.ts", - "2": "libs/stream-resource/README.md", - "3": "libs/stream-resource" + "1": "libs/angular/src/public-api.ts", + "2": "libs/angular/README.md", + "3": "libs/angular" }, "reflections": { "1": 0, diff --git a/apps/website/public/whitepaper-preview.html b/apps/website/public/whitepaper-preview.html index 4a840fd55..e5cfc533c 100644 --- a/apps/website/public/whitepaper-preview.html +++ b/apps/website/public/whitepaper-preview.html @@ -20,7 +20,7 @@
-
StreamResource · Production Readiness Guide
+
Agent · Production Readiness Guide

From Prototype
to Production

The Angular Agent Readiness Guide

cacheplane.io · 2026
@@ -65,10 +65,10 @@

Overview

When you move from prototype to production, the requirements change fundamentally. What worked in a demo — direct API calls, synchronous state, manual zone management — falls apart at scale.

The Signals-Native Approach

-

StreamResource provides a signals-native approach that eliminates the boilerplate:

+

Agent provides a signals-native approach that eliminates the boilerplate:

@Component({...})
 export class ChatComponent {
-  chat = streamResource<{ messages: BaseMessage[] }>({
+  chat = agent<{ messages: BaseMessage[] }>({
     assistantId: 'chat_agent',
   });
 }
@@ -84,7 +84,7 @@ 

Overview

Demos work with ephemeral state. Production agents need conversation history that survives page refreshes, tab switches, and navigation — wired to LangGraph's MemorySaver backend.

The threadId Pattern

-
provideStreamResource({
+
provideAgent({
   apiUrl: 'http://localhost:2024',
   threadId: signal(localStorage.getItem('threadId')),
   onThreadId: (id) => localStorage.setItem('threadId', id),
@@ -150,8 +150,8 @@ 

Production Checklist

Deterministic Testing

Overview

Agent UIs are notoriously hard to test because they depend on live LLM responses. Flaky tests, slow CI, and inability to reproduce edge cases are the main reasons agent UIs ship with low confidence.

-

The MockStreamTransport Approach

-
const ref = createMockStreamResourceRef();
+

The MockAgentTransport Approach

+
const ref = createMockAgentRef();
 ref.messages.set([{ role: 'assistant', content: 'Hello' }]);
 ref.isStreaming.set(false);
 expect(fixture.nativeElement.querySelector('.message').textContent)
@@ -160,7 +160,7 @@ 

The MockStreamTransport Approach

Production Checklist

  • Do your agent component tests run offline and complete in under 100ms each?
  • Are streaming, interrupts, tool calls, and generative UI all tested in isolation?
  • -
  • Is MockStreamTransport used instead of mocking streamResource() itself?
+
  • Is MockAgentTransport used instead of mocking agent() itself?
  • diff --git a/apps/website/scripts/generate-agent-context.ts b/apps/website/scripts/generate-agent-context.ts index da65c52ae..5eecd23b2 100644 --- a/apps/website/scripts/generate-agent-context.ts +++ b/apps/website/scripts/generate-agent-context.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; // Read version from library package.json (not website) -const libPkgPath = path.join(__dirname, '..', '..', '..', 'libs', 'stream-resource', 'package.json'); +const libPkgPath = path.join(__dirname, '..', '..', '..', 'libs', 'angular', 'package.json'); let version = '0.1.0'; if (fs.existsSync(libPkgPath)) { const libPkg = JSON.parse(fs.readFileSync(libPkgPath, 'utf8')) as { version?: string }; diff --git a/apps/website/scripts/generate-api-docs.ts b/apps/website/scripts/generate-api-docs.ts index 48d8f2848..bc35ece81 100644 --- a/apps/website/scripts/generate-api-docs.ts +++ b/apps/website/scripts/generate-api-docs.ts @@ -120,8 +120,8 @@ function reflectionToEntry(ref: any): ApiDocEntry | null { async function main() { const candidates = [ - 'libs/stream-resource/src/public-api.ts', - 'packages/stream-resource/src/public-api.ts', + 'libs/angular/src/public-api.ts', + 'packages/angular/src/public-api.ts', ]; const entryPoint = candidates.find((p) => fs.existsSync(p)); if (!entryPoint) { diff --git a/apps/website/scripts/generate-narrative-docs.ts b/apps/website/scripts/generate-narrative-docs.ts index 537f93376..11180b1ba 100644 --- a/apps/website/scripts/generate-narrative-docs.ts +++ b/apps/website/scripts/generate-narrative-docs.ts @@ -10,23 +10,23 @@ const API_DOCS = 'apps/website/public/api-docs.json'; const TOPICS = [ { slug: 'introduction', - prompt: 'Write an introduction to the Angular Stream Resource library. Explain what it does, who it is for, and why it exists. Include a minimal getting-started example.', + prompt: 'Write an introduction to the Angular Agent Framework library. Explain what it does, who it is for, and why it exists. Include a minimal getting-started example.', }, { slug: 'streaming', - prompt: 'Explain how token-by-token streaming works with streamResource(). Cover the messages signal, how chunks arrive, and how Angular re-renders on each chunk.', + prompt: 'Explain how token-by-token streaming works with agent(). Cover the messages signal, how chunks arrive, and how Angular re-renders on each chunk.', }, { slug: 'thread-persistence', - prompt: 'Explain thread persistence in streamResource(). Cover threadId, onThreadId, and how to resume threads across page refreshes with localStorage.', + prompt: 'Explain thread persistence in agent(). Cover threadId, onThreadId, and how to resume threads across page refreshes with localStorage.', }, { slug: 'configuration', - prompt: 'Explain provideStreamResource() and per-call configuration. Show how to set a global apiUrl and how to override it per-call.', + prompt: 'Explain provideAgent() and per-call configuration. Show how to set a global apiUrl and how to override it per-call.', }, { slug: 'testing', - prompt: 'Explain how to unit test components that use streamResource() with MockStreamTransport. Show a complete test example.', + prompt: 'Explain how to unit test components that use agent() with MockAgentTransport. Show a complete test example.', }, ]; @@ -36,7 +36,7 @@ async function generateDoc(slug: string, prompt: string, apiDocsJson: string): P max_tokens: 2048, messages: [{ role: 'user', - content: `You are writing documentation for the Angular Stream Resource library. + content: `You are writing documentation for the Angular Agent Framework library. Here is the TypeDoc API reference JSON:\n\n${apiDocsJson}\n\n${prompt} Write clean, developer-friendly MDX documentation. Use precise, no-fluff prose. Include code examples. Start with a single # heading.`, diff --git a/apps/website/scripts/generate-whitepaper.ts b/apps/website/scripts/generate-whitepaper.ts index 07abe0ed8..45a1b7bdd 100644 --- a/apps/website/scripts/generate-whitepaper.ts +++ b/apps/website/scripts/generate-whitepaper.ts @@ -21,9 +21,9 @@ Context: Angular teams building LangGraph-powered agents must wire SSE event str Cover: - Why streaming state is hard in Angular (zone.js, change detection, timing) -- The signals-native approach: how streamResource() exposes messages() as Signal +- The signals-native approach: how agent() exposes messages() as Signal - How isStreaming() lets developers drive loading UI without polling -- Code example: minimal streamResource() setup (TypeScript snippet, 8-12 lines) +- Code example: minimal agent() setup (TypeScript snippet, 8-12 lines) - Production checklist item: "Are your message signals OnPush-compatible?" Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engineers.`, @@ -42,7 +42,7 @@ Cover: - The threadId signal and onThreadId callback pattern - How to persist threadId to localStorage and restore on mount - Thread list UI and switching between conversations -- Code example: provideStreamResource() with threadId (8-12 lines) +- Code example: provideAgent() with threadId (8-12 lines) - Production checklist item: "Does your agent UI resume threads correctly after a browser refresh?" Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engineers.`, @@ -78,7 +78,7 @@ Context: Production agents that take consequential actions — sending emails, d Cover: - The LangGraph interrupt() and Command.RESUME pattern - Why polling and custom websocket approaches are brittle -- The interrupt() signal in streamResource() and how it maps to approval state +- The interrupt() signal in agent() and how it maps to approval state - headless and prebuilt - The three approval actions: approve, edit, cancel — and how each maps to a resume command - Code example: interrupt signal binding (8-12 lines) @@ -116,10 +116,10 @@ Context: Agent UIs are notoriously hard to test because they depend on live LLM Cover: - Why testing agent components against real LLM APIs is impractical -- The MockStreamTransport approach: scripted event sequences, no server needed -- createMockStreamResourceRef(): writable signals you control directly in tests +- The MockAgentTransport approach: scripted event sequences, no server needed +- createMockAgentRef(): writable signals you control directly in tests - How to test streaming, interrupts, tool calls, and generative UI in isolation -- Code example: createMockStreamResourceRef() test pattern (10-14 lines) +- Code example: createMockAgentRef() test pattern (10-14 lines) - Production checklist item: "Do your agent component tests run offline and complete in under 100ms each?" Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engineers.`, @@ -181,7 +181,7 @@ function buildHTML(chapters: Array<{ title: string; content: string }>): string
    -
    StreamResource · Production Readiness Guide
    +
    Agent · Production Readiness Guide

    From Prototype
    to Production

    The Angular Agent Readiness Guide

    cacheplane.io · ${new Date().getFullYear()}
    @@ -230,7 +230,7 @@ async function generateChapter(chapter: typeof CHAPTERS[0]): Promise { // ── Main ───────────────────────────────────────────────────────────────── async function main() { - console.log('StreamResource White Paper Generator\n'); + console.log('Agent White Paper Generator\n'); console.log(`Model: ${MODEL}`); console.log(`Output: ${OUTPUT_PDF}\n`); diff --git a/apps/website/src/app/api/newsletter/route.ts b/apps/website/src/app/api/newsletter/route.ts index de8ae91a0..dda0e469d 100644 --- a/apps/website/src/app/api/newsletter/route.ts +++ b/apps/website/src/app/api/newsletter/route.ts @@ -22,7 +22,7 @@ export async function POST(req: NextRequest) { sendEmail({ from: FROM, to: email, - subject: 'Welcome to Angular Stream Resource updates', + subject: 'Welcome to Angular Agent Framework updates', html: newsletterWelcomeHtml(), }), addToAudience(email), diff --git a/apps/website/src/app/docs/[[...slug]]/page.tsx b/apps/website/src/app/docs/[[...slug]]/page.tsx index e61f2eac2..5a8803c95 100644 --- a/apps/website/src/app/docs/[[...slug]]/page.tsx +++ b/apps/website/src/app/docs/[[...slug]]/page.tsx @@ -22,10 +22,10 @@ function loadApiDocs(): ApiDocEntry[] { } const API_NAME_MAP: Record = { - 'stream-resource': 'streamResource', - 'provide-stream-resource': 'provideStreamResource', + 'angular': 'agent', + 'provide-angular': 'provideAgent', 'fetch-stream-transport': 'FetchStreamTransport', - 'mock-stream-transport': 'MockStreamTransport', + 'mock-stream-transport': 'MockAgentTransport', }; export function generateStaticParams() { diff --git a/apps/website/src/app/layout.tsx b/apps/website/src/app/layout.tsx index 14c5d09a6..94d186adf 100644 --- a/apps/website/src/app/layout.tsx +++ b/apps/website/src/app/layout.tsx @@ -22,17 +22,17 @@ const mono = JetBrains_Mono({ }); export const metadata: Metadata = { - title: 'Angular Stream Resource — Signal-Native Streaming for Angular + LangGraph', + title: 'Angular Agent Framework — Signal-Native Streaming for Angular + LangGraph', description: 'The Enterprise Streaming Resource for LangChain and Angular. Signal-native streaming, thread persistence, and production patterns for Angular 20+.', openGraph: { - title: 'Angular Stream Resource', + title: 'Angular Agent Framework', description: 'Signal-native streaming for LangGraph — production patterns your Angular team can own.', type: 'website', - siteName: 'Angular Stream Resource', + siteName: 'Angular Agent Framework', }, twitter: { card: 'summary_large_image', - title: 'Angular Stream Resource', + title: 'Angular Agent Framework', description: 'Signal-native streaming for LangGraph — production patterns your Angular team can own.', }, }; diff --git a/apps/website/src/app/llms-full.txt/route.ts b/apps/website/src/app/llms-full.txt/route.ts index 2f0627744..d0f2672fe 100644 --- a/apps/website/src/app/llms-full.txt/route.ts +++ b/apps/website/src/app/llms-full.txt/route.ts @@ -27,21 +27,21 @@ function loadAllPrompts(): string { export async function GET() { const sections = [ - '# Angular Stream Resource — Full Reference\n\nSee /llms.txt for a compact summary.\n', + '# Angular Agent Framework — Full Reference\n\nSee /llms.txt for a compact summary.\n', '## API Reference (TypeDoc)\n\n' + loadApiDocs(), '## Prompt Recipes\n\n' + loadAllPrompts(), [ '## Common Gotchas', '', - 'streamResource() MUST be called inside an Angular injection context.', + 'agent() MUST be called inside an Angular injection context.', 'Do not call it in ngOnInit — use constructor or field initializer.', - 'Do not mock streamResource() in tests — use MockStreamTransport.', + 'Do not mock agent() in tests — use MockAgentTransport.', 'RxJS is an internal implementation detail — do not import rxjs in consumer code.', ].join('\n'), [ '## MCP server', '', - 'npx @cacheplane/stream-resource-mcp', + 'npx @cacheplane/angular-mcp', 'Add to Claude Code settings.json, Cursor .cursor/mcp.json, or any MCP-compatible agent.', ].join('\n'), ]; diff --git a/apps/website/src/app/llms.txt/route.ts b/apps/website/src/app/llms.txt/route.ts index 0eee65125..de348aac3 100644 --- a/apps/website/src/app/llms.txt/route.ts +++ b/apps/website/src/app/llms.txt/route.ts @@ -5,30 +5,30 @@ function buildLlmsTxt(): string { // Inline version — updated by publish workflow const version = '0.1.0'; return [ - `# Angular Stream Resource v${version}`, + `# Angular Agent Framework v${version}`, '', - "Angular Stream Resource — the enterprise streaming library for LangChain/LangGraph. Provides streamResource() — full parity with React's useStream() hook, built on Angular Signals.", + "Angular Agent Framework — the enterprise streaming library for LangChain/LangGraph. Provides agent() — full parity with React's useStream() hook, built on Angular Signals.", '', '## Install', - 'npm install @cacheplane/stream-resource', + 'npm install @cacheplane/angular', '', '## Key API', - '- streamResource(options): StreamResourceRef — call in Angular injection context (constructor or field initializer)', - '- provideStreamResource(config): Provider — register in app.config.ts for global defaults', - "- StreamResourceRef.messages(): Signal — updates token by token", - '- StreamResourceRef.submit(values): Promise — send a message / trigger a run', - "- StreamResourceRef.status(): Signal<'idle'|'loading'|'resolved'|'error'>", - '- StreamResourceRef.threadId signal + onThreadId callback — thread persistence across refreshes', - '- MockStreamTransport — deterministic unit testing without a real server', + '- agent(options): AgentRef — call in Angular injection context (constructor or field initializer)', + '- provideAgent(config): Provider — register in app.config.ts for global defaults', + "- AgentRef.messages(): Signal — updates token by token", + '- AgentRef.submit(values): Promise — send a message / trigger a run', + "- AgentRef.status(): Signal<'idle'|'loading'|'resolved'|'error'>", + '- AgentRef.threadId signal + onThreadId callback — thread persistence across refreshes', + '- MockAgentTransport — deterministic unit testing without a real server', '', '## Minimal example', - "import { streamResource } from '@cacheplane/stream-resource';", - "const chat = streamResource({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024' });", + "import { agent } from '@cacheplane/angular';", + "const chat = agent({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024' });", '// Template: @for (msg of chat.messages(); track $index) {

    {{ msg.content }}

    }', "// Submit: chat.submit({ messages: [{ role: 'human', content: input }] })", '', '## MCP server', - 'npx @cacheplane/stream-resource-mcp', + 'npx @cacheplane/angular-mcp', '', '## Full reference', 'https://stream-resource.dev/llms-full.txt', diff --git a/apps/website/src/app/page.tsx b/apps/website/src/app/page.tsx index 99b8f83bf..daf63b17e 100644 --- a/apps/website/src/app/page.tsx +++ b/apps/website/src/app/page.tsx @@ -41,7 +41,7 @@ export default async function HomePage() { {/* 7. Depth — capability showcases */} - {/* 8. Fair comparison — honest LangChain + Angular Stream Resource table */} + {/* 8. Fair comparison — honest LangChain + Angular Agent Framework table */} {/* 9. White paper free download */} diff --git a/apps/website/src/app/pilot-to-prod/page.tsx b/apps/website/src/app/pilot-to-prod/page.tsx index d2b23ba64..8234bdb95 100644 --- a/apps/website/src/app/pilot-to-prod/page.tsx +++ b/apps/website/src/app/pilot-to-prod/page.tsx @@ -9,7 +9,7 @@ import { PilotFooterCTA } from '../../components/landing/PilotFooterCTA'; import { tokens } from '../../../lib/design-tokens'; export const metadata = { - title: 'Pilot to Production — Angular Stream Resource', + title: 'Pilot to Production — Angular Agent Framework', description: 'Close the last-mile gap. Purchase an app deployment license and we work alongside your Angular team for 3 months to ship your first agent to production.', }; diff --git a/apps/website/src/components/docs/ArchFlowDiagram.tsx b/apps/website/src/components/docs/ArchFlowDiagram.tsx index bef621fd7..c29428356 100644 --- a/apps/website/src/components/docs/ArchFlowDiagram.tsx +++ b/apps/website/src/components/docs/ArchFlowDiagram.tsx @@ -95,7 +95,7 @@ export function ArchFlowDiagram() {
    - streamResource() — live architecture flow + agent() — live architecture flow localhost:4200
    diff --git a/apps/website/src/components/landing/ArchDiagram.tsx b/apps/website/src/components/landing/ArchDiagram.tsx index 6155403d7..63f1c2022 100644 --- a/apps/website/src/components/landing/ArchDiagram.tsx +++ b/apps/website/src/components/landing/ArchDiagram.tsx @@ -18,13 +18,13 @@ const NODES: NodeDef[] = [ id: 'angular', label: 'Angular App', subtitle: 'Components & Signals', - description: 'Your Angular components call streamResource() and bind the returned Signals directly in templates. OnPush change detection handles re-renders automatically.', + description: 'Your Angular components call agent() and bind the returned Signals directly in templates. OnPush change detection handles re-renders automatically.', side: 'angular', icon: '🅰️', }, { id: 'sr', - label: 'streamResource()', + label: 'agent()', subtitle: 'Reactive Bridge', description: 'The core primitive. Creates a reactive resource that exposes messages, status, error, and threadId as Angular Signals. Manages the full agent lifecycle — streaming, interrupts, branching, and thread persistence.', side: 'bridge', @@ -34,7 +34,7 @@ const NODES: NodeDef[] = [ id: 'transport', label: 'FetchStreamTransport', subtitle: 'SSE Connection', - description: 'Handles the HTTP/SSE transport layer. Opens a server-sent events connection to LangGraph Cloud, parses streaming chunks, and feeds them into the resource. Swappable with MockStreamTransport for testing.', + description: 'Handles the HTTP/SSE transport layer. Opens a server-sent events connection to LangGraph Cloud, parses streaming chunks, and feeds them into the resource. Swappable with MockAgentTransport for testing.', side: 'bridge', icon: '📡', }, @@ -119,7 +119,7 @@ export function ArchDiagram() { maxWidth: '50ch', margin: '0 auto 64px', lineHeight: 1.6, - }}>Click any component to learn how data flows from your Angular app through streamResource to LangGraph and back.

    + }}>Click any component to learn how data flows from your Angular app through agent to LangGraph and back.

    {/* Left: vertical node stack */} diff --git a/apps/website/src/components/landing/ChatFeaturesSection.tsx b/apps/website/src/components/landing/ChatFeaturesSection.tsx index 8f97bd22b..0d26a5c9e 100644 --- a/apps/website/src/components/landing/ChatFeaturesSection.tsx +++ b/apps/website/src/components/landing/ChatFeaturesSection.tsx @@ -48,7 +48,7 @@ async function runStream(ctx: ScenarioCtx) { const { out, cur } = makeAIBubble(); litRight(0); await typeText(out, cur, - 'LangGraph structures your agent as a graph of nodes and edges. Each node returns a partial state update. Angular Stream Resource connects to that stream and exposes each update as Angular signals — so your template reacts as tokens arrive.', + 'LangGraph structures your agent as a graph of nodes and edges. Each node returns a partial state update. Angular Agent Framework connects to that stream and exposes each update as Angular signals — so your template reacts as tokens arrive.', 30 ); if (ctx.token !== token) return; diff --git a/apps/website/src/components/landing/CodeBlock.tsx b/apps/website/src/components/landing/CodeBlock.tsx index a114cfd78..c26b3fb03 100644 --- a/apps/website/src/components/landing/CodeBlock.tsx +++ b/apps/website/src/components/landing/CodeBlock.tsx @@ -2,10 +2,10 @@ import { codeToHtml } from 'shiki'; import { tokens } from '@cacheplane/design-tokens'; const EXAMPLE = `// app.config.ts -provideStreamResource({ apiUrl: 'http://localhost:2024' }) +provideAgent({ apiUrl: 'http://localhost:2024' }) // chat.component.ts -const chat = streamResource<{ messages: BaseMessage[] }>({ +const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: signal(this.threadId), onThreadId: (id) => localStorage.setItem('threadId', id), diff --git a/apps/website/src/components/landing/DeepAgentsShowcase.tsx b/apps/website/src/components/landing/DeepAgentsShowcase.tsx index 05a3ffc25..7566fb788 100644 --- a/apps/website/src/components/landing/DeepAgentsShowcase.tsx +++ b/apps/website/src/components/landing/DeepAgentsShowcase.tsx @@ -8,7 +8,7 @@ const CAPABILITIES = [ title: 'Planning', description: 'Turn high-level goals into ordered action sequences with explicit constraints and checkpoints. The agent chooses next steps grounded in real context.', code: `// Agent plans and executes steps -const planner = streamResource({ +const planner = agent({ assistantId: 'planning_agent', }); @@ -25,7 +25,7 @@ const planner = streamResource({ title: 'Subagents', description: 'Split complex tasks into focused workers with clear ownership boundaries. Each subagent handles a specialized piece and reports back.', code: `// Orchestrator delegates to subagents -const orchestrator = streamResource({ +const orchestrator = agent({ assistantId: 'orchestrator', }); @@ -42,7 +42,7 @@ const activeWorkers = computed(() => title: 'Skills', description: 'Package repeatable agent behavior into focused, reusable instruction sets. Skills define scope, response format, and operational boundaries.', code: `// Agent uses a skill for code review -const reviewer = streamResource({ +const reviewer = agent({ assistantId: 'code_review_skill', input: { files: changedFiles(), @@ -60,7 +60,7 @@ const issues = reviewer.messages() title: 'Memory', description: 'Retain useful intermediate context across agent turns without leaking irrelevant history. Memory shapes routing and improves response quality over time.', code: `// Agent with persistent memory -const agent = streamResource({ +const agent = agent({ assistantId: 'memory_agent', threadId: signal(userId()), }); diff --git a/apps/website/src/components/landing/FairComparisonSection.tsx b/apps/website/src/components/landing/FairComparisonSection.tsx index 31678b637..13417438d 100644 --- a/apps/website/src/components/landing/FairComparisonSection.tsx +++ b/apps/website/src/components/landing/FairComparisonSection.tsx @@ -6,7 +6,7 @@ const ROWS = [ { capability: 'Token streaming', without: 'Custom SSE wiring + zone management', - with: 'streamResource() signal, zero boilerplate', + with: 'agent() signal, zero boilerplate', }, { capability: 'Thread persistence', @@ -31,7 +31,7 @@ const ROWS = [ { capability: 'Deterministic testing', without: 'Mock HTTP + tick management', - with: 'MockStreamTransport + writable signals', + with: 'MockAgentTransport + writable signals', }, { capability: 'Human approval UI', @@ -67,7 +67,7 @@ export function FairComparisonSection() { fontSize: 'clamp(26px,3.5vw,46px)', fontWeight: 800, lineHeight: 1.1, color: tokens.colors.textPrimary, marginBottom: 12, }}> - What Angular Stream Resource adds + What Angular Agent Framework adds

    - {['Capability', '@langchain/langgraph-sdk', 'With Angular Stream Resource'].map((h, i) => ( + {['Capability', '@langchain/langgraph-sdk', 'With Angular Agent Framework'].map((h, i) => (

    - With Angular Stream Resource + With Angular Agent Framework {row.with} diff --git a/apps/website/src/components/landing/FeatureStrip.tsx b/apps/website/src/components/landing/FeatureStrip.tsx index 17f880b1b..a60b82b27 100644 --- a/apps/website/src/components/landing/FeatureStrip.tsx +++ b/apps/website/src/components/landing/FeatureStrip.tsx @@ -6,7 +6,7 @@ const FEATURES = [ { icon: '\u26A1', title: 'Token-by-token streaming', desc: 'Real-time SSE streaming via FetchStreamTransport. Messages update as each token arrives.' }, { icon: '\uD83D\uDD17', title: 'Thread persistence', desc: 'MemorySaver-backed threads survive page refreshes via threadId signal and onThreadId callback.' }, { icon: '\uD83D\uDCD0', title: 'Angular Signals', desc: 'Every state slice is an Angular Signal. Works with OnPush, async pipe, and computed().' }, - { icon: '\uD83E\uDDEA', title: 'MockStreamTransport', desc: 'Deterministic unit testing. Script event sequences and step through them in your specs.' }, + { icon: '\uD83E\uDDEA', title: 'MockAgentTransport', desc: 'Deterministic unit testing. Script event sequences and step through them in your specs.' }, { icon: '\uD83C\uDFE2', title: 'Source-available licensing', desc: 'Free for noncommercial use under PolyForm Noncommercial 1.0.0. Commercial license at $500/seat/year or $2,000/app deployment.' }, ]; diff --git a/apps/website/src/components/landing/FullStackSection.tsx b/apps/website/src/components/landing/FullStackSection.tsx index 511d19afa..7ef99abc4 100644 --- a/apps/website/src/components/landing/FullStackSection.tsx +++ b/apps/website/src/components/landing/FullStackSection.tsx @@ -6,15 +6,15 @@ const LAYERS = [ { id: 'sr', tag: 'Primitives', - pkg: '@cacheplane/stream-resource', + pkg: '@cacheplane/angular', color: tokens.colors.accent, rgb: '0,64,144', bg: 'rgba(0,64,144,0.05)', border: 'rgba(0,64,144,0.25)', outcome: 'Ship streaming agents without building the plumbing.', problem: 'Wiring SSE into Angular requires weeks of zone patching, manual subscription management, and custom thread-persistence code — most of which breaks under load or after a page refresh.', - solution: 'streamResource() gives your team production-ready streaming, thread persistence, interrupt handling, and a deterministic test transport on day one.', - chips: ['streamResource()', 'messages()', 'interrupt()', 'time travel', 'MockStreamTransport'], + solution: 'agent() gives your team production-ready streaming, thread persistence, interrupt handling, and a deterministic test transport on day one.', + chips: ['agent()', 'messages()', 'interrupt()', 'time travel', 'MockAgentTransport'], connLabel: 'AIMessage stream', connColor: 'rgba(0,64,144,.22)', connFill: '#004090', diff --git a/apps/website/src/components/landing/GenerativeUIFrame.tsx b/apps/website/src/components/landing/GenerativeUIFrame.tsx index b97cd2163..b3a9e1469 100644 --- a/apps/website/src/components/landing/GenerativeUIFrame.tsx +++ b/apps/website/src/components/landing/GenerativeUIFrame.tsx @@ -27,7 +27,7 @@ export function GenerativeUIFrame() {
    - npm install @cacheplane/stream-resource + npm install @cacheplane/angular
    diff --git a/apps/website/src/components/landing/HowItWorks.tsx b/apps/website/src/components/landing/HowItWorks.tsx index 3597567b5..68be290b5 100644 --- a/apps/website/src/components/landing/HowItWorks.tsx +++ b/apps/website/src/components/landing/HowItWorks.tsx @@ -17,7 +17,7 @@ const phases: Phase[] = [ number: 1, title: 'Integration Sprint', description: - 'We install stream-resource into your Angular workspace, wire it to your LangGraph backend, and ship your first streamed response. Your team sees tokens flowing within days.', + 'We install angular into your Angular workspace, wire it to your LangGraph backend, and ship your first streamed response. Your team sees tokens flowing within days.', deliverable: '✓ First stream live', }, { diff --git a/apps/website/src/components/landing/LangGraphShowcase.tsx b/apps/website/src/components/landing/LangGraphShowcase.tsx index 8e53411b7..6aa799fb3 100644 --- a/apps/website/src/components/landing/LangGraphShowcase.tsx +++ b/apps/website/src/components/landing/LangGraphShowcase.tsx @@ -8,7 +8,7 @@ const CAPABILITIES = [ title: 'Streaming', description: 'Surface intermediate progress while the graph runs. Token-by-token updates arrive via SSE and land directly in Angular Signals.', code: `// Token-by-token streaming -const chat = streamResource({ +const chat = agent({ assistantId: 'chat_agent', }); @@ -25,7 +25,7 @@ const chat = streamResource({ title: 'Persistence', description: 'Execution state survives retries and resumptions. Thread-based checkpoint recovery means users never lose their conversation.', code: `// Thread persistence across sessions -const chat = streamResource({ +const chat = agent({ assistantId: 'agent', threadId: signal(localStorage.getItem('tid')), onThreadId: (id) => { @@ -39,7 +39,7 @@ const chat = streamResource({ title: 'Interrupts', description: 'Pause execution for human decisions \u2014 approvals, confirmations, corrections. Resume without losing any context or state.', code: `// Human-in-the-loop approval -const agent = streamResource({ +const agent = agent({ assistantId: 'approval_agent', onInterrupt: (data) => { this.approval.set(data); diff --git a/apps/website/src/components/landing/PilotFooterCTA.tsx b/apps/website/src/components/landing/PilotFooterCTA.tsx index 6610558f4..9490f3d1d 100644 --- a/apps/website/src/components/landing/PilotFooterCTA.tsx +++ b/apps/website/src/components/landing/PilotFooterCTA.tsx @@ -74,7 +74,7 @@ export function PilotFooterCTA() { marginBottom: '2.5rem', }} > - Half of GenAI projects die after proof of concept. Angular Stream Resource closes the gap. Start with a conversation. + Half of GenAI projects die after proof of concept. Angular Agent Framework closes the gap. Start with a conversation.

    {/* CTA buttons */} diff --git a/apps/website/src/components/landing/PilotHero.tsx b/apps/website/src/components/landing/PilotHero.tsx index 64d37eb77..8b4267638 100644 --- a/apps/website/src/components/landing/PilotHero.tsx +++ b/apps/website/src/components/landing/PilotHero.tsx @@ -75,7 +75,7 @@ export function PilotHero() { marginBottom: '1.5rem', }} > - Angular Stream Resource Pilot Program + Angular Agent Framework Pilot Program @@ -114,7 +114,7 @@ export function PilotHero() { marginBottom: '2.5rem', }} > - Half of GenAI projects die after proof of concept. Yours doesn't have to. Angular Stream Resource closes the + Half of GenAI projects die after proof of concept. Yours doesn't have to. Angular Agent Framework closes the gap — app deployment license, fixed price, your team owns the result. diff --git a/apps/website/src/components/landing/PricingSignal.tsx b/apps/website/src/components/landing/PricingSignal.tsx index abc02d44c..91df4bc19 100644 --- a/apps/website/src/components/landing/PricingSignal.tsx +++ b/apps/website/src/components/landing/PricingSignal.tsx @@ -4,7 +4,7 @@ import { motion } from 'framer-motion'; import { tokens } from '../../../lib/design-tokens'; const features = [ - 'stream-resource license for one app in production', + 'angular license for one app in production', '3-month co-pilot engagement alongside your team', 'Architecture reviews, code pairing, unblocking sessions', 'Patterns your team owns and can replicate', @@ -78,7 +78,7 @@ export function PricingSignal() { marginTop: '8px', }} > - App deployment license. Includes stream-resource + 3-month co-pilot engagement. + App deployment license. Includes angular + 3-month co-pilot engagement.
    diff --git a/apps/website/src/components/landing/ProblemSection.tsx b/apps/website/src/components/landing/ProblemSection.tsx index f18340f64..78e80e046 100644 --- a/apps/website/src/components/landing/ProblemSection.tsx +++ b/apps/website/src/components/landing/ProblemSection.tsx @@ -326,7 +326,7 @@ export function ProblemSection() { transition: 'opacity 0.4s, transform 0.4s', }}> - Angular Stream Resource closes the gap + Angular Agent Framework closes the gap
    ({ +const chat = agent({ assistantId: 'agent', }); @@ -30,7 +30,7 @@ const lastMessage = computed(() => headline: 'Full Agent Lifecycle Support', description: 'Handle interrupts for human-in-the-loop approval, process tool calls, navigate branch history, and manage subagent delegation. Every LangGraph agent pattern has a first-class Angular API — no React translation layer needed.', code: `// approval.component.ts -const agent = streamResource({ +const agent = agent({ assistantId: 'approval_agent', onInterrupt: (interrupt) => { // Agent paused — surface to user @@ -51,16 +51,16 @@ const branches = agent.history();`, id: 'testing', label: 'Test Everything', headline: 'Deterministic Agent Testing', - description: 'MockStreamTransport lets you script exact event sequences and step through them in your specs. No flaky SSE connections, no timing issues, no running LangGraph server. Test agent behavior the same way you test any Angular service.', + description: 'MockAgentTransport lets you script exact event sequences and step through them in your specs. No flaky SSE connections, no timing issues, no running LangGraph server. Test agent behavior the same way you test any Angular service.', code: `// chat.component.spec.ts -const transport = new MockStreamTransport(); +const transport = new MockAgentTransport(); transport.script([ { type: 'values', data: { messages: [aiMsg('Hello')] } }, { type: 'values', data: { status: 'done' } }, ]); -const chat = streamResource({ +const chat = agent({ transport, assistantId: 'test_agent', }); @@ -85,7 +85,7 @@ export async function ValueProps() { return (

    Why streamResource()?

    + style={{ color: tokens.colors.accent }}>Why agent()?

    {/* Brand */}
    -

    Angular Stream Resource

    +

    Angular Agent Framework

    The enterprise streaming resource for LangChain and Angular. Signal-native streaming built for production Angular 20+.

    @@ -120,7 +120,7 @@ export function Footer() { aria-label="GitHub"> - (e.currentTarget.style.color = tokens.colors.textSecondary)}> Documentation - (e.currentTarget.style.color = tokens.colors.accent)} onMouseLeave={(e) => (e.currentTarget.style.color = tokens.colors.textSecondary)}> API Reference @@ -173,7 +173,7 @@ export function Footer() { onMouseLeave={(e) => (e.currentTarget.style.color = tokens.colors.textSecondary)}> Getting Started - (e.currentTarget.style.color = tokens.colors.accent)} @@ -191,7 +191,7 @@ export function Footer() { {/* Bottom bar */}
    - © {new Date().getFullYear()} Angular Stream Resource. All rights reserved. + © {new Date().getFullYear()} Angular Agent Framework. All rights reserved. PolyForm Noncommercial 1.0.0 · (e.currentTarget.style.color = tokens.colors.accent)} onMouseLeave={(e) => (e.currentTarget.style.color = tokens.colors.textMuted)}>Commercial License diff --git a/apps/website/src/components/shared/InstallStrip.tsx b/apps/website/src/components/shared/InstallStrip.tsx index 0343a98cc..e722ab043 100644 --- a/apps/website/src/components/shared/InstallStrip.tsx +++ b/apps/website/src/components/shared/InstallStrip.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import { tokens } from '@cacheplane/design-tokens'; -const CMD = 'npm install @cacheplane/stream-resource'; +const CMD = 'npm install @cacheplane/angular'; export function InstallStrip() { const [copied, setCopied] = useState(false); diff --git a/apps/website/src/components/shared/Nav.tsx b/apps/website/src/components/shared/Nav.tsx index f7288ef28..5b32c6384 100644 --- a/apps/website/src/components/shared/Nav.tsx +++ b/apps/website/src/components/shared/Nav.tsx @@ -6,7 +6,7 @@ import { tokens } from '@cacheplane/design-tokens'; const links = [ { label: 'Pilot to Prod', href: '/pilot-to-prod', external: false }, { label: 'Docs', href: '/docs', external: false }, - { label: 'API', href: '/docs/api/stream-resource', external: false }, + { label: 'API', href: '/docs/api/angular', external: false }, { label: 'Examples', href: 'https://cockpit.stream-resource.dev', external: true }, { label: 'Pricing', href: '/pricing', external: false }, ]; @@ -50,7 +50,7 @@ export function Nav() { {/* Top bar */}
    - Angular Stream Resource + Angular Agent Framework {/* Desktop links */} diff --git a/apps/website/src/lib/docs-config.ts b/apps/website/src/lib/docs-config.ts index 0224f2f88..b8e5cd37f 100644 --- a/apps/website/src/lib/docs-config.ts +++ b/apps/website/src/lib/docs-config.ts @@ -53,10 +53,10 @@ export const docsConfig: DocsSection[] = [ id: 'api', color: 'blue', pages: [ - { title: 'streamResource()', slug: 'stream-resource', section: 'api' }, - { title: 'provideStreamResource()', slug: 'provide-stream-resource', section: 'api' }, + { title: 'agent()', slug: 'angular', section: 'api' }, + { title: 'provideAgent()', slug: 'provide-angular', section: 'api' }, { title: 'FetchStreamTransport', slug: 'fetch-stream-transport', section: 'api' }, - { title: 'MockStreamTransport', slug: 'mock-stream-transport', section: 'api' }, + { title: 'MockAgentTransport', slug: 'mock-stream-transport', section: 'api' }, ], }, ]; diff --git a/apps/website/src/lib/docs.spec.ts b/apps/website/src/lib/docs.spec.ts index ef294b75b..16ecb53a4 100644 --- a/apps/website/src/lib/docs.spec.ts +++ b/apps/website/src/lib/docs.spec.ts @@ -8,14 +8,14 @@ describe('website docs bindings', () => { expect(slugs.length).toBe(allDocsPages.length); expect(slugs).toContainEqual({ section: 'getting-started', slug: 'introduction' }); expect(slugs).toContainEqual({ section: 'guides', slug: 'streaming' }); - expect(slugs).toContainEqual({ section: 'api', slug: 'stream-resource' }); + expect(slugs).toContainEqual({ section: 'api', slug: 'angular' }); }); it('loads a doc by section and slug', () => { const doc = getDocBySlug('getting-started', 'introduction'); expect(doc).not.toBeNull(); expect(doc?.title).toBe('Introduction'); - expect(doc?.content).toContain('Angular Stream Resource'); + expect(doc?.content).toContain('Angular Agent Framework'); }); it('returns null for non-existent doc', () => { diff --git a/cockpit/deep-agents/filesystem/angular/package.json b/cockpit/deep-agents/filesystem/angular/package.json index cd7907aeb..ed1cc73de 100644 --- a/cockpit/deep-agents/filesystem/angular/package.json +++ b/cockpit/deep-agents/filesystem/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/filesystem/angular/src/app/app.config.ts b/cockpit/deep-agents/filesystem/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/filesystem/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/filesystem/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/filesystem/angular/src/app/filesystem.component.ts b/cockpit/deep-agents/filesystem/angular/src/app/filesystem.component.ts index 2a6d924f2..699ec60fb 100644 --- a/cockpit/deep-agents/filesystem/angular/src/app/filesystem.component.ts +++ b/cockpit/deep-agents/filesystem/angular/src/app/filesystem.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -65,7 +65,7 @@ export class FilesystemComponent { * The graph uses `read_file` and `write_file` tool calls that appear * in `stream.messages()`. We filter and display them in the sidebar. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/filesystem/python/docs/guide.md b/cockpit/deep-agents/filesystem/python/docs/guide.md index 69d172d48..08f857422 100644 --- a/cockpit/deep-agents/filesystem/python/docs/guide.md +++ b/cockpit/deep-agents/filesystem/python/docs/guide.md @@ -1,47 +1,47 @@ -# File Operations with stream-resource +# File Operations with angular -Build a chat interface that shows real-time file operation logs using `streamResource()` from -`@cacheplane/stream-resource`. The agent reads and writes files using tool calls, and the +Build a chat interface that shows real-time file operation logs using `agent()` from +`@cacheplane/angular`. The agent reads and writes files using tool calls, and the sidebar displays each operation as it happens. -Add a file operations sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.messages()` to access tool call data, derive `toolCallEntries` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. +Add a file operations sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.messages()` to access tool call data, derive `toolCallEntries` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your filesystem graph: +In your component, call `agent()` with the `assistantId` pointing to your filesystem graph: ```typescript // filesystem.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class FilesystemComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'filesystem', }); } @@ -64,7 +64,7 @@ interface ToolCallEntry { } export class FilesystemComponent { - protected readonly stream = streamResource({ assistantId: 'filesystem' }); + protected readonly stream = agent({ assistantId: 'filesystem' }); toolCallEntries = computed(() => { const msg = this.stream.messages(); diff --git a/cockpit/deep-agents/memory/angular/package.json b/cockpit/deep-agents/memory/angular/package.json index f494653dc..576506d26 100644 --- a/cockpit/deep-agents/memory/angular/package.json +++ b/cockpit/deep-agents/memory/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/memory/angular/src/app/app.config.ts b/cockpit/deep-agents/memory/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/memory/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/memory/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/memory/angular/src/app/memory.component.ts b/cockpit/deep-agents/memory/angular/src/app/memory.component.ts index 01f230248..847917984 100644 --- a/cockpit/deep-agents/memory/angular/src/app/memory.component.ts +++ b/cockpit/deep-agents/memory/angular/src/app/memory.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -51,7 +51,7 @@ export class MemoryComponent { * The graph returns an `agent_memory` (or `memory`) dict alongside messages * in its state. We derive a reactive signal from `stream.value()` for display. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/memory/python/docs/guide.md b/cockpit/deep-agents/memory/python/docs/guide.md index 0db37f322..82340d6bb 100644 --- a/cockpit/deep-agents/memory/python/docs/guide.md +++ b/cockpit/deep-agents/memory/python/docs/guide.md @@ -1,45 +1,45 @@ -# Persistent Agent Memory with stream-resource +# Persistent Agent Memory with angular -Build a chat interface where the agent remembers facts about the user across turns using `streamResource()` from `@cacheplane/stream-resource`. The agent stores learned facts in `agent_memory` state, and the sidebar displays them in real time. +Build a chat interface where the agent remembers facts about the user across turns using `agent()` from `@cacheplane/angular`. The agent stores learned facts in `agent_memory` state, and the sidebar displays them in real time. -Add a memory sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.value()` to access the agent's `agent_memory` state, derive `memoryEntries` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. +Add a memory sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.value()` to access the agent's `agent_memory` state, derive `memoryEntries` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your memory graph: +In your component, call `agent()` with the `assistantId` pointing to your memory graph: ```typescript // memory.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class MemoryComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'da-memory', }); } @@ -56,7 +56,7 @@ Use Angular's `computed()` to reactively derive the memory key/value pairs from import { computed } from '@angular/core'; export class MemoryComponent { - protected readonly stream = streamResource({ assistantId: 'da-memory' }); + protected readonly stream = agent({ assistantId: 'da-memory' }); memoryEntries = computed(() => { const val = this.stream.value() as { agent_memory?: Record } | undefined; diff --git a/cockpit/deep-agents/planning/angular/package.json b/cockpit/deep-agents/planning/angular/package.json index 8d2057bb3..d998930b4 100644 --- a/cockpit/deep-agents/planning/angular/package.json +++ b/cockpit/deep-agents/planning/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/planning/angular/src/app/app.config.ts b/cockpit/deep-agents/planning/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/planning/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/planning/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/planning/angular/src/app/planning.component.ts b/cockpit/deep-agents/planning/angular/src/app/planning.component.ts index 790565512..4678db670 100644 --- a/cockpit/deep-agents/planning/angular/src/app/planning.component.ts +++ b/cockpit/deep-agents/planning/angular/src/app/planning.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -63,7 +63,7 @@ export class PlanningComponent { * The graph returns a `plan` array alongside messages in its state. * Each plan entry has a `title` and `status` that drive the sidebar checklist. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/planning/python/docs/guide.md b/cockpit/deep-agents/planning/python/docs/guide.md index 84a0a4ba9..6a848c49d 100644 --- a/cockpit/deep-agents/planning/python/docs/guide.md +++ b/cockpit/deep-agents/planning/python/docs/guide.md @@ -1,47 +1,47 @@ -# Task Decomposition with stream-resource +# Task Decomposition with angular -Build a chat interface that shows real-time task decomposition using `streamResource()` from -`@cacheplane/stream-resource`. The agent breaks complex requests into ordered steps, and the +Build a chat interface that shows real-time task decomposition using `agent()` from +`@cacheplane/angular`. The agent breaks complex requests into ordered steps, and the sidebar displays each step's status as the agent works through them. -Add a task planning sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.value()` to access the agent's plan state, derive `planSteps` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. +Add a task planning sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.value()` to access the agent's plan state, derive `planSteps` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your planning graph: +In your component, call `agent()` with the `assistantId` pointing to your planning graph: ```typescript // planning.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class PlanningComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'planning', }); } @@ -63,7 +63,7 @@ interface PlanStep { } export class PlanningComponent { - protected readonly stream = streamResource({ assistantId: 'planning' }); + protected readonly stream = agent({ assistantId: 'planning' }); planSteps = computed(() => { const val = this.stream.value() as { plan?: PlanStep[] } | undefined; diff --git a/cockpit/deep-agents/sandboxes/angular/package.json b/cockpit/deep-agents/sandboxes/angular/package.json index 3c0d67a53..22a0dac66 100644 --- a/cockpit/deep-agents/sandboxes/angular/package.json +++ b/cockpit/deep-agents/sandboxes/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/sandboxes/angular/src/app/app.config.ts b/cockpit/deep-agents/sandboxes/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/sandboxes/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/sandboxes/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/sandboxes/angular/src/app/sandboxes.component.ts b/cockpit/deep-agents/sandboxes/angular/src/app/sandboxes.component.ts index f86b65a67..1f349ca8b 100644 --- a/cockpit/deep-agents/sandboxes/angular/src/app/sandboxes.component.ts +++ b/cockpit/deep-agents/sandboxes/angular/src/app/sandboxes.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -59,7 +59,7 @@ interface CodeExecution { `, }) export class SandboxesComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/sandboxes/python/docs/guide.md b/cockpit/deep-agents/sandboxes/python/docs/guide.md index 1cdaf2629..762f09de9 100644 --- a/cockpit/deep-agents/sandboxes/python/docs/guide.md +++ b/cockpit/deep-agents/sandboxes/python/docs/guide.md @@ -1,47 +1,47 @@ -# Code Execution Sandbox with stream-resource +# Code Execution Sandbox with angular -Build a chat interface that shows real-time code execution logs using `streamResource()` from -`@cacheplane/stream-resource`. The agent writes Python code and runs it in a sandbox, and the +Build a chat interface that shows real-time code execution logs using `agent()` from +`@cacheplane/angular`. The agent writes Python code and runs it in a sandbox, and the sidebar displays each execution as a log entry with code input, stdout output, and exit status. -Add a code execution log sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.messages()` to access tool call data from the `run_code` tool, derive `executionLogs` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. +Add a code execution log sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.messages()` to access tool call data from the `run_code` tool, derive `executionLogs` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your sandboxes graph: +In your component, call `agent()` with the `assistantId` pointing to your sandboxes graph: ```typescript // sandboxes.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class SandboxesComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'sandboxes', }); } @@ -64,7 +64,7 @@ interface ExecutionLog { } export class SandboxesComponent { - protected readonly stream = streamResource({ assistantId: 'sandboxes' }); + protected readonly stream = agent({ assistantId: 'sandboxes' }); executionLogs = computed(() => { const msgs = this.stream.messages(); diff --git a/cockpit/deep-agents/skills/angular/package.json b/cockpit/deep-agents/skills/angular/package.json index 6a35f6cae..5c1b5ac9d 100644 --- a/cockpit/deep-agents/skills/angular/package.json +++ b/cockpit/deep-agents/skills/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/skills/angular/src/app/app.config.ts b/cockpit/deep-agents/skills/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/skills/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/skills/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/skills/angular/src/app/skills.component.ts b/cockpit/deep-agents/skills/angular/src/app/skills.component.ts index 7d43b6180..71c3cb577 100644 --- a/cockpit/deep-agents/skills/angular/src/app/skills.component.ts +++ b/cockpit/deep-agents/skills/angular/src/app/skills.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -65,7 +65,7 @@ interface SkillInvocation { `, }) export class SkillsComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/skills/python/docs/guide.md b/cockpit/deep-agents/skills/python/docs/guide.md index d8974ce22..9fbbaf032 100644 --- a/cockpit/deep-agents/skills/python/docs/guide.md +++ b/cockpit/deep-agents/skills/python/docs/guide.md @@ -1,47 +1,47 @@ -# Multi-Skill Agent with stream-resource +# Multi-Skill Agent with angular -Build a chat interface that shows real-time skill invocations using `streamResource()` from -`@cacheplane/stream-resource`. The agent selects from specialized tools (calculator, word counter, +Build a chat interface that shows real-time skill invocations using `agent()` from +`@cacheplane/angular`. The agent selects from specialized tools (calculator, word counter, summarizer) based on the user's request, and the sidebar displays each skill invocation as a card. -Add a skill invocation sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.messages()` to access tool call data, derive `skillInvocations` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. +Add a skill invocation sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.messages()` to access tool call data, derive `skillInvocations` with `computed()`, and bind them to the sidebar via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your skills graph: +In your component, call `agent()` with the `assistantId` pointing to your skills graph: ```typescript // skills.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class SkillsComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'skills', }); } @@ -64,7 +64,7 @@ interface SkillInvocation { } export class SkillsComponent { - protected readonly stream = streamResource({ assistantId: 'skills' }); + protected readonly stream = agent({ assistantId: 'skills' }); skillInvocations = computed(() => { const msgs = this.stream.messages(); diff --git a/cockpit/deep-agents/subagents/angular/package.json b/cockpit/deep-agents/subagents/angular/package.json index c5a6b89b5..7008680f2 100644 --- a/cockpit/deep-agents/subagents/angular/package.json +++ b/cockpit/deep-agents/subagents/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/deep-agents/subagents/angular/src/app/app.config.ts b/cockpit/deep-agents/subagents/angular/src/app/app.config.ts index 08e9180d0..bbe3e5e49 100644 --- a/cockpit/deep-agents/subagents/angular/src/app/app.config.ts +++ b/cockpit/deep-agents/subagents/angular/src/app/app.config.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { provideRender } from '@cacheplane/render'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), provideRender({}), ], diff --git a/cockpit/deep-agents/subagents/angular/src/app/subagents.component.ts b/cockpit/deep-agents/subagents/angular/src/app/subagents.component.ts index cd07b6e35..412aa989a 100644 --- a/cockpit/deep-agents/subagents/angular/src/app/subagents.component.ts +++ b/cockpit/deep-agents/subagents/angular/src/app/subagents.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -55,7 +55,7 @@ export class SubagentsComponent { /** * The streaming resource connected to the subagents orchestrator graph. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/deep-agents/subagents/python/docs/guide.md b/cockpit/deep-agents/subagents/python/docs/guide.md index 46c043c21..75ec364a5 100644 --- a/cockpit/deep-agents/subagents/python/docs/guide.md +++ b/cockpit/deep-agents/subagents/python/docs/guide.md @@ -1,47 +1,47 @@ -# Child Agent Delegation with stream-resource +# Child Agent Delegation with angular -Build a chat interface that shows real-time subagent activity using `streamResource()` from -`@cacheplane/stream-resource`. An orchestrator agent delegates subtasks to specialist child +Build a chat interface that shows real-time subagent activity using `agent()` from +`@cacheplane/angular`. An orchestrator agent delegates subtasks to specialist child agents, and the sidebar displays each subagent's status and message count as they stream. -Add a subagent activity sidebar to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.subagents()` to access the live Map of child agent streams, derive `subagentEntries` with `computed()`, and render them in the `` sidebar. +Add a subagent activity sidebar to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.subagents()` to access the live Map of child agent streams, derive `subagentEntries` with `computed()`, and render them in the `` sidebar. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your subagents graph: +In your component, call `agent()` with the `assistantId` pointing to your subagents graph: ```typescript // subagents.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class SubagentsComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'subagents', }); } @@ -58,7 +58,7 @@ Use Angular's `computed()` to convert the subagents Map into a renderable array: import { computed } from '@angular/core'; export class SubagentsComponent { - protected readonly stream = streamResource({ assistantId: 'subagents' }); + protected readonly stream = agent({ assistantId: 'subagents' }); subagentEntries = computed(() => Array.from(this.stream.subagents().entries())); } diff --git a/cockpit/langgraph/deployment-runtime/angular/package.json b/cockpit/langgraph/deployment-runtime/angular/package.json index 47596b10d..b8c480640 100644 --- a/cockpit/langgraph/deployment-runtime/angular/package.json +++ b/cockpit/langgraph/deployment-runtime/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/deployment-runtime/angular/prompts/deployment-runtime.md b/cockpit/langgraph/deployment-runtime/angular/prompts/deployment-runtime.md index d75d372c4..6ba1ffaca 100644 --- a/cockpit/langgraph/deployment-runtime/angular/prompts/deployment-runtime.md +++ b/cockpit/langgraph/deployment-runtime/angular/prompts/deployment-runtime.md @@ -2,4 +2,4 @@ This capability demonstrates production deployment patterns for LangGraph agents — including environment-specific base URLs, authentication headers, and assistant resolution — using the `@cacheplane/chat` Angular component library. The `` component is configured through Angular's dependency injection system, making it straightforward to swap between local development, staging, and production LangGraph Cloud deployments. -Key components used: ``. Configuration is provided via an Angular environment token injected into `streamResource`, keeping all deployment concerns out of the component template and enabling zero-code environment switches at build time. +Key components used: ``. Configuration is provided via an Angular environment token injected into `agent`, keeping all deployment concerns out of the component template and enabling zero-code environment switches at build time. diff --git a/cockpit/langgraph/deployment-runtime/angular/src/app/app.config.ts b/cockpit/langgraph/deployment-runtime/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/deployment-runtime/angular/src/app/app.config.ts +++ b/cockpit/langgraph/deployment-runtime/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/deployment-runtime/angular/src/app/deployment-runtime.component.ts b/cockpit/langgraph/deployment-runtime/angular/src/app/deployment-runtime.component.ts index 14f4e2e76..ab9429322 100644 --- a/cockpit/langgraph/deployment-runtime/angular/src/app/deployment-runtime.component.ts +++ b/cockpit/langgraph/deployment-runtime/angular/src/app/deployment-runtime.component.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { Component } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** * Deployment-runtime demo — production deployment patterns. * - * Shows how streamResource() connects to a deployed LangGraph Cloud + * Shows how agent() connects to a deployed LangGraph Cloud * instance using environment-specific API URLs and assistant IDs. */ @Component({ @@ -17,7 +17,7 @@ import { environment } from '../environments/environment'; template: ``, }) export class DeploymentRuntimeComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.deploymentRuntimeAssistantId, }); diff --git a/cockpit/langgraph/deployment-runtime/python/docs/guide.md b/cockpit/langgraph/deployment-runtime/python/docs/guide.md index f767e1323..3b53082cf 100644 --- a/cockpit/langgraph/deployment-runtime/python/docs/guide.md +++ b/cockpit/langgraph/deployment-runtime/python/docs/guide.md @@ -2,13 +2,13 @@ Deploy a LangGraph graph to LangGraph Cloud and connect an Angular app using -`streamResource()` from `@cacheplane/stream-resource`. This tutorial covers +`agent()` from `@cacheplane/angular`. This tutorial covers `langgraph deploy`, environment configuration, Vercel hosting for Angular, and CI automation. -Build a production-ready Angular chat app that connects to a LangGraph Cloud deployment using `streamResource()` from `@cacheplane/stream-resource`. Configure the `apiUrl` to point to your deployed LangGraph Cloud endpoint and set `assistantId` to match the graph name in `langgraph.json`. Display the deployment status via `stream.status()` and show the thread ID from the `onThreadId` callback. +Build a production-ready Angular chat app that connects to a LangGraph Cloud deployment using `agent()` from `@cacheplane/angular`. Configure the `apiUrl` to point to your deployed LangGraph Cloud endpoint and set `assistantId` to match the graph name in `langgraph.json`. Display the deployment status via `stream.status()` and show the thread ID from the `onThreadId` callback. @@ -70,17 +70,17 @@ export const environment = { Angular's file replacement swaps the environment at build time. - + -In your component, pass the deployment URL and assistant ID to `streamResource()`: +In your component, pass the deployment URL and assistant ID to `agent()`: ```typescript // deployment-runtime.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; export class DeploymentRuntimeComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.deploymentRuntimeAssistantId, onThreadId: (id: string) => { diff --git a/cockpit/langgraph/durable-execution/angular/package.json b/cockpit/langgraph/durable-execution/angular/package.json index e3e2ebb1c..302f2bb3e 100644 --- a/cockpit/langgraph/durable-execution/angular/package.json +++ b/cockpit/langgraph/durable-execution/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/durable-execution/angular/prompts/durable-execution.md b/cockpit/langgraph/durable-execution/angular/prompts/durable-execution.md index 20dd481b5..0fcf6a4e4 100644 --- a/cockpit/langgraph/durable-execution/angular/prompts/durable-execution.md +++ b/cockpit/langgraph/durable-execution/angular/prompts/durable-execution.md @@ -1,5 +1,5 @@ # LangGraph Durable Execution (Angular) -This capability demonstrates LangGraph's durable execution guarantees — automatic retry, reconnection, and resumption after network interruptions — using the `@cacheplane/chat` Angular component library. The `` component surfaces transient failures with a one-click reconnect affordance, while `streamResource` handles exponential back-off and checkpoint-based resumption transparently. +This capability demonstrates LangGraph's durable execution guarantees — automatic retry, reconnection, and resumption after network interruptions — using the `@cacheplane/chat` Angular component library. The `` component surfaces transient failures with a one-click reconnect affordance, while `agent` handles exponential back-off and checkpoint-based resumption transparently. -Key components used: ``, ``. When the SSE stream is interrupted, `` replaces the typing indicator with an error banner; once the user reconnects (or `streamResource` auto-retries), the component dismisses automatically and the stream resumes from the last persisted checkpoint. +Key components used: ``, ``. When the SSE stream is interrupted, `` replaces the typing indicator with an error banner; once the user reconnects (or `agent` auto-retries), the component dismisses automatically and the stream resumes from the last persisted checkpoint. diff --git a/cockpit/langgraph/durable-execution/angular/src/app/app.config.ts b/cockpit/langgraph/durable-execution/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/durable-execution/angular/src/app/app.config.ts +++ b/cockpit/langgraph/durable-execution/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/durable-execution/angular/src/app/durable-execution.component.ts b/cockpit/langgraph/durable-execution/angular/src/app/durable-execution.component.ts index a20bb86b8..f5a63e1be 100644 --- a/cockpit/langgraph/durable-execution/angular/src/app/durable-execution.component.ts +++ b/cockpit/langgraph/durable-execution/angular/src/app/durable-execution.component.ts @@ -1,6 +1,6 @@ import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -24,7 +24,7 @@ const STEP_LABELS: Record = { /** * DurableExecutionComponent demonstrates fault-tolerant multi-step execution - * with `streamResource()`. + * with `agent()`. * * This example shows how a graph checkpoints at each node, enabling it to * resume after failures. The backend processes each request through three @@ -92,7 +92,7 @@ const STEP_LABELS: Record = { `, }) export class DurableExecutionComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/durable-execution/python/docs/guide.md b/cockpit/langgraph/durable-execution/python/docs/guide.md index 61cb3473d..b6bb32c5e 100644 --- a/cockpit/langgraph/durable-execution/python/docs/guide.md +++ b/cockpit/langgraph/durable-execution/python/docs/guide.md @@ -1,48 +1,48 @@ -# Durable Execution with stream-resource +# Durable Execution with angular -Build a fault-tolerant chat interface using `streamResource()` from -`@cacheplane/stream-resource`. The backend graph checkpoints state after +Build a fault-tolerant chat interface using `agent()` from +`@cacheplane/angular`. The backend graph checkpoints state after each node, enabling resume-on-failure. The sidebar monitors execution status in real time and exposes a "Retry" button when errors occur. -Add a durable multi-step execution workflow to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Display `stream.status()` as a colour-coded badge, show a `stream.hasValue()` indicator, and render a "Retry" button that calls `stream.reload()` when `stream.error()` is set. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. +Add a durable multi-step execution workflow to this Angular component using `agent()` from `@cacheplane/angular`. Display `stream.status()` as a colour-coded badge, show a `stream.hasValue()` indicator, and render a "Retry" button that calls `stream.reload()` when `stream.error()` is set. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `assistantId` pointing to your durable-execution graph: +In your component, call `agent()` with the `assistantId` pointing to your durable-execution graph: ```typescript // durable-execution.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class DurableExecutionComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'durable-execution', }); diff --git a/cockpit/langgraph/interrupts/angular/package.json b/cockpit/langgraph/interrupts/angular/package.json index 9cf2cf3e5..d5511f987 100644 --- a/cockpit/langgraph/interrupts/angular/package.json +++ b/cockpit/langgraph/interrupts/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/interrupts/angular/prompts/interrupts.md b/cockpit/langgraph/interrupts/angular/prompts/interrupts.md index 153bdf979..840f96b01 100644 --- a/cockpit/langgraph/interrupts/angular/prompts/interrupts.md +++ b/cockpit/langgraph/interrupts/angular/prompts/interrupts.md @@ -1,5 +1,5 @@ # LangGraph Interrupts (Angular) -This capability demonstrates human-in-the-loop interrupt handling using LangGraph's `interrupt()` primitive and the `@cacheplane/chat` Angular component library. When the graph pauses at an interrupt node, the `` surfaces the pending decision to the user; their response is submitted back to the graph via `streamResource`'s `resume` helper. +This capability demonstrates human-in-the-loop interrupt handling using LangGraph's `interrupt()` primitive and the `@cacheplane/chat` Angular component library. When the graph pauses at an interrupt node, the `` surfaces the pending decision to the user; their response is submitted back to the graph via `agent`'s `resume` helper. Key components used: ``, ``. The interrupt panel renders inside the chat host and becomes visible automatically whenever the underlying stream resource detects a pending interrupt in the thread state. diff --git a/cockpit/langgraph/interrupts/angular/src/app/app.config.ts b/cockpit/langgraph/interrupts/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/interrupts/angular/src/app/app.config.ts +++ b/cockpit/langgraph/interrupts/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/interrupts/angular/src/app/interrupts.component.ts b/cockpit/langgraph/interrupts/angular/src/app/interrupts.component.ts index de14f8ab1..b6683d5b5 100644 --- a/cockpit/langgraph/interrupts/angular/src/app/interrupts.component.ts +++ b/cockpit/langgraph/interrupts/angular/src/app/interrupts.component.ts @@ -1,11 +1,11 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { Component } from '@angular/core'; import { ChatComponent, ChatInterruptPanelComponent, type InterruptAction } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** - * InterruptsComponent demonstrates human-in-the-loop with `streamResource()`. + * InterruptsComponent demonstrates human-in-the-loop with `agent()`. * * The LangGraph backend pauses execution when it needs human approval. * The `stream.interrupt()` signal provides the interrupt data, and @@ -38,7 +38,7 @@ export class InterruptsComponent { * When the LangGraph backend calls `interrupt()`, the `stream.interrupt()` * signal emits the interrupt payload for display via ChatInterruptPanelComponent. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/interrupts/python/docs/guide.md b/cockpit/langgraph/interrupts/python/docs/guide.md index f2b9e9899..268540ba5 100644 --- a/cockpit/langgraph/interrupts/python/docs/guide.md +++ b/cockpit/langgraph/interrupts/python/docs/guide.md @@ -1,47 +1,47 @@ -# Human-in-the-Loop Interrupts with stream-resource +# Human-in-the-Loop Interrupts with angular -Build a chat interface with human-in-the-loop approval using `streamResource()` from -`@cacheplane/stream-resource`. The LangGraph backend pauses execution for approval, +Build a chat interface with human-in-the-loop approval using `agent()` from +`@cacheplane/angular`. The LangGraph backend pauses execution for approval, and the frontend resumes it with `stream.submit()`. -Add human-in-the-loop approval to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.interrupt()` to display pending approvals, `stream.submit(null)` to approve and resume execution, and `stream.submit({ resume: false })` to reject. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. +Add human-in-the-loop approval to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.interrupt()` to display pending approvals, `stream.submit(null)` to approve and resume execution, and `stream.submit({ resume: false })` to reject. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the assistant ID that maps to your interrupts graph: +In your component, call `agent()` with the assistant ID that maps to your interrupts graph: ```typescript // interrupts.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class InterruptsComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'interrupts', }); } diff --git a/cockpit/langgraph/memory/angular/package.json b/cockpit/langgraph/memory/angular/package.json index 9e29cbbf0..c943f9885 100644 --- a/cockpit/langgraph/memory/angular/package.json +++ b/cockpit/langgraph/memory/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/memory/angular/prompts/memory.md b/cockpit/langgraph/memory/angular/prompts/memory.md index 773eec12c..f74a8f0c1 100644 --- a/cockpit/langgraph/memory/angular/prompts/memory.md +++ b/cockpit/langgraph/memory/angular/prompts/memory.md @@ -2,4 +2,4 @@ This capability demonstrates cross-thread memory using LangGraph's persistent memory store and the `@cacheplane/chat` Angular component library. Facts and preferences written by the agent in one thread are automatically recalled in subsequent threads, giving the user a coherent long-term experience across sessions. -Key components used: `` with a thread list sidebar. Each new `streamResource` ref carries the same `userId` namespace so the LangGraph memory store can surface relevant memories regardless of which thread is active. +Key components used: `` with a thread list sidebar. Each new `agent` ref carries the same `userId` namespace so the LangGraph memory store can surface relevant memories regardless of which thread is active. diff --git a/cockpit/langgraph/memory/angular/src/app/app.config.ts b/cockpit/langgraph/memory/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/memory/angular/src/app/app.config.ts +++ b/cockpit/langgraph/memory/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/memory/angular/src/app/memory.component.ts b/cockpit/langgraph/memory/angular/src/app/memory.component.ts index cfd879daf..ae954171f 100644 --- a/cockpit/langgraph/memory/angular/src/app/memory.component.ts +++ b/cockpit/langgraph/memory/angular/src/app/memory.component.ts @@ -1,11 +1,11 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** - * MemoryComponent demonstrates cross-thread persistent context with `streamResource()`. + * MemoryComponent demonstrates cross-thread persistent context with `agent()`. * * This example shows how an agent can learn and remember facts about the user * across separate conversations. The graph maintains a `memory` dict in its @@ -47,7 +47,7 @@ export class MemoryComponent { * The graph returns a `memory` dict alongside messages in its state. * We expose it via `stream.value()` and derive a reactive signal for display. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/memory/python/docs/guide.md b/cockpit/langgraph/memory/python/docs/guide.md index afff4e8f3..8271b83d2 100644 --- a/cockpit/langgraph/memory/python/docs/guide.md +++ b/cockpit/langgraph/memory/python/docs/guide.md @@ -1,4 +1,4 @@ -# Cross-Thread Persistent Memory with stream-resource +# Cross-Thread Persistent Memory with angular Build a chat interface where the agent actively learns and remembers facts about the user. @@ -8,22 +8,22 @@ and displays it in a live sidebar. -Add persistent agent memory to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.value()` to access the `memory` field in graph state, derive a reactive `memoryEntries` signal with Angular's `computed()`, and render the facts in a sidebar panel via the `` component from `@cacheplane/chat`. +Add persistent agent memory to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.value()` to access the `memory` field in graph state, derive a reactive `memoryEntries` signal with Angular's `computed()`, and render the facts in a sidebar panel via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], @@ -33,14 +33,14 @@ export const appConfig: ApplicationConfig = { -In your component, call `streamResource()` pointing at the `memory` assistant: +In your component, call `agent()` pointing at the `memory` assistant: ```typescript // memory.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class MemoryComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'memory', }); } diff --git a/cockpit/langgraph/persistence/angular/package.json b/cockpit/langgraph/persistence/angular/package.json index 5e7cb32bd..8b60986f6 100644 --- a/cockpit/langgraph/persistence/angular/package.json +++ b/cockpit/langgraph/persistence/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/persistence/angular/prompts/persistence.md b/cockpit/langgraph/persistence/angular/prompts/persistence.md index a9b69b93a..b4c85491d 100644 --- a/cockpit/langgraph/persistence/angular/prompts/persistence.md +++ b/cockpit/langgraph/persistence/angular/prompts/persistence.md @@ -2,4 +2,4 @@ This capability demonstrates persisted conversation threads using LangGraph checkpointers and the `@cacheplane/chat` Angular component library. The `` component is paired with a thread list so users can switch between saved conversations — each backed by a LangGraph thread ID — without losing history. -Key components used: `` with a thread list sidebar driven by the LangGraph Threads API. The `streamResource` ref is re-initialised with a new `threadId` whenever the user selects a different thread, and the chat view replays the persisted checkpoint automatically. +Key components used: `` with a thread list sidebar driven by the LangGraph Threads API. The `agent` ref is re-initialised with a new `threadId` whenever the user selects a different thread, and the chat view replays the persisted checkpoint automatically. diff --git a/cockpit/langgraph/persistence/angular/src/app/app.config.ts b/cockpit/langgraph/persistence/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/persistence/angular/src/app/app.config.ts +++ b/cockpit/langgraph/persistence/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/persistence/angular/src/app/persistence.component.ts b/cockpit/langgraph/persistence/angular/src/app/persistence.component.ts index c140127f7..67f2218b6 100644 --- a/cockpit/langgraph/persistence/angular/src/app/persistence.component.ts +++ b/cockpit/langgraph/persistence/angular/src/app/persistence.component.ts @@ -1,6 +1,6 @@ import { Component, signal } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; interface Thread { @@ -9,7 +9,7 @@ interface Thread { } /** - * PersistenceComponent demonstrates thread persistence with `streamResource()`. + * PersistenceComponent demonstrates thread persistence with `agent()`. * * Layout: a full-height flex row with the `` area (flex-1) on the left * and a fixed-width thread-picker sidebar on the right. @@ -91,7 +91,7 @@ export class PersistenceComponent { * The `onThreadId` callback fires when a new thread is created, * allowing us to track thread IDs for the sidebar picker. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, onThreadId: (id: string) => { diff --git a/cockpit/langgraph/persistence/python/docs/guide.md b/cockpit/langgraph/persistence/python/docs/guide.md index 22d67bc96..cbd2b5a4a 100644 --- a/cockpit/langgraph/persistence/python/docs/guide.md +++ b/cockpit/langgraph/persistence/python/docs/guide.md @@ -1,47 +1,47 @@ -# Thread Persistence with stream-resource +# Thread Persistence with angular -Build a chat interface with thread persistence using `streamResource()` from -`@cacheplane/stream-resource`. Conversations survive browser refreshes and +Build a chat interface with thread persistence using `agent()` from +`@cacheplane/angular`. Conversations survive browser refreshes and can be resumed using `stream.switchThread(id)`. -Add thread persistence to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use the `onThreadId` callback to capture thread IDs, `stream.switchThread(id)` to resume conversations, and `stream.switchThread(null)` to start fresh. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. +Add thread persistence to this Angular component using `agent()` from `@cacheplane/angular`. Use the `onThreadId` callback to capture thread IDs, `stream.switchThread(id)` to resume conversations, and `stream.switchThread(null)` to start fresh. Bind `stream.messages()` in the template via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` with the `onThreadId` callback to capture new thread IDs: +In your component, call `agent()` with the `onThreadId` callback to capture new thread IDs: ```typescript // persistence.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class PersistenceComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'persistence', onThreadId: (id: string) => { this.currentThreadId = id; diff --git a/cockpit/langgraph/streaming/angular/package.json b/cockpit/langgraph/streaming/angular/package.json index 02699697e..222846536 100644 --- a/cockpit/langgraph/streaming/angular/package.json +++ b/cockpit/langgraph/streaming/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/streaming/angular/prompts/streaming.md b/cockpit/langgraph/streaming/angular/prompts/streaming.md index dc055e2c6..ab28278f7 100644 --- a/cockpit/langgraph/streaming/angular/prompts/streaming.md +++ b/cockpit/langgraph/streaming/angular/prompts/streaming.md @@ -1,5 +1,5 @@ # LangGraph Streaming (Angular) -This capability demonstrates real-time token streaming from a LangGraph agent using the `@cacheplane/chat` Angular component library. The example shows how to wire a `streamResource` ref into the `` host component and compose ``, ``, and `` to deliver a responsive, streaming chat experience. +This capability demonstrates real-time token streaming from a LangGraph agent using the `@cacheplane/chat` Angular component library. The example shows how to wire a `agent` ref into the `` host component and compose ``, ``, and `` to deliver a responsive, streaming chat experience. -Key components used: ``, ``, ``, ``. The `streamResource` signal handles SSE fan-out from the LangGraph streaming endpoint, and the chat components subscribe reactively without any manual subscription management. +Key components used: ``, ``, ``, ``. The `agent` signal handles SSE fan-out from the LangGraph streaming endpoint, and the chat components subscribe reactively without any manual subscription management. diff --git a/cockpit/langgraph/streaming/angular/src/app/app.config.ts b/cockpit/langgraph/streaming/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/streaming/angular/src/app/app.config.ts +++ b/cockpit/langgraph/streaming/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/streaming/angular/src/app/streaming.component.ts b/cockpit/langgraph/streaming/angular/src/app/streaming.component.ts index 4de25f813..cc445bfd3 100644 --- a/cockpit/langgraph/streaming/angular/src/app/streaming.component.ts +++ b/cockpit/langgraph/streaming/angular/src/app/streaming.component.ts @@ -1,13 +1,13 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { Component } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** * Streaming demo — simplest possible @cacheplane/chat integration. * - * Creates a streamResource ref and passes it to the prebuilt + * Creates a agent ref and passes it to the prebuilt * composition. The composition handles message rendering, input, typing * indicator, and error display internally. */ @@ -18,7 +18,7 @@ import { environment } from '../environments/environment'; template: ``, }) export class StreamingComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/streaming/python/docs/guide.md b/cockpit/langgraph/streaming/python/docs/guide.md index 6c132b92c..529431cb2 100644 --- a/cockpit/langgraph/streaming/python/docs/guide.md +++ b/cockpit/langgraph/streaming/python/docs/guide.md @@ -1,53 +1,53 @@ -# Streaming with stream-resource +# Streaming with angular -Build a real-time streaming chat interface using `streamResource()` from -`@cacheplane/stream-resource` connected to a LangGraph backend on LangSmith Cloud. +Build a real-time streaming chat interface using `agent()` from +`@cacheplane/angular` connected to a LangGraph backend on LangSmith Cloud. -Add real-time LLM streaming to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Configure `provideStreamResource({ apiUrl })` in the app config, then call `stream.submit()` to send messages. Bind `stream.messages()` in the template using `@for` — all Signals, no subscriptions needed. +Add real-time LLM streaming to this Angular component using `agent()` from `@cacheplane/angular`. Configure `provideAgent({ apiUrl })` in the app config, then call `stream.submit()` to send messages. Bind `stream.messages()` in the template using `@for` — all Signals, no subscriptions needed. -Set up `provideStreamResource()` in your app config with the LangGraph Cloud URL: +Set up `provideAgent()` in your app config with the LangGraph Cloud URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], }; ``` -This makes the API URL available to all `streamResource()` calls in your app. +This makes the API URL available to all `agent()` calls in your app. -In your component, call `streamResource()` in a field initializer (injection context required): +In your component, call `agent()` in a field initializer (injection context required): ```typescript // streaming.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class StreamingComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'streaming', }); } ``` -`streamResource()` must be called within an Angular injection context — a component field initializer or constructor body. +`agent()` must be called within an Angular injection context — a component field initializer or constructor body. @@ -114,7 +114,7 @@ Deploy with `langgraph deploy` from `langgraph-cli`. The `assistantId` in your A -No service layer needed — `streamResource()` replaces wrapper services entirely. It handles connection lifecycle, state management, and error recovery. +No service layer needed — `agent()` replaces wrapper services entirely. It handles connection lifecycle, state management, and error recovery. diff --git a/cockpit/langgraph/subgraphs/angular/package.json b/cockpit/langgraph/subgraphs/angular/package.json index 2be9769e1..fad17e402 100644 --- a/cockpit/langgraph/subgraphs/angular/package.json +++ b/cockpit/langgraph/subgraphs/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/subgraphs/angular/src/app/app.config.ts b/cockpit/langgraph/subgraphs/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/subgraphs/angular/src/app/app.config.ts +++ b/cockpit/langgraph/subgraphs/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/subgraphs/angular/src/app/subgraphs.component.ts b/cockpit/langgraph/subgraphs/angular/src/app/subgraphs.component.ts index 48a411ab4..9b98c234a 100644 --- a/cockpit/langgraph/subgraphs/angular/src/app/subgraphs.component.ts +++ b/cockpit/langgraph/subgraphs/angular/src/app/subgraphs.component.ts @@ -1,11 +1,11 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { Component, computed } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** - * SubgraphsComponent demonstrates nested agent delegation with `streamResource()`. + * SubgraphsComponent demonstrates nested agent delegation with `agent()`. * * This example shows how a parent orchestrator delegates tasks to child subgraphs. * The sidebar tracks active subagents in real time using `stream.subagents()`, @@ -50,7 +50,7 @@ export class SubgraphsComponent { * `stream.subagents()` is a Signal> that updates * as the parent orchestrator dispatches work to child subgraphs. */ - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/subgraphs/python/docs/guide.md b/cockpit/langgraph/subgraphs/python/docs/guide.md index 2ab26482b..fd61a5f5e 100644 --- a/cockpit/langgraph/subgraphs/python/docs/guide.md +++ b/cockpit/langgraph/subgraphs/python/docs/guide.md @@ -1,28 +1,28 @@ -# Nested Agent Delegation with Subgraphs and stream-resource +# Nested Agent Delegation with Subgraphs and angular -Build a chat interface that visualizes nested agent delegation using `streamResource()` from -`@cacheplane/stream-resource`. A parent orchestrator dispatches research tasks to a child +Build a chat interface that visualizes nested agent delegation using `agent()` from +`@cacheplane/angular`. A parent orchestrator dispatches research tasks to a child subgraph, and the sidebar tracks each subagent's status in real time using `stream.subagents()`. -Add a subgraph-powered orchestrator to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Use `stream.subagents()` to track active child subgraph executions, and derive a `subagentEntries` signal with `computed()` for template iteration. Bind `stream.messages()` via the `` component from `@cacheplane/chat`. +Add a subgraph-powered orchestrator to this Angular component using `agent()` from `@cacheplane/angular`. Use `stream.subagents()` to track active child subgraph executions, and derive a `subagentEntries` signal with `computed()` for template iteration. Bind `stream.messages()` via the `` component from `@cacheplane/chat`. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], @@ -32,15 +32,15 @@ export const appConfig: ApplicationConfig = { -In your component, call `streamResource()` with the assistant ID pointing to your subgraphs graph: +In your component, call `agent()` with the assistant ID pointing to your subgraphs graph: ```typescript // subgraphs.component.ts import { Component, computed } from '@angular/core'; -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class SubgraphsComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'subgraphs', }); @@ -114,7 +114,7 @@ parent_graph.add_edge("research", END) graph = parent_graph.compile() ``` -The child subgraph is compiled and passed as a node to the parent graph. LangGraph streams subgraph events separately, which `stream-resource` captures and exposes through `stream.subagents()`. +The child subgraph is compiled and passed as a node to the parent graph. LangGraph streams subgraph events separately, which `angular` captures and exposes through `stream.subagents()`. Child subgraphs can have their own state, checkpointers, and tools. This pattern is ideal for multi-agent systems where specialized agents handle distinct concerns. diff --git a/cockpit/langgraph/time-travel/angular/package.json b/cockpit/langgraph/time-travel/angular/package.json index adbd93331..4312ae2f2 100644 --- a/cockpit/langgraph/time-travel/angular/package.json +++ b/cockpit/langgraph/time-travel/angular/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "peerDependencies": { "@cacheplane/chat": "^0.0.1", - "@cacheplane/stream-resource": "^0.0.1", + "@cacheplane/angular": "^0.0.1", "@langchain/langgraph-sdk": "^0.0.36" }, "license": "PolyForm-Noncommercial-1.0.0", diff --git a/cockpit/langgraph/time-travel/angular/prompts/time-travel.md b/cockpit/langgraph/time-travel/angular/prompts/time-travel.md index 0bb54152f..ac1113dfd 100644 --- a/cockpit/langgraph/time-travel/angular/prompts/time-travel.md +++ b/cockpit/langgraph/time-travel/angular/prompts/time-travel.md @@ -2,4 +2,4 @@ This capability demonstrates LangGraph's time-travel feature — replaying or branching from any past checkpoint — using the `@cacheplane/chat` Angular component library. The `` lets the user scrub through the full checkpoint history of a thread and fork execution from any historical state. -Key components used: ``, ``. The slider reads checkpoint metadata from the thread state exposed by `streamResource` and emits a `checkpointId` that is passed back to the graph to resume from that point in history. +Key components used: ``, ``. The slider reads checkpoint metadata from the thread state exposed by `agent` and emits a `checkpointId` that is passed back to the graph to resume from that point in history. diff --git a/cockpit/langgraph/time-travel/angular/src/app/app.config.ts b/cockpit/langgraph/time-travel/angular/src/app/app.config.ts index b52a916ac..1e72bb3c9 100644 --- a/cockpit/langgraph/time-travel/angular/src/app/app.config.ts +++ b/cockpit/langgraph/time-travel/angular/src/app/app.config.ts @@ -1,12 +1,12 @@ // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; import { provideChat } from '@cacheplane/chat'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ apiUrl: environment.langGraphApiUrl }), + provideAgent({ apiUrl: environment.langGraphApiUrl }), provideChat({}), ], }; diff --git a/cockpit/langgraph/time-travel/angular/src/app/time-travel.component.ts b/cockpit/langgraph/time-travel/angular/src/app/time-travel.component.ts index aab762004..ae21482b1 100644 --- a/cockpit/langgraph/time-travel/angular/src/app/time-travel.component.ts +++ b/cockpit/langgraph/time-travel/angular/src/app/time-travel.component.ts @@ -1,7 +1,7 @@ import { Component, computed, signal } from '@angular/core'; import { ChatComponent } from '@cacheplane/chat'; -import { streamResource } from '@cacheplane/stream-resource'; -import type { ThreadState } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; +import type { ThreadState } from '@cacheplane/angular'; import { environment } from '../environments/environment'; /** @@ -101,7 +101,7 @@ import { environment } from '../environments/environment'; `, }) export class TimeTravelComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ apiUrl: environment.langGraphApiUrl, assistantId: environment.streamingAssistantId, }); diff --git a/cockpit/langgraph/time-travel/python/docs/guide.md b/cockpit/langgraph/time-travel/python/docs/guide.md index ff4ef7661..63d5bace1 100644 --- a/cockpit/langgraph/time-travel/python/docs/guide.md +++ b/cockpit/langgraph/time-travel/python/docs/guide.md @@ -1,29 +1,29 @@ -# Time Travel with stream-resource +# Time Travel with angular -Build a chat interface with time travel using `streamResource()` from -`@cacheplane/stream-resource`. Browse the checkpoint history via `stream.history()`, +Build a chat interface with time travel using `agent()` from +`@cacheplane/angular`. Browse the checkpoint history via `stream.history()`, see the active branch via `stream.branch()`, and fork the conversation from any past state with `stream.setBranch(checkpointId)`. -Add time travel to this Angular component using `streamResource()` from `@cacheplane/stream-resource`. Display checkpoint history from `stream.history()` in the sidebar. Highlight the active branch using `stream.branch()`. Call `stream.setBranch(id)` when the user clicks a checkpoint to fork the conversation from that point. +Add time travel to this Angular component using `agent()` from `@cacheplane/angular`. Display checkpoint history from `stream.history()` in the sidebar. Highlight the active branch using `stream.branch()`. Call `stream.setBranch(id)` when the user clicks a checkpoint to fork the conversation from that point. -Set up `provideStreamResource()` in your app config with the LangGraph API URL: +Set up `provideAgent()` in your app config with the LangGraph API URL: ```typescript // app.config.ts import { ApplicationConfig } from '@angular/core'; -import { provideStreamResource } from '@cacheplane/stream-resource'; +import { provideAgent } from '@cacheplane/angular'; export const appConfig: ApplicationConfig = { providers: [ - provideStreamResource({ + provideAgent({ apiUrl: 'https://your-deployment.langgraph.app', }), ], @@ -33,15 +33,15 @@ export const appConfig: ApplicationConfig = { -In your component, call `streamResource()`. The history and branch signals are +In your component, call `agent()`. The history and branch signals are available automatically — no extra config needed: ```typescript // time-travel.component.ts -import { streamResource } from '@cacheplane/stream-resource'; +import { agent } from '@cacheplane/angular'; export class TimeTravelComponent { - protected readonly stream = streamResource({ + protected readonly stream = agent({ assistantId: 'time-travel', }); } diff --git a/docs/limitations.md b/docs/limitations.md index 875bb25e3..49b9e2935 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -1,4 +1,4 @@ -# Angular Stream Resource — Limitations vs React useStream() +# Angular Agent Framework — Limitations vs React useStream() Features that are technically impossible or behaviorally degraded when porting LangGraph's React `useStream()` hook to Angular. @@ -19,7 +19,7 @@ Rapid token-by-token streaming may produce more intermediate renders than the React equivalent. **Workaround:** Use the `throttle` option to coalesce rapid updates: -`streamResource({ throttle: 50, ... })`. This applies +`agent({ throttle: 50, ... })`. This applies `throttleTime(50ms, { leading: true, trailing: true })` to the `values$` and `messages$` streams. @@ -30,7 +30,7 @@ and `messages$` streams. **React behavior:** LangGraph UI components can render on the server via React Server Components, enabling SSR of streamed AI responses. -**Angular behavior:** `streamResource()` requires a browser environment +**Angular behavior:** `agent()` requires a browser environment and an injection context. Angular has no equivalent of React Server Components. Server-side rendering of streaming content is not supported. @@ -45,7 +45,7 @@ development to detect side effects. Tests written expecting this behavior will not port directly. **Angular behavior:** Angular has no `StrictMode` double-invocation -equivalent. `streamResource()` is called once. No behavioral impact. +equivalent. `agent()` is called once. No behavioral impact. **Workaround:** Not needed. Simply omit double-invocation assumptions from ported test patterns. diff --git a/docs/superpowers/context/2026-04-06-chat-library-continuation.md b/docs/superpowers/context/2026-04-06-chat-library-continuation.md index 5ce45d05c..661ca1778 100644 --- a/docs/superpowers/context/2026-04-06-chat-library-continuation.md +++ b/docs/superpowers/context/2026-04-06-chat-library-continuation.md @@ -59,7 +59,7 @@ Two-layer Angular chat library: headless primitives + prebuilt Tailwind composit **Tests:** 112 passing. -**Peer deps:** `@cacheplane/render`, `@cacheplane/stream-resource`, `@angular/core`, `@angular/common`, `@langchain/core` +**Peer deps:** `@cacheplane/render`, `@cacheplane/angular`, `@angular/core`, `@angular/common`, `@langchain/core` ### Cockpit Integration — 14 Angular Examples @@ -129,7 +129,7 @@ All 14 standalone Angular apps consuming @cacheplane/chat, each with Angular CLI | AI message style | No bubble, plain text + avatar | ChatGPT pattern | | Theming | CSS custom properties on `:host` | No runtime overhead, works with any CSS framework | | Template overrides | `chatMessageTemplate` directive | Full rendering control per message type | -| State ownership | Consumer passes StreamResourceRef | Chat components never create it internally | +| State ownership | Consumer passes AgentRef | Chat components never create it internally | | Rendering | ngTemplateOutlet recursion | Proven pattern from hashbrown | --- @@ -140,7 +140,7 @@ All 14 standalone Angular apps consuming @cacheplane/chat, each with Angular CLI libs/render/ # @cacheplane/render libs/chat/ # @cacheplane/chat libs/chat/src/lib/styles/chat-theme.css # CSS custom properties -libs/stream-resource/ # @cacheplane/stream-resource (existing) +libs/angular/ # @cacheplane/angular (existing) cockpit/langgraph/*/angular/ # 8 LangGraph examples cockpit/deep-agents/*/angular/ # 6 Deep Agents examples apps/cockpit/ # Next.js cockpit shell @@ -170,7 +170,7 @@ npx tsx apps/cockpit/scripts/serve-example.ts --capability=streaming npx tsx apps/cockpit/scripts/serve-example.ts --all # Test -npx nx test render && npx nx test chat && npx nx test stream-resource +npx nx test render && npx nx test chat && npx nx test angular # Build all examples npx nx run-many -t build --projects='cockpit-*-angular' diff --git a/docs/superpowers/plans/2026-03-17-angular-library.md b/docs/superpowers/plans/2026-03-17-angular-library.md index d9fddd2a1..183c3f458 100644 --- a/docs/superpowers/plans/2026-03-17-angular-library.md +++ b/docs/superpowers/plans/2026-03-17-angular-library.md @@ -2,9 +2,9 @@ > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Build and publish the `stream-resource` Angular 20+ library — a full-parity implementation of LangGraph's `useStream()` React hook using Angular Signals and RxJS. +**Goal:** Build and publish the `angular` Angular 20+ library — a full-parity implementation of LangGraph's `useStream()` React hook using Angular Signals and RxJS. -**Architecture:** `streamResource()` creates 12 `BehaviorSubject`s at injection context time, bridges them to LangGraph's `StreamManager` via `stream-manager.bridge.ts`, and exposes all state as Angular Signals via `toSignal()`. The public surface duck-types Angular's `ResourceRef` while adding the full `useStream()` streaming API. +**Architecture:** `agent()` creates 12 `BehaviorSubject`s at injection context time, bridges them to LangGraph's `StreamManager` via `stream-manager.bridge.ts`, and exposes all state as Angular Signals via `toSignal()`. The public surface duck-types Angular's `ResourceRef` while adding the full `useStream()` streaming API. **Tech Stack:** Angular 20+, RxJS, `@langchain/langgraph-sdk`, `ng-packagr`, Nx, Vitest, TypeScript @@ -13,14 +13,14 @@ ## File Map ``` -libs/stream-resource/ +libs/angular/ ├── src/ │ ├── lib/ -│ │ ├── stream-resource.fn.ts # streamResource() entry point -│ │ ├── stream-resource.types.ts # All public + internal types -│ │ ├── stream-resource.provider.ts # provideStreamResource() + injection token +│ │ ├── angular.fn.ts # agent() entry point +│ │ ├── angular.types.ts # All public + internal types +│ │ ├── angular.provider.ts # provideAgent() + injection token │ │ ├── transport/ -│ │ │ ├── transport.interface.ts # StreamResourceTransport interface +│ │ │ ├── transport.interface.ts # AgentTransport interface │ │ │ ├── fetch-stream.transport.ts # Default HTTP/SSE transport │ │ │ └── mock-stream.transport.ts # Test transport (exported publicly) │ │ └── internals/ @@ -48,7 +48,7 @@ libs/stream-resource/ - [ ] **Step 1: Install Nx and create the integrated monorepo** ```bash -cd /Users/blove/repos/stream-resource +cd /Users/blove/repos/angular npx create-nx-workspace@latest . \ --preset=empty \ --nxCloud=skip \ @@ -83,19 +83,19 @@ git commit -m "chore: scaffold Nx monorepo" ## Task 2: Generate Angular Library **Files:** -- Create: `libs/stream-resource/` (full structure) -- Create: `libs/stream-resource/src/public-api.ts` -- Create: `libs/stream-resource/ng-package.json` -- Create: `libs/stream-resource/project.json` -- Create: `libs/stream-resource/vite.config.mts` +- Create: `libs/angular/` (full structure) +- Create: `libs/angular/src/public-api.ts` +- Create: `libs/angular/ng-package.json` +- Create: `libs/angular/project.json` +- Create: `libs/angular/vite.config.mts` - [ ] **Step 1: Generate the publishable Angular library** ```bash -npx nx g @nx/angular:library stream-resource \ +npx nx g @nx/angular:library angular \ --publishable \ - --importPath=stream-resource \ - --directory=libs/stream-resource \ + --importPath=angular \ + --directory=libs/angular \ --standalone \ --unitTestRunner=none \ --skipModule @@ -109,7 +109,7 @@ npm install --save-dev vitest @vitest/coverage-v8 jsdom @angular/core/testing - [ ] **Step 3: Create `vite.config.mts`** -Create `libs/stream-resource/vite.config.mts`: +Create `libs/angular/vite.config.mts`: ```typescript import { defineConfig } from 'vite'; @@ -134,13 +134,13 @@ import '@angular/core/testing'; - [ ] **Step 5: Update `project.json` to use Vitest** -In `libs/stream-resource/project.json`, replace the `test` target with: +In `libs/angular/project.json`, replace the `test` target with: ```json "test": { "executor": "@nx/vite:test", "options": { - "configFile": "libs/stream-resource/vite.config.mts" + "configFile": "libs/angular/vite.config.mts" } } ``` @@ -148,10 +148,10 @@ In `libs/stream-resource/project.json`, replace the `test` target with: - [ ] **Step 6: Verify the library builds** ```bash -npx nx build stream-resource +npx nx build angular ``` -Expected: build succeeds, output in `dist/libs/stream-resource` +Expected: build succeeds, output in `dist/libs/angular` - [ ] **Step 7: Commit** @@ -165,11 +165,11 @@ git commit -m "chore: generate publishable Angular library with Vitest" ## Task 3: Types Foundation **Files:** -- Create: `libs/stream-resource/src/lib/stream-resource.types.ts` +- Create: `libs/angular/src/lib/angular.types.ts` - [ ] **Step 1: Write types file** -Create `libs/stream-resource/src/lib/stream-resource.types.ts`: +Create `libs/angular/src/lib/angular.types.ts`: ```typescript import { Signal, ResourceStatus } from '@angular/core'; @@ -199,7 +199,7 @@ export interface StreamEvent { [key: string]: unknown; } -export interface StreamResourceTransport { +export interface AgentTransport { stream( assistantId: string, threadId: string | null, @@ -218,7 +218,7 @@ export interface StreamResourceTransport { // ── Options ────────────────────────────────────────────────────────────────── -export interface StreamResourceOptions { +export interface AgentOptions { apiUrl: string; assistantId: string; threadId?: Signal | string | null; @@ -227,7 +227,7 @@ export interface StreamResourceOptions { messagesKey?: string; throttle?: number | false; toMessage?: (msg: unknown) => BaseMessage; - transport?: StreamResourceTransport; + transport?: AgentTransport; filterSubagentMessages?: boolean; subagentToolNames?: string[]; } @@ -241,9 +241,9 @@ export interface SubagentStreamRef { messages: Signal; } -// ── StreamResourceRef ──────────────────────────────────────────────────────── +// ── AgentRef ──────────────────────────────────────────────────────── -export interface StreamResourceRef { +export interface AgentRef { // ResourceRef compatible members (duck-typed, not inherited) value: Signal; status: Signal; @@ -307,7 +307,7 @@ npm install @langchain/langgraph-sdk @langchain/core rxjs - [ ] **Step 3: Verify TypeScript compiles** ```bash -npx nx build stream-resource +npx nx build angular ``` Expected: no TypeScript errors @@ -315,8 +315,8 @@ Expected: no TypeScript errors - [ ] **Step 4: Commit** ```bash -git add libs/stream-resource/src/lib/stream-resource.types.ts -git commit -m "feat(stream-resource): add type definitions" +git add libs/angular/src/lib/angular.types.ts +git commit -m "feat(angular): add type definitions" ``` --- @@ -324,53 +324,53 @@ git commit -m "feat(stream-resource): add type definitions" ## Task 4: Transport Layer **Files:** -- Create: `libs/stream-resource/src/lib/transport/transport.interface.ts` -- Create: `libs/stream-resource/src/lib/transport/fetch-stream.transport.ts` -- Create: `libs/stream-resource/src/lib/transport/mock-stream.transport.ts` -- Test: `libs/stream-resource/src/lib/transport/mock-stream.transport.spec.ts` +- Create: `libs/angular/src/lib/transport/transport.interface.ts` +- Create: `libs/angular/src/lib/transport/fetch-stream.transport.ts` +- Create: `libs/angular/src/lib/transport/mock-stream.transport.ts` +- Test: `libs/angular/src/lib/transport/mock-stream.transport.spec.ts` - [ ] **Step 1: Create transport interface** -Create `libs/stream-resource/src/lib/transport/transport.interface.ts`: +Create `libs/angular/src/lib/transport/transport.interface.ts`: ```typescript -export { StreamResourceTransport, StreamEvent } from '../stream-resource.types'; +export { AgentTransport, StreamEvent } from '../angular.types'; ``` -- [ ] **Step 2: Write failing tests for MockStreamTransport** +- [ ] **Step 2: Write failing tests for MockAgentTransport** -Create `libs/stream-resource/src/lib/transport/mock-stream.transport.spec.ts`: +Create `libs/angular/src/lib/transport/mock-stream.transport.spec.ts`: ```typescript import { describe, it, expect, beforeEach } from 'vitest'; -import { MockStreamTransport } from './mock-stream.transport'; +import { MockAgentTransport } from './mock-stream.transport'; -describe('MockStreamTransport', () => { +describe('MockAgentTransport', () => { it('returns empty batch when no script provided', () => { - const t = new MockStreamTransport(); + const t = new MockAgentTransport(); expect(t.nextBatch()).toEqual([]); }); it('returns batches in order from script', () => { const batch1 = [{ type: 'values' as const, values: {} }]; const batch2 = [{ type: 'error' as const, error: 'oops' }]; - const t = new MockStreamTransport([batch1, batch2]); + const t = new MockAgentTransport([batch1, batch2]); expect(t.nextBatch()).toEqual(batch1); expect(t.nextBatch()).toEqual(batch2); }); it('returns empty batch when script exhausted', () => { - const t = new MockStreamTransport([[{ type: 'values' as const, values: {} }]]); + const t = new MockAgentTransport([[{ type: 'values' as const, values: {} }]]); t.nextBatch(); expect(t.nextBatch()).toEqual([]); }); it('isStreaming returns false initially', () => { - expect(new MockStreamTransport().isStreaming()).toBe(false); + expect(new MockAgentTransport().isStreaming()).toBe(false); }); it('emit() triggers events on the stream iterable', async () => { - const t = new MockStreamTransport(); + const t = new MockAgentTransport(); const events: unknown[] = []; const ac = new AbortController(); const iter = t.stream('agent', null, {}, ac.signal); @@ -384,7 +384,7 @@ describe('MockStreamTransport', () => { }); it('emitError() causes stream to throw', async () => { - const t = new MockStreamTransport(); + const t = new MockAgentTransport(); const ac = new AbortController(); const iter = t.stream('agent', null, {}, ac.signal); t.emitError(new Error('transport error')); @@ -398,19 +398,19 @@ describe('MockStreamTransport', () => { - [ ] **Step 3: Run tests to verify they fail** ```bash -npx nx test stream-resource --testFile=src/lib/transport/mock-stream.transport.spec.ts +npx nx test angular --testFile=src/lib/transport/mock-stream.transport.spec.ts ``` -Expected: FAIL — `MockStreamTransport` not found +Expected: FAIL — `MockAgentTransport` not found -- [ ] **Step 4: Implement MockStreamTransport** +- [ ] **Step 4: Implement MockAgentTransport** -Create `libs/stream-resource/src/lib/transport/mock-stream.transport.ts`: +Create `libs/angular/src/lib/transport/mock-stream.transport.ts`: ```typescript -import { StreamResourceTransport, StreamEvent } from '../stream-resource.types'; +import { AgentTransport, StreamEvent } from '../angular.types'; -export class MockStreamTransport implements StreamResourceTransport { +export class MockAgentTransport implements AgentTransport { private script: StreamEvent[][]; private scriptIndex = 0; private streaming = false; @@ -482,13 +482,13 @@ export class MockStreamTransport implements StreamResourceTransport { - [ ] **Step 5: Create FetchStreamTransport** -Create `libs/stream-resource/src/lib/transport/fetch-stream.transport.ts`: +Create `libs/angular/src/lib/transport/fetch-stream.transport.ts`: ```typescript import { Client } from '@langchain/langgraph-sdk'; -import { StreamResourceTransport, StreamEvent } from '../stream-resource.types'; +import { AgentTransport, StreamEvent } from '../angular.types'; -export class FetchStreamTransport implements StreamResourceTransport { +export class FetchStreamTransport implements AgentTransport { private client: Client; private onThreadId?: (id: string) => void; @@ -542,7 +542,7 @@ export class FetchStreamTransport implements StreamResourceTransport { - [ ] **Step 6: Run tests — should pass** ```bash -npx nx test stream-resource --testFile=src/lib/transport/mock-stream.transport.spec.ts +npx nx test angular --testFile=src/lib/transport/mock-stream.transport.spec.ts ``` Expected: all 6 tests PASS @@ -550,8 +550,8 @@ Expected: all 6 tests PASS - [ ] **Step 7: Commit** ```bash -git add libs/stream-resource/src/lib/transport/ -git commit -m "feat(stream-resource): add transport layer with MockStreamTransport" +git add libs/angular/src/lib/transport/ +git commit -m "feat(angular): add transport layer with MockAgentTransport" ``` --- @@ -559,20 +559,20 @@ git commit -m "feat(stream-resource): add transport layer with MockStreamTranspo ## Task 5: StreamManager Bridge **Files:** -- Create: `libs/stream-resource/src/lib/internals/stream-manager.bridge.ts` -- Test: `libs/stream-resource/src/lib/internals/stream-manager.bridge.spec.ts` +- Create: `libs/angular/src/lib/internals/stream-manager.bridge.ts` +- Test: `libs/angular/src/lib/internals/stream-manager.bridge.spec.ts` - [ ] **Step 1: Write failing tests** -Create `libs/stream-resource/src/lib/internals/stream-manager.bridge.spec.ts`: +Create `libs/angular/src/lib/internals/stream-manager.bridge.spec.ts`: ```typescript import { describe, it, expect, beforeEach, vi } from 'vitest'; import { BehaviorSubject, Subject } from 'rxjs'; import { ResourceStatus } from '@angular/core'; import { createStreamManagerBridge } from './stream-manager.bridge'; -import { MockStreamTransport } from '../transport/mock-stream.transport'; -import { StreamSubjects } from '../stream-resource.types'; +import { MockAgentTransport } from '../transport/mock-stream.transport'; +import { StreamSubjects } from '../angular.types'; import { of } from 'rxjs'; function makeSubjects(): StreamSubjects> { @@ -594,7 +594,7 @@ function makeSubjects(): StreamSubjects> { describe('createStreamManagerBridge', () => { it('creates a bridge with submit and stop methods', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const subjects = makeSubjects(); const destroy$ = new Subject(); const bridge = createStreamManagerBridge({ @@ -609,7 +609,7 @@ describe('createStreamManagerBridge', () => { }); it('sets status to Loading when submit is called', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const subjects = makeSubjects(); const destroy$ = new Subject(); const bridge = createStreamManagerBridge({ @@ -624,7 +624,7 @@ describe('createStreamManagerBridge', () => { }); it('sets status to Resolved when stream completes', async () => { - const transport = new MockStreamTransport([ + const transport = new MockAgentTransport([ [{ type: 'values', values: { count: 1 } }], ]); const subjects = makeSubjects(); @@ -646,7 +646,7 @@ describe('createStreamManagerBridge', () => { }); it('updates values$ when values event received', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const subjects = makeSubjects(); const destroy$ = new Subject(); const bridge = createStreamManagerBridge({ @@ -664,7 +664,7 @@ describe('createStreamManagerBridge', () => { }); it('sets status to Error on transport error', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const subjects = makeSubjects(); const destroy$ = new Subject(); const bridge = createStreamManagerBridge({ @@ -682,7 +682,7 @@ describe('createStreamManagerBridge', () => { }); it('stop() aborts the active stream', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const subjects = makeSubjects(); const destroy$ = new Subject(); const bridge = createStreamManagerBridge({ @@ -702,30 +702,30 @@ describe('createStreamManagerBridge', () => { - [ ] **Step 2: Run tests to verify they fail** ```bash -npx nx test stream-resource --testFile=src/lib/internals/stream-manager.bridge.spec.ts +npx nx test angular --testFile=src/lib/internals/stream-manager.bridge.spec.ts ``` Expected: FAIL — `createStreamManagerBridge` not found - [ ] **Step 3: Implement the bridge** -Create `libs/stream-resource/src/lib/internals/stream-manager.bridge.ts`: +Create `libs/angular/src/lib/internals/stream-manager.bridge.ts`: ```typescript import { ResourceStatus } from '@angular/core'; import { Observable, takeUntil } from 'rxjs'; import { - StreamResourceOptions, + AgentOptions, StreamSubjects, StreamEvent, - StreamResourceTransport, -} from '../stream-resource.types'; + AgentTransport, +} from '../angular.types'; import { FetchStreamTransport } from '../transport/fetch-stream.transport'; import { BagTemplate } from '@langchain/langgraph-sdk/ui'; import type { BaseMessage } from '@langchain/core/messages'; export interface StreamManagerBridgeOptions { - options: StreamResourceOptions; + options: AgentOptions; subjects: StreamSubjects; threadId$: Observable; destroy$: Observable; @@ -742,7 +742,7 @@ export interface StreamManagerBridge { export function createStreamManagerBridge( { options, subjects, threadId$, destroy$ }: StreamManagerBridgeOptions ): StreamManagerBridge { - const transport: StreamResourceTransport = + const transport: AgentTransport = options.transport ?? new FetchStreamTransport(options.apiUrl, options.onThreadId); let currentThreadId: string | null = null; @@ -880,7 +880,7 @@ export function createStreamManagerBridge( - [ ] **Step 4: Run tests — should pass** ```bash -npx nx test stream-resource --testFile=src/lib/internals/stream-manager.bridge.spec.ts +npx nx test angular --testFile=src/lib/internals/stream-manager.bridge.spec.ts ``` Expected: all 6 tests PASS @@ -888,29 +888,29 @@ Expected: all 6 tests PASS - [ ] **Step 5: Commit** ```bash -git add libs/stream-resource/src/lib/internals/ -git commit -m "feat(stream-resource): add StreamManager bridge" +git add libs/angular/src/lib/internals/ +git commit -m "feat(angular): add StreamManager bridge" ``` --- -## Task 6: `streamResource()` Function +## Task 6: `agent()` Function **Files:** -- Create: `libs/stream-resource/src/lib/stream-resource.fn.ts` -- Test: `libs/stream-resource/src/lib/stream-resource.fn.spec.ts` +- Create: `libs/angular/src/lib/angular.fn.ts` +- Test: `libs/angular/src/lib/angular.fn.spec.ts` - [ ] **Step 1: Write failing tests** -Create `libs/stream-resource/src/lib/stream-resource.fn.spec.ts`: +Create `libs/angular/src/lib/angular.fn.spec.ts`: ```typescript import { describe, it, expect, vi } from 'vitest'; import { TestBed } from '@angular/core/testing'; import { Component, signal } from '@angular/core'; import { ResourceStatus } from '@angular/core'; -import { streamResource } from './stream-resource.fn'; -import { MockStreamTransport } from './transport/mock-stream.transport'; +import { agent } from './angular.fn'; +import { MockAgentTransport } from './transport/mock-stream.transport'; function withInjectionContext(fn: () => T): T { let result!: T; @@ -918,11 +918,11 @@ function withInjectionContext(fn: () => T): T { return result; } -describe('streamResource', () => { +describe('agent', () => { it('returns a ref with initial idle status', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); expect(ref.status()).toBe(ResourceStatus.Idle); expect(ref.isLoading()).toBe(false); @@ -932,9 +932,9 @@ describe('streamResource', () => { }); it('returns initialValues in value() immediately', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ + agent({ apiUrl: '', assistantId: 'a', transport, initialValues: { count: 99 }, }) @@ -943,18 +943,18 @@ describe('streamResource', () => { }); it('status transitions to Loading on submit()', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.submit({}); expect(ref.isLoading()).toBe(true); }); it('hasValue becomes true after values event', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.submit({}); transport.emit([{ type: 'values', values: { x: 1 } }]); @@ -965,9 +965,9 @@ describe('streamResource', () => { }); it('error() is set and status is Error on transport error', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.submit({}); transport.emitError(new Error('fail')); @@ -977,9 +977,9 @@ describe('streamResource', () => { }); it('stop() resolves the stream and sets status to Resolved', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.submit({}); await ref.stop(); @@ -988,10 +988,10 @@ describe('streamResource', () => { }); it('reload() re-submits the last payload', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const submitSpy = vi.fn(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); await ref.submit({ msg: 'hello' }); transport.close(); @@ -1002,18 +1002,18 @@ describe('streamResource', () => { }); it('accepts threadId as a Signal', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const threadId = signal(null); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport, threadId }) + agent({ apiUrl: '', assistantId: 'a', transport, threadId }) ); expect(ref.status()).toBe(ResourceStatus.Idle); }); it('messages() updates when messages event received', async () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.submit({}); transport.emit([{ @@ -1026,9 +1026,9 @@ describe('streamResource', () => { }); it('switchThread() resets messages and values', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); const ref = withInjectionContext(() => - streamResource({ apiUrl: '', assistantId: 'a', transport }) + agent({ apiUrl: '', assistantId: 'a', transport }) ); ref.switchThread('thread-2'); expect(ref.messages()).toEqual([]); @@ -1039,14 +1039,14 @@ describe('streamResource', () => { - [ ] **Step 2: Run tests to verify they fail** ```bash -npx nx test stream-resource --testFile=src/lib/stream-resource.fn.spec.ts +npx nx test angular --testFile=src/lib/angular.fn.spec.ts ``` -Expected: FAIL — `streamResource` not found +Expected: FAIL — `agent` not found -- [ ] **Step 3: Implement `streamResource()`** +- [ ] **Step 3: Implement `agent()`** -Create `libs/stream-resource/src/lib/stream-resource.fn.ts`: +Create `libs/angular/src/lib/angular.fn.ts`: ```typescript import { @@ -1062,19 +1062,19 @@ import type { BaseMessage } from '@langchain/core/messages'; import type { BagTemplate, InferBag } from '@langchain/langgraph-sdk/ui'; import { - StreamResourceOptions, - StreamResourceRef, + AgentOptions, + AgentRef, StreamSubjects, SubagentStreamRef, -} from './stream-resource.types'; +} from './angular.types'; import { createStreamManagerBridge } from './internals/stream-manager.bridge'; -export function streamResource< +export function agent< T = Record, Bag extends BagTemplate = BagTemplate, >( - options: StreamResourceOptions>, -): StreamResourceRef> { + options: AgentOptions>, +): AgentRef> { // Injection context required const destroyRef = inject(DestroyRef); const destroy$ = new Subject(); @@ -1193,7 +1193,7 @@ export function streamResource< - [ ] **Step 4: Run tests — should pass** ```bash -npx nx test stream-resource --testFile=src/lib/stream-resource.fn.spec.ts +npx nx test angular --testFile=src/lib/angular.fn.spec.ts ``` Expected: all 10 tests PASS @@ -1201,7 +1201,7 @@ Expected: all 10 tests PASS - [ ] **Step 5: Run all library tests** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: all tests PASS @@ -1209,9 +1209,9 @@ Expected: all tests PASS - [ ] **Step 6: Commit** ```bash -git add libs/stream-resource/src/lib/stream-resource.fn.ts \ - libs/stream-resource/src/lib/stream-resource.fn.spec.ts -git commit -m "feat(stream-resource): implement streamResource() function" +git add libs/angular/src/lib/angular.fn.ts \ + libs/angular/src/lib/angular.fn.spec.ts +git commit -m "feat(angular): implement agent() function" ``` --- @@ -1219,32 +1219,32 @@ git commit -m "feat(stream-resource): implement streamResource() function" ## Task 7: Provider **Files:** -- Create: `libs/stream-resource/src/lib/stream-resource.provider.ts` -- Test: `libs/stream-resource/src/lib/stream-resource.provider.spec.ts` +- Create: `libs/angular/src/lib/angular.provider.ts` +- Test: `libs/angular/src/lib/angular.provider.spec.ts` - [ ] **Step 1: Write failing tests** -Create `libs/stream-resource/src/lib/stream-resource.provider.spec.ts`: +Create `libs/angular/src/lib/angular.provider.spec.ts`: ```typescript import { describe, it, expect } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { provideStreamResource, STREAM_RESOURCE_CONFIG } from './stream-resource.provider'; -import { MockStreamTransport } from './transport/mock-stream.transport'; +import { provideAgent, STREAM_RESOURCE_CONFIG } from './angular.provider'; +import { MockAgentTransport } from './transport/mock-stream.transport'; -describe('provideStreamResource', () => { +describe('provideAgent', () => { it('provides STREAM_RESOURCE_CONFIG token', () => { TestBed.configureTestingModule({ - providers: [provideStreamResource({ apiUrl: 'https://api.example.com' })], + providers: [provideAgent({ apiUrl: 'https://api.example.com' })], }); const config = TestBed.inject(STREAM_RESOURCE_CONFIG); expect(config.apiUrl).toBe('https://api.example.com'); }); it('provides custom transport via config', () => { - const transport = new MockStreamTransport(); + const transport = new MockAgentTransport(); TestBed.configureTestingModule({ - providers: [provideStreamResource({ apiUrl: '', transport })], + providers: [provideAgent({ apiUrl: '', transport })], }); const config = TestBed.inject(STREAM_RESOURCE_CONFIG); expect(config.transport).toBe(transport); @@ -1255,28 +1255,28 @@ describe('provideStreamResource', () => { - [ ] **Step 2: Run to verify failure** ```bash -npx nx test stream-resource --testFile=src/lib/stream-resource.provider.spec.ts +npx nx test angular --testFile=src/lib/angular.provider.spec.ts ``` Expected: FAIL - [ ] **Step 3: Implement provider** -Create `libs/stream-resource/src/lib/stream-resource.provider.ts`: +Create `libs/angular/src/lib/angular.provider.ts`: ```typescript import { InjectionToken, Provider } from '@angular/core'; -import { StreamResourceTransport } from './stream-resource.types'; +import { AgentTransport } from './angular.types'; -export interface StreamResourceConfig { +export interface AgentConfig { apiUrl?: string; - transport?: StreamResourceTransport; + transport?: AgentTransport; } export const STREAM_RESOURCE_CONFIG = - new InjectionToken('STREAM_RESOURCE_CONFIG'); + new InjectionToken('STREAM_RESOURCE_CONFIG'); -export function provideStreamResource(config: StreamResourceConfig): Provider { +export function provideAgent(config: AgentConfig): Provider { return { provide: STREAM_RESOURCE_CONFIG, useValue: config, @@ -1287,7 +1287,7 @@ export function provideStreamResource(config: StreamResourceConfig): Provider { - [ ] **Step 4: Run tests — should pass** ```bash -npx nx test stream-resource --testFile=src/lib/stream-resource.provider.spec.ts +npx nx test angular --testFile=src/lib/angular.provider.spec.ts ``` Expected: PASS @@ -1295,9 +1295,9 @@ Expected: PASS - [ ] **Step 5: Commit** ```bash -git add libs/stream-resource/src/lib/stream-resource.provider.ts \ - libs/stream-resource/src/lib/stream-resource.provider.spec.ts -git commit -m "feat(stream-resource): add provideStreamResource() provider" +git add libs/angular/src/lib/angular.provider.ts \ + libs/angular/src/lib/angular.provider.spec.ts +git commit -m "feat(angular): add provideAgent() provider" ``` --- @@ -1305,45 +1305,45 @@ git commit -m "feat(stream-resource): add provideStreamResource() provider" ## Task 8: Public API & Build Verification **Files:** -- Modify: `libs/stream-resource/src/public-api.ts` +- Modify: `libs/angular/src/public-api.ts` - [ ] **Step 1: Write the public API barrel** -Replace contents of `libs/stream-resource/src/public-api.ts`: +Replace contents of `libs/angular/src/public-api.ts`: ```typescript // Primary function -export { streamResource } from './lib/stream-resource.fn'; +export { agent } from './lib/angular.fn'; // Provider -export { provideStreamResource, STREAM_RESOURCE_CONFIG } from './lib/stream-resource.provider'; -export type { StreamResourceConfig } from './lib/stream-resource.provider'; +export { provideAgent, STREAM_RESOURCE_CONFIG } from './lib/angular.provider'; +export type { AgentConfig } from './lib/angular.provider'; // Public types export type { - StreamResourceOptions, - StreamResourceRef, - StreamResourceTransport, + AgentOptions, + AgentRef, + AgentTransport, StreamEvent, SubagentStreamRef, -} from './lib/stream-resource.types'; +} from './lib/angular.types'; -// Re-export from SDK (consumers import from stream-resource, not langgraph-sdk) +// Re-export from SDK (consumers import from angular, not langgraph-sdk) export type { BagTemplate, InferBag, Interrupt, ThreadState, SubmitOptions } - from './lib/stream-resource.types'; + from './lib/angular.types'; // Re-export ResourceStatus from Angular core for convenience export { ResourceStatus } from '@angular/core'; // Test utilities (always exported — tree-shaken in prod builds) -export { MockStreamTransport } from './lib/transport/mock-stream.transport'; +export { MockAgentTransport } from './lib/transport/mock-stream.transport'; export { FetchStreamTransport } from './lib/transport/fetch-stream.transport'; ``` - [ ] **Step 2: Run all tests** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: all tests PASS @@ -1351,16 +1351,16 @@ Expected: all tests PASS - [ ] **Step 3: Build the library in production mode** ```bash -npx nx build stream-resource --configuration=production +npx nx build angular --configuration=production ``` -Expected: successful build, output in `dist/libs/stream-resource` +Expected: successful build, output in `dist/libs/angular` - [ ] **Step 4: Verify the built package structure** ```bash -ls dist/libs/stream-resource/ -cat dist/libs/stream-resource/package.json +ls dist/libs/angular/ +cat dist/libs/angular/package.json ``` Expected: `fesm2022/`, `esm2022/`, `index.d.ts`, `package.json` with `exports` map @@ -1368,8 +1368,8 @@ Expected: `fesm2022/`, `esm2022/`, `index.d.ts`, `package.json` with `exports` m - [ ] **Step 5: Commit** ```bash -git add libs/stream-resource/src/public-api.ts -git commit -m "feat(stream-resource): finalize public API barrel exports" +git add libs/angular/src/public-api.ts +git commit -m "feat(angular): finalize public API barrel exports" ``` --- @@ -1384,7 +1384,7 @@ git commit -m "feat(stream-resource): finalize public API barrel exports" Create `docs/limitations.md`: ```markdown -# Angular Stream Resource — Angular Limitations vs React useStream() +# Angular Agent Framework — Angular Limitations vs React useStream() Features that are technically impossible or behaviorally degraded when porting LangGraph's React `useStream()` hook to Angular. @@ -1405,7 +1405,7 @@ Rapid token-by-token streaming may produce more intermediate renders than the React equivalent. **Workaround:** Use the `throttle` option to coalesce rapid updates: -`streamResource({ throttle: 50, ... })`. This applies +`agent({ throttle: 50, ... })`. This applies `throttleTime(50ms, { leading: true, trailing: true })` to the `values$` and `messages$` streams. @@ -1416,7 +1416,7 @@ and `messages$` streams. **React behavior:** LangGraph UI components can render on the server via React Server Components, enabling SSR of streamed AI responses. -**Angular behavior:** `streamResource()` requires a browser environment +**Angular behavior:** `agent()` requires a browser environment and an injection context. Angular has no equivalent of React Server Components. Server-side rendering of streaming content is not supported. @@ -1431,7 +1431,7 @@ development to detect side effects. Tests written expecting this behavior will not port directly. **Angular behavior:** Angular has no `StrictMode` double-invocation -equivalent. `streamResource()` is called once. No behavioral impact. +equivalent. `agent()` is called once. No behavioral impact. **Workaround:** Not needed. Simply omit double-invocation assumptions from ported test patterns. @@ -1535,11 +1535,11 @@ jobs: cache: npm - run: npm ci - name: Lint - run: npx nx lint stream-resource + run: npx nx lint angular - name: Test - run: npx nx test stream-resource --coverage + run: npx nx test angular --coverage - name: Build - run: npx nx build stream-resource --configuration=production + run: npx nx build angular --configuration=production ``` - [ ] **Step 2: Create publish workflow** @@ -1565,10 +1565,10 @@ jobs: cache: npm registry-url: https://registry.npmjs.org - run: npm ci - - run: npx nx test stream-resource - - run: npx nx build stream-resource --configuration=production + - run: npx nx test angular + - run: npx nx build angular --configuration=production - name: Publish to npm - run: npx nx-release-publish stream-resource + run: npx nx-release-publish angular env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ``` @@ -1576,7 +1576,7 @@ jobs: - [ ] **Step 3: Final test run** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: all tests PASS with coverage report @@ -1584,7 +1584,7 @@ Expected: all tests PASS with coverage report - [ ] **Step 4: Final build verification** ```bash -npx nx build stream-resource --configuration=production +npx nx build angular --configuration=production ``` Expected: clean build, no errors or warnings @@ -1611,7 +1611,7 @@ Create `LICENSE`: ``` MIT License (Non-Commercial Use Only) -Copyright (c) 2025 Angular Stream Resource Contributors +Copyright (c) 2025 Angular Agent Framework Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1642,11 +1642,11 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. Create `LICENSE-COMMERCIAL`: ``` -Angular Stream Resource Commercial License +Angular Agent Framework Commercial License -Copyright (c) 2025 Angular Stream Resource Contributors +Copyright (c) 2025 Angular Agent Framework Contributors -Commercial use of Angular Stream Resource requires a paid license. +Commercial use of Angular Agent Framework requires a paid license. DEVELOPER SEAT LICENSE: $500 per developer seat per year - Grants commercial use rights for one developer @@ -1656,7 +1656,7 @@ DEVELOPER SEAT LICENSE: $500 per developer seat per year APPLICATION DEPLOYMENT LICENSE: $2,000 per application - Required for each production application or service that uses - Angular Stream Resource commercially + Angular Agent Framework commercially - Covers all environments (development, staging, production) - One-time purchase per application @@ -1685,7 +1685,7 @@ git commit -m "docs: add MIT (non-commercial) and commercial license files" - [ ] **Run full test suite one last time** ```bash -npx nx test stream-resource --reporter=verbose +npx nx test angular --reporter=verbose ``` Expected: all tests pass @@ -1693,8 +1693,8 @@ Expected: all tests pass - [ ] **Build production artifact** ```bash -npx nx build stream-resource --configuration=production -ls -la dist/libs/stream-resource/ +npx nx build angular --configuration=production +ls -la dist/libs/angular/ ``` Expected: built package ready to publish @@ -1702,7 +1702,7 @@ Expected: built package ready to publish - [ ] **Verify package.json exports** ```bash -cat dist/libs/stream-resource/package.json | grep -A 20 '"exports"' +cat dist/libs/angular/package.json | grep -A 20 '"exports"' ``` -Expected: proper ESM/CJS exports map with `stream-resource` as the import path +Expected: proper ESM/CJS exports map with `angular` as the import path diff --git a/docs/superpowers/plans/2026-03-17-readme.md b/docs/superpowers/plans/2026-03-17-readme.md index eb3db5e66..76fbf7ceb 100644 --- a/docs/superpowers/plans/2026-03-17-readme.md +++ b/docs/superpowers/plans/2026-03-17-readme.md @@ -38,7 +38,7 @@ apps/website/public/assets/ **Visual specification:** - Background: `#080705` (near-black) - Text color: `#d4aa6a` (gold) -- Wordmark: "Angular Stream Resource" in EB Garamond-style serif paths +- Wordmark: "Angular Agent Framework" in EB Garamond-style serif paths - Subtitle: "The Enterprise Streaming Resource for LangChain and Angular" in lighter gold - Dimensions: 1200 × 300 (standard GitHub README banner ratio) - No JavaScript, no ``, no web fonts (paths only — renders everywhere) @@ -57,7 +57,7 @@ apps/website/public/assets/ - + Angular Stream Resource + >Angular Agent Framework - + streamResource() + font-size="15" font-weight="700" fill="#d4aa6a">agent() 12 BehaviorSubjects @@ -198,14 +198,14 @@ apps/website/public/assets/ font-family="'Courier New', monospace" font-size="11" fill="#7a6e5e" opacity="0.7">SSE / stream events - + BehaviorSubject.next() - + FetchStreamTransport | MockStreamTransport + font-size="11" fill="#7a6e5e" opacity="0.6">FetchStreamTransport | MockAgentTransport @@ -243,8 +243,8 @@ apps/website/public/assets/ ````markdown

    Angular Stream Resource — The Enterprise Streaming Resource for LangChain and Angular

    @@ -254,13 +254,13 @@ apps/website/public/assets/

    - - npm version + + npm version License: MIT (non-commercial) - + Angular 20+ @@ -270,14 +270,14 @@ apps/website/public/assets/ --- -`streamResource()` is the Angular equivalent of LangGraph's React `useStream()` hook — a full-parity implementation built on Angular Signals and the Angular Resource API. It gives enterprise Angular teams the same production-grade streaming primitives available to React developers on LangChain, without compromises or workarounds. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get reactive, signal-driven access to streaming state, messages, tool calls, interrupts, and thread history. +`agent()` is the Angular equivalent of LangGraph's React `useStream()` hook — a full-parity implementation built on Angular Signals and the Angular Resource API. It gives enterprise Angular teams the same production-grade streaming primitives available to React developers on LangChain, without compromises or workarounds. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get reactive, signal-driven access to streaming state, messages, tool calls, interrupts, and thread history. --- ## Install ```bash -npm install stream-resource +npm install angular ``` **Peer dependencies:** `@angular/core ^20.0.0`, `@angular/common ^20.0.0`, `@langchain/langgraph-sdk` @@ -288,7 +288,7 @@ npm install stream-resource ```typescript import { Component, signal } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; @Component({ selector: 'app-chat', @@ -307,7 +307,7 @@ import { streamResource } from 'stream-resource'; `, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ apiUrl: 'https://your-langgraph-platform.com', assistantId: 'my-agent', messagesKey: 'messages', @@ -325,7 +325,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp ## Feature Comparison -| Feature | `streamResource()` (Angular) | `useStream()` (React) | +| Feature | `agent()` (Angular) | `useStream()` (React) | |---|---|---| | Streaming state as reactive primitives | Angular Signals | React state | | Messages signal | `messages()` | `messages` | @@ -341,7 +341,7 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp | Submit | `submit(values, opts?)` | `submit(values, opts?)` | | Stop | `stop()` | `stop()` | | Reload last submission | `reload()` | — | -| Custom transport (for testing) | `MockStreamTransport` | mock fetch | +| Custom transport (for testing) | `MockAgentTransport` | mock fetch | | Angular `ResourceRef` compatibility | Full duck-type parity | N/A | | Angular 20+ Signals API | Native | N/A | | SSR / Server Components | Client-side only | React Server Components (React) | @@ -352,13 +352,13 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp

    Angular Stream Resource architecture: Angular Component → streamResource() → StreamManager Bridge → LangGraph Platform, with signals returned reactively

    -`streamResource()` creates 12 `BehaviorSubject`s at injection-context time — once, at component construction. The `StreamManager` bridge (the only file that touches `@langchain/langgraph-sdk/ui` internals) pushes stream events into those subjects. `toSignal()` converts each subject to an Angular Signal, also at construction time. Dynamic actions (`submit`, `stop`, `switchThread`) push into the existing subjects — no new subjects are ever created after construction. This architecture is required because `toSignal()` must be called in an injection context and cannot be called again later. +`agent()` creates 12 `BehaviorSubject`s at injection-context time — once, at component construction. The `StreamManager` bridge (the only file that touches `@langchain/langgraph-sdk/ui` internals) pushes stream events into those subjects. `toSignal()` converts each subject to an Angular Signal, also at construction time. Dynamic actions (`submit`, `stop`, `switchThread`) push into the existing subjects — no new subjects are ever created after construction. This architecture is required because `toSignal()` must be called in an injection context and cannot be called again later. --- @@ -371,27 +371,27 @@ That's it. `chat.messages()` is an Angular Signal. Bind it directly in your temp | **Application Deployment** | $2,000 / app | One-time per application — covers dev, staging, and prod | | **Enterprise** | Custom | Volume seats, unlimited deployments, SLA, dedicated support | -[Full pricing details and license terms →](https://stream-resource.vercel.app/pricing) +[Full pricing details and license terms →](https://angular.vercel.app/pricing) --- ## Documentation -- [Getting Started](https://stream-resource.vercel.app/docs/getting-started) -- [API Reference](https://stream-resource.vercel.app/api-reference) -- [Testing with MockStreamTransport](https://stream-resource.vercel.app/docs/testing) -- [Human-in-the-Loop / Interrupts](https://stream-resource.vercel.app/docs/interrupts) -- [Subagent Streaming](https://stream-resource.vercel.app/docs/subagents) -- [Angular Limitations vs React](https://stream-resource.vercel.app/docs/limitations) +- [Getting Started](https://angular.vercel.app/docs/getting-started) +- [API Reference](https://angular.vercel.app/api-reference) +- [Testing with MockAgentTransport](https://angular.vercel.app/docs/testing) +- [Human-in-the-Loop / Interrupts](https://angular.vercel.app/docs/interrupts) +- [Subagent Streaming](https://angular.vercel.app/docs/subagents) +- [Angular Limitations vs React](https://angular.vercel.app/docs/limitations) --- ## License -`stream-resource` is dual-licensed: +`angular` is dual-licensed: - **MIT License** — free for non-commercial use (personal projects, open source, academic, non-profit). See [`LICENSE`](./LICENSE). -- **Commercial License** — required for any for-profit or revenue-generating use. See [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL) and [pricing](https://stream-resource.vercel.app/pricing). +- **Commercial License** — required for any for-profit or revenue-generating use. See [`LICENSE-COMMERCIAL`](./LICENSE-COMMERCIAL) and [pricing](https://angular.vercel.app/pricing). Non-commercial use is defined as: personal projects with no revenue, OSI-licensed open source projects, academic and research use, and internal tooling at non-profit organizations. All other use requires a commercial license. ```` @@ -416,6 +416,6 @@ These checks are visual / manual — run them after each deliverable: - **DRY:** `hero.svg` and `arch-diagram.svg` live in `apps/website/public/assets/` — one copy, referenced by both the README (via Vercel URL) and the website. No duplication. - **YAGNI:** No animation in the SVGs at this stage — animation is the website plan's responsibility. These are static assets. -- **Placeholder URLs:** All `https://stream-resource.vercel.app/...` URLs are placeholders matching the expected Vercel deployment path. They will resolve once the website is deployed. The README is written against these paths intentionally — GitHub will render the images once the site is live. +- **Placeholder URLs:** All `https://angular.vercel.app/...` URLs are placeholders matching the expected Vercel deployment path. They will resolve once the website is deployed. The README is written against these paths intentionally — GitHub will render the images once the site is live. - **No web fonts in SVGs:** System serif fallback (`Georgia, 'Times New Roman', serif`) is used in the SVGs to ensure they render correctly on GitHub's SVG renderer without font loading. - **Commits after each deliverable:** One commit per deliverable, not a single bulk commit. diff --git a/docs/superpowers/plans/2026-03-17-website.md b/docs/superpowers/plans/2026-03-17-website.md index 90481cc1c..e21ebae55 100644 --- a/docs/superpowers/plans/2026-03-17-website.md +++ b/docs/superpowers/plans/2026-03-17-website.md @@ -2,7 +2,7 @@ > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Build the Angular Stream Resource marketing website — landing page, pricing, docs, and live demo — deployed to Vercel. +**Goal:** Build the Angular Agent Framework marketing website — landing page, pricing, docs, and live demo — deployed to Vercel. **Architecture:** Next.js 15 App Router with Tailwind CSS dark luxury design system, Framer Motion scroll-triggered animations, SVG architecture diagram with `animateMotion`, MDX docs with Claude-generated narrative content, and an embedded Angular Elements live demo. @@ -56,7 +56,7 @@ apps/website/ apps/demo/ # Angular Elements demo app ├── src/app/ │ └── chat-demo/ -│ ├── chat-demo.component.ts # Web component using streamResource() +│ ├── chat-demo.component.ts # Web component using agent() │ └── chat-demo.module.ts └── project.json ``` @@ -73,7 +73,7 @@ apps/demo/ # Angular Elements demo app - [ ] **Step 1: Generate Next.js app within existing Nx monorepo** ```bash -cd /path/to/stream-resource +cd /path/to/angular npx nx g @nx/next:app website \ --directory=apps/website \ --style=css \ @@ -236,7 +236,7 @@ export function Nav() {
    ); } @@ -1486,8 +1486,8 @@ const OUTPUT = path.join(__dirname, '../content/api-docs.json'); async function main() { const app = await TypeDoc.Application.bootstrapWithPlugins({ - entryPoints: [path.join(__dirname, '../../../libs/stream-resource/src/public-api.ts')], - tsconfig: path.join(__dirname, '../../../libs/stream-resource/tsconfig.lib.json'), + entryPoints: [path.join(__dirname, '../../../libs/angular/src/public-api.ts')], + tsconfig: path.join(__dirname, '../../../libs/angular/tsconfig.lib.json'), json: OUTPUT, skipErrorChecking: true, }); @@ -1517,11 +1517,11 @@ const DOCS_DIR = path.join(__dirname, '../content/docs'); const API_DOCS = path.join(__dirname, '../content/api-docs.json'); const PAGES = [ - { slug: 'getting-started', prompt: 'Write a Getting Started guide for stream-resource: installation, peer dependencies, first component, and provideStreamResource() setup. Target: senior Angular engineer who knows LangChain.' }, - { slug: 'stream-resource-fn', prompt: 'Write a deep-dive API guide for the streamResource() function: all options, the StreamResourceRef surface, signal lifecycle, and injection context requirements.' }, - { slug: 'testing', prompt: 'Write a Testing guide for stream-resource using MockStreamTransport: unit tests with Vitest, test harness setup, scripted event sequences, and error simulation patterns.' }, - { slug: 'transport', prompt: 'Write a Transport guide for stream-resource: FetchStreamTransport, custom transport implementation, auth header injection patterns, and onThreadId usage.' }, - { slug: 'limitations', prompt: 'Write a Limitations guide explaining the behavioral differences between streamResource() and React useStream(): concurrent-mode batching, Server Components, and the v1 deferred features (toolProgress, getMessagesMetadata).' }, + { slug: 'getting-started', prompt: 'Write a Getting Started guide for angular: installation, peer dependencies, first component, and provideAgent() setup. Target: senior Angular engineer who knows LangChain.' }, + { slug: 'angular-fn', prompt: 'Write a deep-dive API guide for the agent() function: all options, the AgentRef surface, signal lifecycle, and injection context requirements.' }, + { slug: 'testing', prompt: 'Write a Testing guide for angular using MockAgentTransport: unit tests with Vitest, test harness setup, scripted event sequences, and error simulation patterns.' }, + { slug: 'transport', prompt: 'Write a Transport guide for angular: FetchStreamTransport, custom transport implementation, auth header injection patterns, and onThreadId usage.' }, + { slug: 'limitations', prompt: 'Write a Limitations guide explaining the behavioral differences between agent() and React useStream(): concurrent-mode batching, Server Components, and the v1 deferred features (toolProgress, getMessagesMetadata).' }, ]; async function main() { @@ -1539,7 +1539,7 @@ async function main() { max_tokens: 4096, messages: [{ role: 'user', - content: `You are a technical writer creating documentation for stream-resource, an Angular 20+ library. + content: `You are a technical writer creating documentation for angular, an Angular 20+ library. API shape (TypeDoc JSON summary): ${JSON.stringify(apiDocs).slice(0, 8000)} @@ -1625,7 +1625,7 @@ Create `apps/demo/src/app/chat-demo/chat-demo.component.ts`: ```typescript import { Component, Input, OnInit, ViewEncapsulation, Injector, runInInjectionContext } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -1680,18 +1680,18 @@ export class ChatDemoComponent implements OnInit { @Input() apiUrl = ''; @Input() assistantId = 'agent'; - stream!: ReturnType; + stream!: ReturnType; - // Injector is stored so we can call streamResource() in runInInjectionContext. - // streamResource() MUST be called in an injection context. @Input() values + // Injector is stored so we can call agent() in runInInjectionContext. + // agent() MUST be called in an injection context. @Input() values // aren't resolved until ngOnInit, so we cannot call it in the constructor. constructor(private injector: Injector) {} ngOnInit() { // runInInjectionContext re-establishes the injection context so that - // streamResource() can call inject(DestroyRef) and toSignal() internally. + // agent() can call inject(DestroyRef) and toSignal() internally. this.stream = runInInjectionContext(this.injector, () => - streamResource({ + agent({ apiUrl: this.apiUrl, assistantId: this.assistantId, }) @@ -1815,12 +1815,12 @@ test.describe('Landing page', () => { test('renders architecture diagram SVG', async ({ page }) => { await page.goto('/'); - await expect(page.locator('svg[aria-label="Angular Stream Resource architecture diagram"]')).toBeVisible(); + await expect(page.locator('svg[aria-label="Angular Agent Framework architecture diagram"]')).toBeVisible(); }); test('renders install command', async ({ page }) => { await page.goto('/'); - await expect(page.getByText('npm install stream-resource')).toBeVisible(); + await expect(page.getByText('npm install angular')).toBeVisible(); }); test('renders feature cards', async ({ page }) => { @@ -1833,7 +1833,7 @@ test.describe('Landing page', () => { test('mobile: hero is readable at 375px', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); await page.goto('/'); - await expect(page.getByText('npm install stream-resource')).toBeVisible(); + await expect(page.getByText('npm install angular')).toBeVisible(); }); }); ``` @@ -1888,13 +1888,13 @@ import { test, expect } from '@playwright/test'; test.describe('Docs page', () => { test('renders docs index', async ({ page }) => { await page.goto('/docs'); - await expect(page.getByText('Angular Stream Resource Documentation')).toBeVisible(); + await expect(page.getByText('Angular Agent Framework Documentation')).toBeVisible(); }); test('API reference renders signal table', async ({ page }) => { await page.goto('/api-reference'); - await expect(page.getByText('streamResource() Options')).toBeVisible(); - await expect(page.getByText('StreamResourceRef Members')).toBeVisible(); + await expect(page.getByText('agent() Options')).toBeVisible(); + await expect(page.getByText('AgentRef Members')).toBeVisible(); await expect(page.getByText('assistantId')).toBeVisible(); }); diff --git a/docs/superpowers/plans/2026-03-18-agentic-additions.md b/docs/superpowers/plans/2026-03-18-agentic-additions.md index 32dc09acd..5e300bb8e 100644 --- a/docs/superpowers/plans/2026-03-18-agentic-additions.md +++ b/docs/superpowers/plans/2026-03-18-agentic-additions.md @@ -1,10 +1,10 @@ -# Angular Stream Resource — Agentic Additions Implementation Plan +# Angular Agent Framework — Agentic Additions Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. Set up an isolated workspace first using superpowers:using-git-worktrees. **Goal:** Add the hero redesign, agentic docs infrastructure, and MCP server package described in the two approved specs, layered on top of the base website plan (`2026-03-18-website.md`). -**Architecture:** Three independent additions to the monorepo: (1) replace `Hero.tsx` with a two-column `HeroTwoCol.tsx` + `GenerativeUIFrame.tsx` SVG animation; (2) add `CopyPromptButton`, prompt files, `llms.txt` routes, `CLAUDE.md`/`AGENTS.md`, and a `getPromptBySlug` loader to the website; (3) scaffold `packages/mcp/` as a new Nx library publishing `@stream-resource/mcp` with six MCP tools backed by TypeDoc JSON. +**Architecture:** Three independent additions to the monorepo: (1) replace `Hero.tsx` with a two-column `HeroTwoCol.tsx` + `GenerativeUIFrame.tsx` SVG animation; (2) add `CopyPromptButton`, prompt files, `llms.txt` routes, `CLAUDE.md`/`AGENTS.md`, and a `getPromptBySlug` loader to the website; (3) scaffold `packages/mcp/` as a new Nx library publishing `@angular/mcp` with six MCP tools backed by TypeDoc JSON. **Tech Stack:** Next.js 15, TypeScript, `@modelcontextprotocol/sdk`, TypeDoc, Nx @@ -49,7 +49,7 @@ packages/mcp/ │ │ ├── search-docs.ts │ │ ├── get-example.ts │ │ ├── scaffold-chat-component.ts -│ │ ├── add-stream-resource.ts +│ │ ├── add-angular.ts │ │ └── get-thread-persistence-pattern.ts │ └── data/ │ └── loader.ts # Reads api-docs.json, exposes typed helpers @@ -74,7 +74,7 @@ Download Angular logo SVG into the project: ```bash mkdir -p apps/website/public/logos curl -o apps/website/public/logos/angular.svg \ - "https://angular.dev/assets/icons/logo.svg" 2>/dev/null || \ + "https://stream-resource.dev/assets/icons/logo.svg" 2>/dev/null || \ echo '', ``` @@ -395,7 +395,7 @@ export async function HeroTwoCol() { fontSize: 12, color: '#4A527A', }}> - npm install stream-resource + npm install angular
    @@ -535,17 +535,17 @@ export function getPromptBySlug(slug: string[]): string | null { Create `apps/website/content/prompts/getting-started.md`: ``` -Add stream-resource to my Angular 20+ application. +Add angular to my Angular 20+ application. -Install: npm install stream-resource +Install: npm install angular -1. In app.config.ts, add provideStreamResource({ apiUrl: 'http://localhost:2024' }) to the providers array. Import it from 'stream-resource'. +1. In app.config.ts, add provideAgent({ apiUrl: 'http://localhost:2024' }) to the providers array. Import it from 'angular'. -2. Create a ChatComponent that calls streamResource<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }) in the constructor or as a field initializer. streamResource() MUST be called inside an Angular injection context — constructor or field initializer is correct; ngOnInit is not. +2. Create a ChatComponent that calls agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }) in the constructor or as a field initializer. agent() MUST be called inside an Angular injection context — constructor or field initializer is correct; ngOnInit is not. 3. The component template should loop over chat.messages() using @for and render each message's content. Add an input field and a button that calls chat.submit({ messages: [{ role: 'human', content: inputValue }] }). -4. In app.config.ts provideStreamResource call, the apiUrl should point to the LangGraph server. For local dev this is http://localhost:2024. For production use the LangGraph Platform URL from environment.ts. +4. In app.config.ts provideAgent call, the apiUrl should point to the LangGraph server. For local dev this is http://localhost:2024. For production use the LangGraph Platform URL from environment.ts. The library is framework-integrated: no subscriptions, no async pipe needed — chat.messages() is an Angular Signal that updates token by token as the LLM responds. ``` @@ -553,15 +553,15 @@ The library is framework-integrated: no subscriptions, no async pipe needed — Create `apps/website/content/prompts/streaming.md`: ``` -Configure token-by-token streaming in my Angular component that uses stream-resource. +Configure token-by-token streaming in my Angular component that uses angular. -The component already has streamResource() set up. Now: +The component already has agent() set up. Now: 1. In the template, bind to chat.messages() with @for — each BaseMessage has a .content property. The template re-renders automatically as tokens arrive because messages() is a Signal. 2. Show a loading indicator while streaming: use chat.isLoading() in an @if block. -3. To throttle rapid re-renders (if performance is a concern), pass throttle: 50 to streamResource() options — this throttles Signal updates to at most one per 50ms while preserving the final value. +3. To throttle rapid re-renders (if performance is a concern), pass throttle: 50 to agent() options — this throttles Signal updates to at most one per 50ms while preserving the final value. 4. To show the stream status more precisely, bind to chat.status() which returns 'idle' | 'loading' | 'resolved' | 'error'. @@ -571,17 +571,17 @@ Do not use async pipe or subscribe() — the signals update automatically. Create `apps/website/content/prompts/thread-persistence.md`: ``` -Add thread persistence to my Angular component that uses stream-resource, so conversations survive page refresh. +Add thread persistence to my Angular component that uses angular, so conversations survive page refresh. 1. On component init, read the stored thread ID: const storedId = localStorage.getItem('chat-thread-id'). 2. Create a signal: threadId = signal(storedId). -3. Pass it to streamResource: streamResource({ ..., threadId: this.threadId, onThreadId: (id) => { this.threadId.set(id); localStorage.setItem('chat-thread-id', id); } }). +3. Pass it to agent: agent({ ..., threadId: this.threadId, onThreadId: (id) => { this.threadId.set(id); localStorage.setItem('chat-thread-id', id); } }). 4. The onThreadId callback fires once when the server creates a new thread. After that, the same thread ID is reused and the full conversation history is restored from the LangGraph server. -5. To start a new conversation, call this.threadId.set(null) — this causes streamResource to create a fresh thread on the next submit. +5. To start a new conversation, call this.threadId.set(null) — this causes agent to create a fresh thread on the next submit. No changes to the template are needed. ``` @@ -589,31 +589,31 @@ No changes to the template are needed. Create `apps/website/content/prompts/configuration.md`: ``` -Configure stream-resource globally and per-component in my Angular application. +Configure angular globally and per-component in my Angular application. -Global config (applies to all streamResource() calls in the app): -In app.config.ts, provideStreamResource({ apiUrl: 'https://my-langgraph-server.com', }) — import provideStreamResource from 'stream-resource'. +Global config (applies to all agent() calls in the app): +In app.config.ts, provideAgent({ apiUrl: 'https://my-langgraph-server.com', }) — import provideAgent from 'angular'. Per-call override (overrides global config for one component): -Pass apiUrl directly to streamResource({ apiUrl: 'https://other-server.com', assistantId: 'my-agent' }) — per-call options take precedence over global config. +Pass apiUrl directly to agent({ apiUrl: 'https://other-server.com', assistantId: 'my-agent' }) — per-call options take precedence over global config. Custom transport (for auth headers, logging, or testing): -Implement StreamResourceTransport interface — it has one method: stream(input, options). Pass it as transport: myTransport to either provideStreamResource or streamResource(). FetchStreamTransport is the default. +Implement AgentTransport interface — it has one method: stream(input, options). Pass it as transport: myTransport to either provideAgent or agent(). FetchStreamTransport is the default. To pass a system prompt to the LangGraph agent per-thread, use the config option: -streamResource({ config: { configurable: { system_prompt: 'You are a helpful assistant.' } } }) +agent({ config: { configurable: { system_prompt: 'You are a helpful assistant.' } } }) ``` Create `apps/website/content/prompts/testing.md`: ``` -Write unit tests for my Angular component that uses stream-resource, without hitting a real LangGraph server. +Write unit tests for my Angular component that uses angular, without hitting a real LangGraph server. -Use MockStreamTransport from 'stream-resource'. It implements StreamResourceTransport and lets you script exactly what events the stream emits. +Use MockAgentTransport from 'angular'. It implements AgentTransport and lets you script exactly what events the stream emits. Test setup: -const transport = new MockStreamTransport(); -const chat = streamResource({ transport, assistantId: 'test', apiUrl: '' }); +const transport = new MockAgentTransport(); +const chat = agent({ transport, assistantId: 'test', apiUrl: '' }); To emit a streaming response: transport.emit([ @@ -630,7 +630,7 @@ transport.emitError(new Error('Network failure')); expect(chat.status()).toBe('error'); expect(chat.error()).toBeInstanceOf(Error); -Never mock streamResource() itself — always use MockStreamTransport and test through the real function. +Never mock agent() itself — always use MockAgentTransport and test through the real function. ``` - [ ] **Step 4: Update `MdxRenderer.tsx` to accept and render `CopyPromptButton`** @@ -729,30 +729,30 @@ import path from 'path'; import pkg from '../../../package.json'; function buildLlmsTxt(): string { - return `# Angular Stream Resource v${pkg.version} + return `# Angular Agent Framework v${pkg.version} -Angular streaming library for LangChain/LangGraph. Provides streamResource() — full parity with React's useStream() hook, built on Angular Signals. +Angular streaming library for LangChain/LangGraph. Provides agent() — full parity with React's useStream() hook, built on Angular Signals. ## Install -npm install stream-resource +npm install angular ## Key API -- streamResource(options): StreamResourceRef — call in Angular injection context (constructor or field initializer) -- provideStreamResource(config): Provider — register in app.config.ts for global defaults -- StreamResourceRef.messages(): Signal — updates token by token -- StreamResourceRef.submit(values): Promise — send a message / trigger a run -- StreamResourceRef.status(): Signal<'idle'|'loading'|'resolved'|'error'> -- StreamResourceRef.threadId signal + onThreadId callback — thread persistence across refreshes -- MockStreamTransport — deterministic unit testing without a real server +- agent(options): AgentRef — call in Angular injection context (constructor or field initializer) +- provideAgent(config): Provider — register in app.config.ts for global defaults +- AgentRef.messages(): Signal — updates token by token +- AgentRef.submit(values): Promise — send a message / trigger a run +- AgentRef.status(): Signal<'idle'|'loading'|'resolved'|'error'> +- AgentRef.threadId signal + onThreadId callback — thread persistence across refreshes +- MockAgentTransport — deterministic unit testing without a real server ## Minimal example -import { streamResource } from 'stream-resource'; -const chat = streamResource({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024' }); +import { agent } from 'angular'; +const chat = agent({ assistantId: 'chat_agent', apiUrl: 'http://localhost:2024' }); // Template: @for (msg of chat.messages(); track $index) {

    {{ msg.content }}

    } // Submit: chat.submit({ messages: [{ role: 'human', content: input }] }) ## MCP server -npx @stream-resource/mcp +npx @angular/mcp ## Full reference https://stream-resource.dev/llms-full.txt @@ -798,11 +798,11 @@ function loadAllPrompts(): string { export async function GET() { const sections = [ - '# Angular Stream Resource — Full Reference\n\nSee /llms.txt for a compact summary.\n', + '# Angular Agent Framework — Full Reference\n\nSee /llms.txt for a compact summary.\n', '## API Reference (TypeDoc)\n\n' + loadApiDocs(), '## Prompt Recipes\n\n' + loadAllPrompts(), - '## Common Gotchas\n\nstreamResource() MUST be called inside an Angular injection context.\nDo not call it in ngOnInit — use constructor or field initializer.\nDo not mock streamResource() in tests — use MockStreamTransport.\nRxJS is an internal implementation detail — do not import rxjs in consumer code.', - '## MCP server\n\nnpx @stream-resource/mcp\nAdd to Claude Code settings.json, Cursor .cursor/mcp.json, or any MCP-compatible agent.', + '## Common Gotchas\n\nagent() MUST be called inside an Angular injection context.\nDo not call it in ngOnInit — use constructor or field initializer.\nDo not mock agent() in tests — use MockAgentTransport.\nRxJS is an internal implementation detail — do not import rxjs in consumer code.', + '## MCP server\n\nnpx @angular/mcp\nAdd to Claude Code settings.json, Cursor .cursor/mcp.json, or any MCP-compatible agent.', ]; return new NextResponse(sections.join('\n\n---\n\n'), { @@ -844,26 +844,26 @@ These files are generated at build time and served as static downloads from the Create `apps/website/content/CLAUDE.md.template`: ``` -# Angular Stream Resource v@VERSION@ +# Angular Agent Framework v@VERSION@ -Angular streaming library for LangChain/LangGraph. Provides `streamResource()` — full parity with React's `useStream()`. +Angular streaming library for LangChain/LangGraph. Provides `agent()` — full parity with React's `useStream()`. ## Install -npm install stream-resource +npm install angular ## Key requirement -`streamResource()` 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". +`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 { provideStreamResource } from 'stream-resource'; +import { provideAgent } from 'angular'; export const appConfig: ApplicationConfig = { - providers: [provideStreamResource({ apiUrl: 'http://localhost:2024' })] + providers: [provideAgent({ apiUrl: 'http://localhost:2024' })] }; // chat.component.ts -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ template: ` @@ -871,20 +871,20 @@ import type { BaseMessage } from '@langchain/core/messages'; `}) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent' }); send() { this.chat.submit({ messages: [{ role: 'human', content: 'Hello' }] }); } } ``` ## Key patterns - Thread persistence: `threadId: signal(localStorage.getItem('t'))` + `onThreadId: (id) => localStorage.setItem('t', id)` -- Global config: `provideStreamResource({ apiUrl })` in app.config.ts -- Per-call override: pass `apiUrl` directly to `streamResource()` -- Testing: use `MockStreamTransport` — never mock `streamResource()` itself +- Global config: `provideAgent({ apiUrl })` in app.config.ts +- Per-call override: pass `apiUrl` directly to `agent()` +- Testing: use `MockAgentTransport` — never mock `agent()` itself ## MCP server (for tool access) Add to ~/.claude/settings.json: -{"mcpServers":{"stream-resource":{"command":"npx","args":["@stream-resource/mcp"]}}} +{"mcpServers":{"angular":{"command":"npx","args":["@angular/mcp"]}}} ## Version check If this file is stale, fetch the latest: https://stream-resource.dev/llms-full.txt @@ -962,11 +962,11 @@ Create `packages/mcp/package.json`: ```json { - "name": "@stream-resource/mcp", + "name": "@angular/mcp", "version": "0.1.0", - "description": "MCP server for the stream-resource Angular library", + "description": "MCP server for the angular Angular library", "main": "dist/index.js", - "bin": { "@stream-resource/mcp": "dist/index.js" }, + "bin": { "@angular/mcp": "dist/index.js" }, "scripts": { "build": "tsc -p tsconfig.json", "start": "node dist/index.js" @@ -1091,11 +1091,11 @@ import { getApiReferenceTool, handleGetApiReference } from './tools/get-api-refe import { searchDocsTool, handleSearchDocs } from './tools/search-docs.js'; import { getExampleTool, handleGetExample } from './tools/get-example.js'; import { scaffoldChatComponentTool, handleScaffoldChatComponent } from './tools/scaffold-chat-component.js'; -import { addStreamResourceTool, handleAddStreamResource } from './tools/add-stream-resource.js'; +import { addAgentTool, handleAddAgent } from './tools/add-angular.js'; import { getThreadPersistencePatternTool, handleGetThreadPersistencePattern } from './tools/get-thread-persistence-pattern.js'; const server = new Server( - { name: 'stream-resource', version: '0.1.0' }, + { name: 'angular', version: '0.1.0' }, { capabilities: { tools: {} } } ); @@ -1104,7 +1104,7 @@ const TOOLS = [ searchDocsTool, getExampleTool, scaffoldChatComponentTool, - addStreamResourceTool, + addAgentTool, getThreadPersistencePatternTool, ]; @@ -1118,7 +1118,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => { case 'search_docs': return handleSearchDocs(a); case 'get_example': return handleGetExample(a); case 'scaffold_chat_component': return handleScaffoldChatComponent(a); - case 'add_stream_resource': return handleAddStreamResource(a); + case 'add_angular': return handleAddAgent(a); case 'get_thread_persistence_pattern': return handleGetThreadPersistencePattern(a); default: return { content: [{ type: 'text', text: `Unknown tool: ${name}` }] }; } @@ -1140,7 +1140,7 @@ Expected: project details printed. ```bash git add packages/mcp/ -git commit -m "feat(mcp): scaffold @stream-resource/mcp package" +git commit -m "feat(mcp): scaffold @angular/mcp package" ``` --- @@ -1152,7 +1152,7 @@ git commit -m "feat(mcp): scaffold @stream-resource/mcp package" - Create: `packages/mcp/src/tools/search-docs.ts` - Create: `packages/mcp/src/tools/get-example.ts` - Create: `packages/mcp/src/tools/scaffold-chat-component.ts` -- Create: `packages/mcp/src/tools/add-stream-resource.ts` +- Create: `packages/mcp/src/tools/add-angular.ts` - Create: `packages/mcp/src/tools/get-thread-persistence-pattern.ts` - [ ] **Step 1: Create `get-api-reference.ts`** @@ -1164,10 +1164,10 @@ import { findSymbol, getAllSymbolNames } from '../data/loader.js'; export const getApiReferenceTool = { name: 'get_api_reference', - description: 'Get the full API documentation for a stream-resource symbol', + description: 'Get the full API documentation for a angular symbol', inputSchema: { type: 'object', - properties: { symbol: { type: 'string', description: 'Symbol name, e.g. "streamResource"' } }, + properties: { symbol: { type: 'string', description: 'Symbol name, e.g. "agent"' } }, required: ['symbol'], }, }; @@ -1197,7 +1197,7 @@ import { getApiDocs } from '../data/loader.js'; export const searchDocsTool = { name: 'search_docs', - description: 'Search stream-resource documentation by keyword or phrase', + description: 'Search angular documentation by keyword or phrase', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query' } }, @@ -1234,9 +1234,9 @@ Create `packages/mcp/src/tools/get-example.ts`: ```typescript const EXAMPLES: Record = { - 'basic-chat': `// Basic chat component with stream-resource + 'basic-chat': `// Basic chat component with angular import { Component } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -1251,7 +1251,7 @@ import type { BaseMessage } from '@langchain/core/messages'; \`, }) export class ChatComponent { - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', }); send(content: string) { @@ -1262,7 +1262,7 @@ export class ChatComponent { 'thread-persistence': `// Thread persistence with localStorage import { Component, signal } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ selector: 'app-chat', template: \` @@ -1273,7 +1273,7 @@ import type { BaseMessage } from '@langchain/core/messages'; export class ChatComponent { threadId = signal(localStorage.getItem('chat-thread')); - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'chat_agent', threadId: this.threadId, onThreadId: (id) => { @@ -1288,11 +1288,11 @@ export class ChatComponent { 'system-prompt': `// System prompt configuration per session import { Component } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; @Component({ selector: 'app-chat', template: '' }) export class ChatComponent { - chat = streamResource({ + chat = agent({ assistantId: 'chat_agent', config: { configurable: { @@ -1302,16 +1302,16 @@ export class ChatComponent { }); }`, - 'mock-testing': `// Unit testing with MockStreamTransport + 'mock-testing': `// Unit testing with MockAgentTransport import { TestBed } from '@angular/core/testing'; -import { streamResource, MockStreamTransport } from 'stream-resource'; +import { agent, MockAgentTransport } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; describe('ChatComponent', () => { it('updates messages signal when transport emits', () => { TestBed.runInInjectionContext(() => { - const transport = new MockStreamTransport(); - const chat = streamResource<{ messages: BaseMessage[] }>({ + const transport = new MockAgentTransport(); + const chat = agent<{ messages: BaseMessage[] }>({ assistantId: 'test', transport, }); transport.emit([ @@ -1325,7 +1325,7 @@ describe('ChatComponent', () => { 'interrupts': `// Handling interrupts (human-in-the-loop) import { Component } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; @Component({ selector: 'app-chat', @@ -1340,14 +1340,14 @@ import { streamResource } from 'stream-resource'; \`, }) export class ChatComponent { - chat = streamResource({ assistantId: 'agent_with_interrupts' }); + chat = agent({ assistantId: 'agent_with_interrupts' }); approve() { this.chat.submit(null, { command: { resume: true } }); } reject() { this.chat.submit(null, { command: { resume: false } }); } }`, 'subagent-progress': `// Showing subagent tool call progress import { Component } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; @Component({ selector: 'app-chat', @@ -1358,13 +1358,13 @@ import { streamResource } from 'stream-resource'; \`, }) export class ChatComponent { - chat = streamResource({ assistantId: 'research_agent' }); + chat = agent({ assistantId: 'research_agent' }); }`, 'custom-transport': `// Custom transport with auth headers -import { StreamResourceTransport } from 'stream-resource'; +import { AgentTransport } from 'angular'; -export class AuthTransport implements StreamResourceTransport { +export class AuthTransport implements AgentTransport { async *stream(input: unknown, options: unknown): AsyncGenerator { const token = await getAuthToken(); // your auth logic const res = await fetch('/api/stream', { @@ -1394,7 +1394,7 @@ const VALID_PATTERNS = Object.keys(EXAMPLES); export const getExampleTool = { name: 'get_example', - description: 'Get a complete runnable code example for a stream-resource pattern', + description: 'Get a complete runnable code example for a angular pattern', inputSchema: { type: 'object', properties: { @@ -1424,7 +1424,7 @@ Create `packages/mcp/src/tools/scaffold-chat-component.ts`: ```typescript export const scaffoldChatComponentTool = { name: 'scaffold_chat_component', - description: 'Generate a complete Angular chat component using stream-resource', + description: 'Generate a complete Angular chat component using angular', inputSchema: { type: 'object', properties: { @@ -1455,7 +1455,7 @@ export function handleScaffoldChatComponent(args: Record) { },` : ""; const code = `import { Component${persistenceImport} } from '@angular/core'; -import { streamResource } from 'stream-resource'; +import { agent } from 'angular'; import type { BaseMessage } from '@langchain/core/messages'; @Component({ @@ -1479,7 +1479,7 @@ import type { BaseMessage } from '@langchain/core/messages'; }) export class ${componentName} {${persistenceFields} - chat = streamResource<{ messages: BaseMessage[] }>({ + chat = agent<{ messages: BaseMessage[] }>({ apiUrl: '${apiUrl}', assistantId: '${assistantId}',${persistenceOptions} }); @@ -1499,16 +1499,16 @@ export class ${componentName} {${persistenceFields} } ``` -- [ ] **Step 5: Create `add-stream-resource.ts`** +- [ ] **Step 5: Create `add-angular.ts`** -Create `packages/mcp/src/tools/add-stream-resource.ts`: +Create `packages/mcp/src/tools/add-angular.ts`: ```typescript import fs from 'fs'; -export const addStreamResourceTool = { - name: 'add_stream_resource', - description: 'Generate npm install command and app.config.ts diff to add stream-resource to an Angular project', +export const addAgentTool = { + name: 'add_angular', + description: 'Generate npm install command and app.config.ts diff to add angular to an Angular project', inputSchema: { type: 'object', properties: { @@ -1518,7 +1518,7 @@ export const addStreamResourceTool = { }, }; -export function handleAddStreamResource(args: Record) { +export function handleAddAgent(args: Record) { const appConfigPath = args['appConfigPath'] as string; if (!fs.existsSync(appConfigPath)) { @@ -1529,20 +1529,20 @@ export function handleAddStreamResource(args: Record) { return { content: [{ type: 'text', text: `File does not appear to be an Angular app.config.ts (no ApplicationConfig found): ${appConfigPath}` }] }; } - const diff = `Steps to add stream-resource: + const diff = `Steps to add angular: 1. Install the package: \`\`\`bash -npm install stream-resource +npm install angular \`\`\` 2. Apply this change to ${appConfigPath}: \`\`\`diff -+import { provideStreamResource } from 'stream-resource'; ++import { provideAgent } from 'angular'; export const appConfig: ApplicationConfig = { providers: [ -+ provideStreamResource({ apiUrl: 'REPLACE_WITH_YOUR_LANGGRAPH_URL' }), ++ provideAgent({ apiUrl: 'REPLACE_WITH_YOUR_LANGGRAPH_URL' }), // ... existing providers ] }; @@ -1563,7 +1563,7 @@ const PATTERNS = { localStorage: `// Thread persistence with localStorage threadId = signal(localStorage.getItem('chat-thread-id')); -chat = streamResource({ +chat = agent({ assistantId: 'chat_agent', threadId: this.threadId, onThreadId: (id: string) => { @@ -1578,7 +1578,7 @@ chat = streamResource({ sessionStorage: `// Thread persistence with sessionStorage (clears on tab close) threadId = signal(sessionStorage.getItem('chat-thread-id')); -chat = streamResource({ +chat = agent({ assistantId: 'chat_agent', threadId: this.threadId, onThreadId: (id: string) => { @@ -1591,7 +1591,7 @@ chat = streamResource({ // TODO: replace saveThread / loadThread with your store (e.g. NgRx, a service, IndexedDB) threadId = signal(loadThread()); -chat = streamResource({ +chat = agent({ assistantId: 'chat_agent', threadId: this.threadId, onThreadId: (id: string) => { @@ -1647,7 +1647,7 @@ Expected: JSON response listing all 6 tools. ```bash git add packages/mcp/src/tools/ packages/mcp/src/index.ts package-lock.json -git commit -m "feat(mcp): implement all six MCP tools for stream-resource" +git commit -m "feat(mcp): implement all six MCP tools for angular" ``` --- @@ -1657,7 +1657,7 @@ git commit -m "feat(mcp): implement all six MCP tools for stream-resource" - [ ] **Run Angular unit tests (unchanged)** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: all tests pass. diff --git a/docs/superpowers/plans/2026-03-18-chat-agent.md b/docs/superpowers/plans/2026-03-18-chat-agent.md index 2f1a54471..f7a9651be 100644 --- a/docs/superpowers/plans/2026-03-18-chat-agent.md +++ b/docs/superpowers/plans/2026-03-18-chat-agent.md @@ -2,7 +2,7 @@ > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. -**Goal:** Build a Python LangGraph chat agent in `examples/chat-agent/` and TypeScript e2e tests in `e2e/stream-resource-e2e/` that together verify the full `stream-resource` Angular library against a real LangGraph server. +**Goal:** Build a Python LangGraph chat agent in `examples/chat-agent/` and TypeScript e2e tests in `e2e/angular-e2e/` that together verify the full `angular` Angular library against a real LangGraph server. **Architecture:** A single-node `MessagesState` LangGraph graph with `MemorySaver` checkpointer and configurable system prompt, served by `langgraph dev` locally and `langgraph deploy` to LangSmith cloud. TypeScript e2e tests use the `@langchain/langgraph-sdk` `Client` directly to verify the server's streaming, thread persistence, and configuration behaviour. A GitHub Actions workflow spins up `langgraph dev` and runs the e2e suite on every push to `main`. @@ -35,7 +35,7 @@ examples/chat-agent/ ├── config.py # Configuration TypedDict └── agent.py # StateGraph + MemorySaver, exports `graph` -e2e/stream-resource-e2e/ +e2e/angular-e2e/ ├── project.json # Nx project: e2e target via @nx/vite:test ├── vite.config.mts # Vitest, node env, 60s timeout ├── tsconfig.json # extends tsconfig.base.json, node types @@ -118,7 +118,7 @@ OPENAI_API_KEY=your-openai-api-key-here OPENAI_MODEL=gpt-5-mini LANGSMITH_API_KEY=your-langsmith-api-key-here LANGSMITH_TRACING=false -LANGSMITH_PROJECT=stream-resource-example +LANGSMITH_PROJECT=angular-example ``` - [ ] **Step 5: Create `.gitignore`** @@ -404,27 +404,27 @@ git commit -m "test(chat-agent): add thread persistence integration test" ## Task 5: E2E Project Scaffold **Files:** -- Create: `e2e/stream-resource-e2e/project.json` -- Create: `e2e/stream-resource-e2e/vite.config.mts` -- Create: `e2e/stream-resource-e2e/tsconfig.json` +- Create: `e2e/angular-e2e/project.json` +- Create: `e2e/angular-e2e/vite.config.mts` +- Create: `e2e/angular-e2e/tsconfig.json` -The e2e tests use the `@langchain/langgraph-sdk` `Client` (already a dependency of the monorepo via `stream-resource`) to test the HTTP/SSE protocol directly — no browser or Angular DI required. Tests are gated on `LANGGRAPH_URL` being set, so they skip safely in standard unit test runs. +The e2e tests use the `@langchain/langgraph-sdk` `Client` (already a dependency of the monorepo via `angular`) to test the HTTP/SSE protocol directly — no browser or Angular DI required. Tests are gated on `LANGGRAPH_URL` being set, so they skip safely in standard unit test runs. - [ ] **Step 1: Create `project.json`** -Create `e2e/stream-resource-e2e/project.json`: +Create `e2e/angular-e2e/project.json`: ```json { - "name": "stream-resource-e2e", + "name": "angular-e2e", "$schema": "../../node_modules/nx/schemas/project-schema.json", "projectType": "application", - "sourceRoot": "e2e/stream-resource-e2e/src", + "sourceRoot": "e2e/angular-e2e/src", "targets": { "e2e": { "executor": "@nx/vite:test", "options": { - "configFile": "e2e/stream-resource-e2e/vite.config.mts" + "configFile": "e2e/angular-e2e/vite.config.mts" } } } @@ -433,7 +433,7 @@ Create `e2e/stream-resource-e2e/project.json`: - [ ] **Step 2: Create `vite.config.mts`** -Create `e2e/stream-resource-e2e/vite.config.mts`: +Create `e2e/angular-e2e/vite.config.mts`: ```typescript import { defineConfig } from 'vite'; @@ -452,7 +452,7 @@ export default defineConfig({ - [ ] **Step 3: Create `tsconfig.json`** -Create `e2e/stream-resource-e2e/tsconfig.json`: +Create `e2e/angular-e2e/tsconfig.json`: ```json { @@ -467,13 +467,13 @@ Create `e2e/stream-resource-e2e/tsconfig.json`: - [ ] **Step 4: Create `src/` directory with a placeholder** ```bash -mkdir -p e2e/stream-resource-e2e/src +mkdir -p e2e/angular-e2e/src ``` - [ ] **Step 5: Verify Nx recognises the project** ```bash -npx nx show project stream-resource-e2e +npx nx show project angular-e2e ``` Expected: project details printed with the `e2e` target listed. @@ -481,8 +481,8 @@ Expected: project details printed with the `e2e` target listed. - [ ] **Step 6: Commit** ```bash -git add e2e/stream-resource-e2e/ -git commit -m "chore(e2e): scaffold stream-resource-e2e Nx project" +git add e2e/angular-e2e/ +git commit -m "chore(e2e): scaffold angular-e2e Nx project" ``` --- @@ -490,11 +490,11 @@ git commit -m "chore(e2e): scaffold stream-resource-e2e Nx project" ## Task 6: E2E Tests **Files:** -- Create: `e2e/stream-resource-e2e/src/chat-agent.e2e.spec.ts` +- Create: `e2e/angular-e2e/src/chat-agent.e2e.spec.ts` - [ ] **Step 1: Write the test file** -Create `e2e/stream-resource-e2e/src/chat-agent.e2e.spec.ts`: +Create `e2e/angular-e2e/src/chat-agent.e2e.spec.ts`: ```typescript import { beforeAll, describe, expect, it } from 'vitest'; @@ -610,7 +610,7 @@ describe.skipIf(!process.env['LANGGRAPH_URL'])('chat-agent e2e', () => { - [ ] **Step 2: Verify tests skip cleanly without server** ```bash -npx nx e2e stream-resource-e2e +npx nx e2e angular-e2e ``` Expected: `chat-agent e2e` suite is skipped (0 tests run, 0 failures) because `LANGGRAPH_URL` is not set. @@ -625,7 +625,7 @@ langgraph dev --no-browser Then in the main terminal: ```bash -LANGGRAPH_URL=http://localhost:2024 npx nx e2e stream-resource-e2e +LANGGRAPH_URL=http://localhost:2024 npx nx e2e angular-e2e ``` Expected: 3 tests PASS (requires `OPENAI_API_KEY` in the server's `.env`). @@ -633,7 +633,7 @@ Expected: 3 tests PASS (requires `OPENAI_API_KEY` in the server's `.env`). - [ ] **Step 4: Commit** ```bash -git add e2e/stream-resource-e2e/src/chat-agent.e2e.spec.ts +git add e2e/angular-e2e/src/chat-agent.e2e.spec.ts git commit -m "test(e2e): add chat-agent end-to-end tests" ``` @@ -685,7 +685,7 @@ jobs: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }} LANGSMITH_TRACING: "true" - LANGSMITH_PROJECT: stream-resource-e2e-ci + LANGSMITH_PROJECT: angular-e2e-ci - name: Wait for server to be ready run: | @@ -698,7 +698,7 @@ jobs: curl -sf http://localhost:2024/ok || (echo "Server failed to start after 60s" && exit 1) - name: Run e2e tests - run: npx nx e2e stream-resource-e2e + run: npx nx e2e angular-e2e env: LANGGRAPH_URL: http://localhost:2024 ``` @@ -714,7 +714,7 @@ Expected: `YAML valid` (no output means no error). - [ ] **Step 3: Run the full angular unit test suite one last time to confirm nothing is broken** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: 24 tests PASS. @@ -723,7 +723,7 @@ Expected: 24 tests PASS. ```bash git add .github/workflows/e2e.yml -git commit -m "ci: add E2E workflow — langgraph dev + stream-resource-e2e" +git commit -m "ci: add E2E workflow — langgraph dev + angular-e2e" ``` --- @@ -733,7 +733,7 @@ git commit -m "ci: add E2E workflow — langgraph dev + stream-resource-e2e" - [ ] **Run unit tests** ```bash -npx nx test stream-resource +npx nx test angular ``` Expected: 24 tests PASS. @@ -745,7 +745,7 @@ Expected: 24 tests PASS. cd examples/chat-agent && langgraph dev --no-browser # Terminal 2 -LANGGRAPH_URL=http://localhost:2024 npx nx e2e stream-resource-e2e +LANGGRAPH_URL=http://localhost:2024 npx nx e2e angular-e2e ``` Expected: 3 e2e tests PASS. diff --git a/docs/superpowers/plans/2026-03-18-website.md b/docs/superpowers/plans/2026-03-18-website.md index 29bf6b711..60679da7f 100644 --- a/docs/superpowers/plans/2026-03-18-website.md +++ b/docs/superpowers/plans/2026-03-18-website.md @@ -1,8 +1,8 @@ -# Angular Stream Resource Website Implementation Plan +# Angular Agent Framework Website Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. Set up an isolated workspace first using superpowers:using-git-worktrees. -**Goal:** Build the Angular Stream Resource Next.js marketing and documentation website — landing page, pricing, docs, live Angular Elements demo — using the indigo-blue neon brand from `docs/superpowers/specs/2026-03-18-website-branding-design.md`. +**Goal:** Build the Angular Agent Framework Next.js marketing and documentation website — landing page, pricing, docs, live Angular Elements demo — using the indigo-blue neon brand from `docs/superpowers/specs/2026-03-18-website-branding-design.md`. **Architecture:** Next.js 15 App Router inside the existing Nx monorepo at `apps/website/`. Design tokens defined once in `globals.css` (CSS custom properties) and `lib/design-tokens.ts` (typed TS constants), consumed by all components via Tailwind CSS utility classes and inline styles. Angular Elements demo app lives at `apps/demo/`, built separately, bundle copied to `public/demo/`. Docs generated by a two-stage script pipeline (TypeDoc → Claude API → MDX). @@ -11,7 +11,7 @@ **Supersedes:** `docs/superpowers/plans/2026-03-17-website.md` **Brand spec:** `docs/superpowers/specs/2026-03-18-website-branding-design.md` -**Structure spec:** `docs/superpowers/specs/2026-03-17-stream-resource-design.md` (Section 3) +**Structure spec:** `docs/superpowers/specs/2026-03-17-angular-design.md` (Section 3) --- @@ -329,7 +329,7 @@ export function Nav() {