Skip to content

Commit 0d3bfd1

Browse files
bloveclaude
andauthored
refactor(langgraph): unify agent() return type as LangGraphAgent (#152)
* docs: LangGraph agent() unification design Eliminate two-step agent()+toAgent() pattern. agent() returns unified LangGraphAgent (extends AgentWithHistory) preserving all AgentRef public surface. Type-level tension resolved via langGraph*-prefixed raw signals (langGraphMessages, langGraphHistory, etc.) alongside runtime-neutral fields. Breaking change; no compat aliases. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: LangGraph agent() unification implementation plan 4 tasks: lib refactor (define LangGraphAgent, fold to-agent translation into agent.fn, delete to-agent.ts, refactor mocks, conformance test), cockpit migration (~23 demos), website docs migration (~20 files), final verify + PR. Three commits sequenced to keep each step build-clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(langgraph): unify agent() return type as LangGraphAgent Eliminate two-step agent()+toAgent() pattern. agent() now returns LangGraphAgent extending AgentWithHistory with the full LangGraph- specific surface preserved (langGraph*-prefixed raw signals where type collisions exist with the runtime-neutral chat contract). - Define LangGraphAgent in agent.types.ts - Fold to-agent translation logic into agent.fn.ts - Delete to-agent.ts and its specs - Add agent.conformance.spec.ts (runAgentConformance suite) - Rename mockAgentRef → mockLangGraphAgent (mock-langgraph-agent.ts) - public-api.ts: drop toAgent, AgentRef, createMockAgentRef; add LangGraphAgent, mockLangGraphAgent BREAKING: AgentRef is no longer exported. agent() return type changed from AgentRef to LangGraphAgent. toAgent() removed entirely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(cockpit): migrate from agent()+toAgent() to unified LangGraphAgent 25 cockpit angular demos updated. The two field initializers (stream = agent({...}); chatAgent = toAgent(this.stream)) collapse to a single field 'agent'. Code reading raw BaseMessage[] switches to .langGraphMessages(); chat-template bindings now reference the unified agent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): align with unified LangGraphAgent API Update MDX prose, code samples in chat/agent/render docs to reference LangGraphAgent + the single agent({...}) flow. Regenerate api-docs.json. Rename createMockAgentRef doc page to mockLangGraphAgent. Update llms.txt example to single-step. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(cockpit): update ag-ui streaming prompt to reference Agent contract * fix(demo): align chat-demo with unified Message type and AgentSubmitInput - msg.getType() === 'ai' → msg.role === 'assistant' (Message has 'role', not BaseMessage's getType()). - chat.submit({ messages: [{ role: 'human', content }] } as any) → chat.submit({ message: content }) (the runtime-neutral AgentSubmitInput shape). - Drop unused BaseMessage import + generic. This resolves the TS2339 error that blocked website lint/build CI. The demo's old code path predates the unification refactor and was reading raw LangChain types directly off the agent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent ca02bc9 commit 0d3bfd1

58 files changed

Lines changed: 1463 additions & 1567 deletions

File tree

Some content is hidden

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

apps/demo/src/app/chat-demo/chat-demo.component.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { Component, Input, OnInit, Injector, runInInjectionContext } from '@angular/core';
22
import { agent } from '@ngaf/langgraph';
3-
import type { BaseMessage } from '@langchain/core/messages';
43

54
@Component({
65
selector: 'stream-chat-demo',
76
standalone: false,
87
template: `
98
<div class="chat-demo">
109
<div class="messages" *ngIf="chat">
11-
<div *ngFor="let msg of chat.messages()" class="message" [class.ai]="msg.getType() === 'ai'">
10+
<div *ngFor="let msg of chat.messages()" class="message" [class.ai]="msg.role === 'assistant'">
1211
{{ msg.content }}
1312
</div>
1413
<div *ngIf="chat.isLoading()" class="loading">Thinking…</div>
@@ -34,14 +33,14 @@ export class ChatDemoComponent implements OnInit {
3433
@Input() apiUrl = 'http://localhost:2024';
3534
@Input() assistantId = 'chat_agent';
3635

37-
chat: ReturnType<typeof agent<{ messages: BaseMessage[] }>> | null = null;
36+
chat: ReturnType<typeof agent> | null = null;
3837

3938
constructor(private injector: Injector) {}
4039

4140
ngOnInit() {
4241
// @Input() values are available in ngOnInit, so use runInInjectionContext
4342
runInInjectionContext(this.injector, () => {
44-
this.chat = agent<{ messages: BaseMessage[] }>({
43+
this.chat = agent({
4544
apiUrl: this.apiUrl,
4645
assistantId: this.assistantId,
4746
});
@@ -55,7 +54,6 @@ export class ChatDemoComponent implements OnInit {
5554
const content = input.value.trim();
5655
if (!content || !this.chat) return;
5756
input.value = '';
58-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59-
this.chat.submit({ messages: [{ role: 'human', content }] } as any);
57+
this.chat.submit({ message: content });
6058
}
6159
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ AG-UI is the open agent-to-UI protocol from the CopilotKit ecosystem. It standar
1818
┌───────────┴───────────┐
1919
▼ ▼
2020
@ngaf/langgraph @ngaf/ag-ui
21-
(toAgent: AgentRef→Agent) (toAgent: AbstractAgent→Agent)
21+
(LangGraphAgent) (toAgent: AbstractAgent→Agent)
2222
│ │
2323
▼ ▼
2424
LangGraph Platform Any AG-UI backend
@@ -28,7 +28,7 @@ AG-UI is the open agent-to-UI protocol from the CopilotKit ecosystem. It standar
2828

2929
## What you get
3030

31-
- **`toAgent(source: AbstractAgent): Agent`** — wraps any `AbstractAgent` subclass (custom transports, mocks).
31+
- **`toAgent(source: AbstractAgent): Agent`** — wraps any `AbstractAgent` subclass (custom transports, mocks) into the runtime-neutral `Agent` contract.
3232
- **`provideAgUiAgent({ url })`** — DI convenience that instantiates `HttpAgent` under the hood for the common SSE/HTTP case.
3333
- **`FakeAgent`** — in-process `AbstractAgent` subclass that emits canned streaming events for offline demos and tests.
3434

0 commit comments

Comments
 (0)