diff --git a/apps/website/content/docs/ag-ui/api/api-docs.json b/apps/website/content/docs/ag-ui/api/api-docs.json index 7be9fe93b..8350f3a58 100644 --- a/apps/website/content/docs/ag-ui/api/api-docs.json +++ b/apps/website/content/docs/ag-ui/api/api-docs.json @@ -550,11 +550,11 @@ { "name": "injectAgent", "kind": "function", - "description": "Injects the Agent from Angular's dependency injection container.\nUse this in components or services that have been provided via provideAgent().", - "signature": "injectAgent(): Agent", + "description": "Injects the AG-UI agent from Angular's dependency injection container.\nUse this in components or services provided via `provideAgent()` (or\n`provideFakeAgent()`).\n\nReturns an `AgUiAgent` — the runtime-neutral `Agent` contract plus the\nAG-UI-specific `customEvents` signal — so `customEvents` is reachable\ndirectly, without casting.", + "signature": "injectAgent(): AgUiAgent", "params": [], "returns": { - "type": "Agent", + "type": "AgUiAgent", "description": "" }, "examples": [] diff --git a/apps/website/content/docs/ag-ui/api/inject-agent.mdx b/apps/website/content/docs/ag-ui/api/inject-agent.mdx index 3413686bf..eec6113f4 100644 --- a/apps/website/content/docs/ag-ui/api/inject-agent.mdx +++ b/apps/website/content/docs/ag-ui/api/inject-agent.mdx @@ -71,12 +71,12 @@ The AG-UI adapter extends the neutral `Agent` contract with one additional signa |-------|------|-------------| | `customEvents()` | `CustomStreamEvent[]` | Custom events emitted by the backend during a run. Accumulates per run; resets on each new `submit()`. | -`injectAgent()` is typed as the neutral `Agent` interface; to access `customEvents` you must cast to `AgUiAgent`: +`injectAgent()` returns the `AgUiAgent` type — the neutral `Agent` contract plus `customEvents` — so the signal is reachable directly, no cast required: ```ts -import { injectAgent, type AgUiAgent } from '@threadplane/ag-ui'; +import { injectAgent } from '@threadplane/ag-ui'; -const chat = injectAgent() as AgUiAgent; +const chat = injectAgent(); chat.customEvents(); // Signal ``` diff --git a/apps/website/content/docs/ag-ui/guides/custom-events.mdx b/apps/website/content/docs/ag-ui/guides/custom-events.mdx index 4a1a8a214..062ae00b4 100644 --- a/apps/website/content/docs/ag-ui/guides/custom-events.mdx +++ b/apps/website/content/docs/ag-ui/guides/custom-events.mdx @@ -1,6 +1,6 @@ # Custom Events -AG-UI `CUSTOM` events let a backend node push arbitrary data to the Angular client while a run is in progress. The adapter accumulates these events into a `customEvents` signal. That signal lives on the widened `AgUiAgent` type — `injectAgent()` returns the neutral `Agent`, so you cast its result to `AgUiAgent` to reach `customEvents` (shown in [Reading Custom Events](#reading-custom-events-in-angular) below). +AG-UI `CUSTOM` events let a backend node push arbitrary data to the Angular client while a run is in progress. The adapter accumulates these events into a `customEvents` signal on the `AgUiAgent` returned by `injectAgent()` — reachable directly, no cast required (shown in [Reading Custom Events](#reading-custom-events-in-angular) below). ```ts interface CustomStreamEvent { @@ -49,7 +49,7 @@ The adapter JSON-parses `value` when it arrives as a string, so consumers always ## Reading Custom Events in Angular -`injectAgent()` returns the neutral `Agent` type; cast it to `AgUiAgent` (exported from `@threadplane/ag-ui`) to reach the `customEvents` signal. +`injectAgent()` returns an `AgUiAgent`, so the `customEvents` signal is available directly on the injected agent — no cast needed. ### Reactive effect @@ -58,7 +58,7 @@ Use an `effect` to react every time new events arrive: ```typescript import { Component, ChangeDetectionStrategy, effect, signal } from '@angular/core'; import { ChatComponent } from '@threadplane/chat'; -import { injectAgent, type AgUiAgent } from '@threadplane/ag-ui'; +import { injectAgent } from '@threadplane/ag-ui'; @Component({ standalone: true, @@ -72,7 +72,7 @@ import { injectAgent, type AgUiAgent } from '@threadplane/ag-ui'; `, }) export class AnalysisComponent { - protected readonly agent = injectAgent() as AgUiAgent; + protected readonly agent = injectAgent(); protected readonly progress = signal(null); constructor() { @@ -96,7 +96,7 @@ When you only need to derive a value, `computed` is more concise: ```typescript import { Component, ChangeDetectionStrategy, computed } from '@angular/core'; import { ChatComponent } from '@threadplane/chat'; -import { injectAgent, type AgUiAgent } from '@threadplane/ag-ui'; +import { injectAgent } from '@threadplane/ag-ui'; import type { CustomStreamEvent } from '@threadplane/ag-ui'; @Component({ @@ -109,7 +109,7 @@ import type { CustomStreamEvent } from '@threadplane/ag-ui'; `, }) export class AnalysisComponent { - protected readonly agent = injectAgent() as AgUiAgent; + protected readonly agent = injectAgent(); protected readonly progressEvents = computed(() => this.agent.customEvents().filter( diff --git a/libs/ag-ui/src/lib/provide-agent.ts b/libs/ag-ui/src/lib/provide-agent.ts index 57af24598..c55da9008 100644 --- a/libs/ag-ui/src/lib/provide-agent.ts +++ b/libs/ag-ui/src/lib/provide-agent.ts @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT import { InjectionToken, inject, type Provider } from '@angular/core'; import { HttpAgent } from '@ag-ui/client'; -import type { Agent, AgentRuntimeTelemetrySink } from '@threadplane/chat'; -import { toAgent } from './to-agent'; +import type { AgentRuntimeTelemetrySink } from '@threadplane/chat'; +import { toAgent, type AgUiAgent } from './to-agent'; /** * Configuration for the AG-UI agent provider. @@ -21,8 +21,12 @@ export interface AgentConfig { telemetry?: AgentRuntimeTelemetrySink | false; } -/** @internal — exported for spec access only. Consumers must use injectAgent(). */ -export const AGENT = new InjectionToken('AGENT'); +/** + * @internal — exported for spec access only. Consumers must use injectAgent(). + * Both `provideAgent` and `provideFakeAgent` register the result of `toAgent()`, + * which is always an `AgUiAgent`, so the token is typed accordingly. + */ +export const AGENT = new InjectionToken('AGENT'); /** * Provides an Agent instance wired through HttpAgent and toAgent. @@ -59,9 +63,14 @@ export function provideAgent( } /** - * Injects the Agent from Angular's dependency injection container. - * Use this in components or services that have been provided via provideAgent(). + * Injects the AG-UI agent from Angular's dependency injection container. + * Use this in components or services provided via `provideAgent()` (or + * `provideFakeAgent()`). + * + * Returns an `AgUiAgent` — the runtime-neutral `Agent` contract plus the + * AG-UI-specific `customEvents` signal — so `customEvents` is reachable + * directly, without casting. */ -export function injectAgent(): Agent { +export function injectAgent(): AgUiAgent { return inject(AGENT); }