Skip to content

Commit 90eed9f

Browse files
authored
Merge pull request #210 from cacheplane/codex/docs-context-sweep
[codex] align docs context and remove stale MCP package
2 parents 218dcbc + 3d8080c commit 90eed9f

67 files changed

Lines changed: 360 additions & 1363 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.

AGENTS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ This file is for agents working in this repository. It is contributor-facing, no
3838

3939
- `libs/langgraph`: main Angular library (`@ngaf/langgraph`).
4040
- `apps/website`: docs and marketing site.
41-
- `packages/mcp`: MCP server package (`@ngaf/langgraph-mcp`).
4241
- `e2e/agent-e2e`: end-to-end coverage for the workspace.
4342

4443
## Working in This Repo

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ That's it. `chat.messages()` and `chat.status()` are Angular Signals. Bind them
8787
| Error state | `error()` ||
8888
| Runtime-neutral status | `status()``'idle' \| 'running' \| 'error'` | partial |
8989
| Interrupt / human-in-the-loop | `interrupt()` / `interrupts()` | `interrupt` / `interrupts` |
90-
| Tool call progress | `toolProgress()` | `toolProgress` |
90+
| Tool call progress | `toolCalls()` | `toolCalls` |
9191
| Tool calls with results | `toolCalls()` | `toolCalls` |
9292
| Branch / history | `branch()` / `history()` / `experimentalBranchTree()` | `branch` / `history` / `experimental_branchTree` |
9393
| Pending run queue | `queue()` | `queue` |
94-
| Subagent streaming and lookup helpers | `subagents()` / `activeSubagents()` / `getSubagent()` | `subagents` / `activeSubagents` / helper methods |
94+
| Subagent streaming and lookup helpers | `subagents()` / `getSubagent()` | `subagents` / helper methods |
9595
| Reactive thread switching | `Signal<string \| null>` input | prop |
9696
| Submit | `submit(values, opts?)` | `submit(values, opts?)` |
9797
| Stop | `stop()` | `stop()` |

apps/website/content/docs/agent/api/api-docs.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@
211211
}
212212
],
213213
"examples": [
214-
"```typescript\nconst transport = new MockAgentTransport([\n [{ type: 'values', data: { messages: [aiMsg('Hello')] } }],\n [{ type: 'values', data: { status: 'done' } }],\n]);\n```"
214+
"```typescript\nconst transport = new MockAgentTransport([\n [{ type: 'values', messages: [aiMsg('Hello')] }],\n [{ type: 'values', messages: [aiMsg('Done')] }],\n]);\n```"
215215
],
216216
"properties": [
217217
{
@@ -405,7 +405,7 @@
405405
{
406406
"name": "nextBatch",
407407
"signature": "nextBatch()",
408-
"description": "Advance to the next scripted batch and return its events.",
408+
"description": "Advance to the next scripted batch. Pass the returned events to `emit()`.",
409409
"params": []
410410
},
411411
{
@@ -1661,7 +1661,7 @@
16611661
"description": ""
16621662
},
16631663
"examples": [
1664-
"```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```"
1664+
"```typescript\n// In a component field initializer\nconst chat = agent({\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```"
16651665
]
16661666
},
16671667
{

apps/website/content/docs/agent/concepts/agent-architecture.mdx

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,13 @@ export class ReactAgentComponent {
179179

180180
messages = this.agent.messages;
181181

182-
// Tools currently executing (spinner, progress bar)
183-
activeTools = computed(() => this.agent.toolProgress());
184-
185-
// Tools that finished with results (expandable cards)
186-
completedTools = computed(() => this.agent.toolCalls());
182+
// Tool calls with status, args, and result data
183+
activeTools = computed(() =>
184+
this.agent.toolCalls().filter((tool) => tool.status === 'running')
185+
);
186+
completedTools = computed(() =>
187+
this.agent.toolCalls().filter((tool) => tool.status === 'complete')
188+
);
187189

188190
send(text: string) {
189191
this.agent.submit({ message: text });
@@ -233,21 +235,23 @@ The LLM reads the docstring to decide when to call a tool. A vague docstring lik
233235

234236
### How Tools Surface in Angular
235237

236-
When the agent calls a tool, agent() exposes the execution lifecycle through two signals:
238+
When the agent calls a tool, agent() exposes the execution lifecycle through `toolCalls()`:
237239

238240
<Tabs>
239-
<Tab label="toolProgress()">
241+
<Tab label="toolCalls()">
240242

241243
```typescript
242-
// toolProgress() — tools currently executing
244+
// toolCalls() — tool calls with status, args, and results
243245
// Updates in real time as tools start and complete
244246

245247
const agent = agent<AgentState>({
246248
assistantId: 'react_agent',
247249
});
248250

249-
// Each entry has: name, args, status
250-
const activeTools = computed(() => agent.toolProgress());
251+
// Each entry has: id, name, args, status, and optional result
252+
const activeTools = computed(() =>
253+
agent.toolCalls().filter((tool) => tool.status === 'running')
254+
);
251255

252256
// Template usage
253257
@Component({
@@ -263,18 +267,19 @@ const activeTools = computed(() => agent.toolProgress());
263267
`,
264268
})
265269
export class ToolProgressComponent {
266-
activeTools = computed(() => this.agent.toolProgress());
270+
activeTools = computed(() =>
271+
this.agent.toolCalls().filter((tool) => tool.status === 'running')
272+
);
267273
}
268274
```
269275

270276
</Tab>
271-
<Tab label="toolCalls()">
277+
<Tab label="completed calls">
272278

273279
```typescript
274-
// toolCalls() — completed tool calls with results
275-
// Available after each tool finishes
276-
277-
const completedTools = computed(() => agent.toolCalls());
280+
const completedTools = computed(() =>
281+
agent.toolCalls().filter((tool) => tool.status === 'complete')
282+
);
278283

279284
// Each entry has: name, args, result, duration
280285
@Component({
@@ -324,7 +329,7 @@ The `should_continue` conditional edge detects `tool_calls` and routes to the `t
324329
LangGraph Platform streams the tool call and result as SSE events to the Angular client.
325330
</Step>
326331
<Step title="agent() updates signals">
327-
`toolProgress()` updates during execution. `toolCalls()` updates when the tool completes. Both trigger OnPush change detection.
332+
`toolCalls()` updates as the tool moves through pending, running, complete, and error states. Each update triggers OnPush change detection.
328333
</Step>
329334
</Steps>
330335

@@ -442,10 +447,14 @@ export class MultiAgentComponent {
442447
messages = this.orchestrator.messages;
443448

444449
// Currently running delegated work with live status
445-
activeTools = computed(() => this.orchestrator.toolProgress());
450+
activeTools = computed(() =>
451+
this.orchestrator.toolCalls().filter((tool) => tool.status === 'running')
452+
);
446453

447454
// Completed tool calls with results
448-
completedTools = computed(() => this.orchestrator.toolCalls());
455+
completedTools = computed(() =>
456+
this.orchestrator.toolCalls().filter((tool) => tool.status === 'complete')
457+
);
449458

450459
send(text: string) {
451460
this.orchestrator.submit({ message: text });
@@ -518,7 +527,7 @@ export class AgentComponent {
518527
|---|---|---|
519528
| Tool throws `ToolException` | Error fed back to LLM, agent retries | `toolCalls()` shows error in result |
520529
| Tool throws unexpected error | LangGraph catches it, marks tool as failed | `error()` fires with details |
521-
| LLM returns invalid tool args | ToolNode validation fails, error fed to LLM | `toolProgress()` shows failed status |
530+
| LLM returns invalid tool args | ToolNode validation fails, error fed to LLM | `toolCalls()` shows failed status |
522531
| Transport error (network) | N/A | `error()` fires, `status()` becomes `'error'` |
523532
| Agent exceeds recursion limit | Graph raises `GraphRecursionError` | `error()` fires with recursion message |
524533

@@ -594,7 +603,7 @@ export class DebugTimelineComponent {
594603

595604
timeTravel(checkpointId: string) {
596605
this.currentCheckpoint.set(checkpointId);
597-
this.agent.submit(null, { checkpointId });
606+
this.agent.submit({}, { checkpointId });
598607
}
599608
}
600609
```
@@ -622,7 +631,7 @@ builder.add_edge("tools", "model")
622631
graph = builder.compile()
623632
```
624633

625-
**Angular signals used:** `messages()`, `toolCalls()`, `toolProgress()`, `status()`
634+
**Angular signals used:** `messages()`, `toolCalls()`, `status()`
626635

627636
### Single Agent with Human-in-the-Loop
628637

@@ -640,7 +649,7 @@ def execute_action(state: AgentState) -> dict:
640649
return perform_action(state["pending_action"])
641650
```
642651

643-
**Angular signals used:** `messages()`, `interrupt()`, `status()` plus `submit(null, { resume })` to approve
652+
**Angular signals used:** `messages()`, `interrupt()`, `status()` plus `submit({ resume })` to approve
644653

645654
### Multi-Agent Supervisor
646655

@@ -654,7 +663,7 @@ builder.add_node("analyst", analyst_subgraph)
654663
builder.add_conditional_edges("supervisor", route_to_agent)
655664
```
656665

657-
**Angular signals used:** `messages()`, `subagents()`, `activeSubagents()`, `toolCalls()`, `toolProgress()`, `status()`
666+
**Angular signals used:** `messages()`, `subagents()`, `toolCalls()`, `status()`
658667

659668
### Decision Matrix
660669

apps/website/content/docs/agent/concepts/angular-signals.mdx

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Under the hood, agent() receives Server-Sent Events (SSE) over HTTP and feeds th
4141
// Simplified view of what agent does internally:
4242

4343
// 1. SSE events arrive as an observable stream
44-
const messages$ = new BehaviorSubject<BaseMessage[]>([]);
44+
const messages$ = new BehaviorSubject<Message[]>([]);
4545
const status$ = new BehaviorSubject<ResourceStatus>('idle');
4646

4747
// 2. Each SSE chunk updates the BehaviorSubject
@@ -68,8 +68,8 @@ const chat = agent<ChatState>({
6868
assistantId: 'chat_agent',
6969
});
7070

71-
chat.messages(); // Signal<BaseMessage[]>
72-
chat.status(); // Signal<ResourceStatus>
71+
chat.messages(); // Signal<Message[]>
72+
chat.status(); // Signal<'idle' | 'running' | 'error'>
7373
chat.error(); // Signal<unknown>
7474
chat.isLoading(); // Signal<boolean>
7575
chat.value(); // Signal<ChatState>
@@ -84,7 +84,7 @@ The BehaviorSubject-to-Signal conversion means you get the best of both worlds:
8484

8585
## The Streaming Lifecycle as Signals
8686

87-
Every agent() instance moves through a lifecycle: **idle**, **loading**, tokens arriving, then **resolved** (or **error**). The `status()` Signal reflects each transition in real time.
87+
Every agent() instance moves through a lifecycle: **idle**, **running** while work is in flight, then back to **idle** when the stream completes (or **error** when it fails). The `status()` Signal reflects each transition in real time, while `isLoading()` is the convenience signal for loading UI.
8888

8989
<Steps>
9090
<Step title="idle — Waiting for input">
@@ -101,39 +101,39 @@ console.log(chat.isLoading()); // false
101101
```
102102
</Step>
103103

104-
<Step title="loading — Request in flight">
105-
After calling `submit()`, the status transitions to `'loading'`. The SSE connection is open and the agent is processing.
104+
<Step title="running — Request in flight">
105+
After calling `submit()`, the status transitions to `'running'`. The SSE connection is open and the agent is processing.
106106

107107
```typescript
108108
chat.submit({ message: 'Explain quantum computing' });
109109

110-
console.log(chat.status()); // 'loading'
110+
console.log(chat.status()); // 'running'
111111
console.log(chat.isLoading()); // true
112112
console.log(chat.messages()); // [] (no tokens yet)
113113
```
114114
</Step>
115115

116-
<Step title="loading — Tokens streaming">
117-
As the agent generates tokens, the `messages()` Signal updates with each chunk. The status remains `'loading'` throughout.
116+
<Step title="running — Tokens streaming">
117+
As the agent generates tokens, the `messages()` Signal updates with each chunk. The status remains `'running'` throughout.
118118

119119
```typescript
120120
// After first few tokens arrive:
121-
console.log(chat.status()); // 'loading' (still streaming)
122-
console.log(chat.messages()); // [AIMessageChunk("Quantum computing uses...")]
121+
console.log(chat.status()); // 'running' (still streaming)
122+
console.log(chat.messages()); // [{ role: 'assistant', content: 'Quantum computing uses...' }]
123123

124124
// After more tokens:
125-
console.log(chat.messages()); // [AIMessageChunk("Quantum computing uses qubits...")]
125+
console.log(chat.messages()); // [{ role: 'assistant', content: 'Quantum computing uses qubits...' }]
126126
// The message content grows as tokens stream in
127127
```
128128
</Step>
129129

130-
<Step title="resolved — Stream complete">
131-
The agent has finished. All tokens have arrived. The status transitions to `'resolved'`.
130+
<Step title="idle — Stream complete">
131+
The agent has finished. All tokens have arrived. The status transitions back to `'idle'`.
132132

133133
```typescript
134-
console.log(chat.status()); // 'resolved'
134+
console.log(chat.status()); // 'idle'
135135
console.log(chat.isLoading()); // false
136-
console.log(chat.messages()); // [AIMessage("Quantum computing uses qubits to...")]
136+
console.log(chat.messages()); // [{ role: 'assistant', content: 'Quantum computing uses qubits to...' }]
137137
```
138138
</Step>
139139

@@ -168,16 +168,11 @@ const lastMessage = computed(() => chat.messages().at(-1));
168168

169169
// Extract just the assistant's messages
170170
const assistantMessages = computed(() =>
171-
chat.messages().filter(m => m._getType() === 'ai')
171+
chat.messages().filter(m => m.role === 'assistant')
172172
);
173173

174174
// Track which tools the agent is actively calling
175-
const activeTools = computed(() =>
176-
chat.messages()
177-
.filter(m => m._getType() === 'ai')
178-
.flatMap(m => m.tool_calls ?? [])
179-
.filter(tc => !tc.result)
180-
);
175+
const activeTools = computed(() => chat.toolCalls());
181176

182177
// Build a user-facing error message
183178
const errorDisplay = computed(() => {
@@ -195,7 +190,7 @@ const errorDisplay = computed(() => {
195190
const viewModel = computed(() => ({
196191
messages: chat.messages(),
197192
isStreaming: chat.isLoading(),
198-
canSend: chat.status() !== 'loading',
193+
canSend: !chat.isLoading(),
199194
messageCount: messageCount(),
200195
error: errorDisplay(),
201196
}));
@@ -238,10 +233,10 @@ effect(() => {
238233
// Track streaming duration for performance monitoring
239234
effect(() => {
240235
const status = chat.status();
241-
if (status === 'loading') {
236+
if (status === 'running') {
242237
this.streamStart = performance.now();
243238
}
244-
if (status === 'resolved' && this.streamStart) {
239+
if (status === 'idle' && this.streamStart) {
245240
const duration = performance.now() - this.streamStart;
246241
this.analytics.track('stream_duration_ms', { duration });
247242
this.streamStart = null;
@@ -267,7 +262,7 @@ import { agent } from '@ngaf/langgraph';
267262
template: `
268263
<!-- Status bar -->
269264
@switch (chat.status()) {
270-
@case ('loading') {
265+
@case ('running') {
271266
<div class="status-bar streaming">
272267
Agent is responding...
273268
</div>
@@ -283,18 +278,18 @@ import { agent } from '@ngaf/langgraph';
283278
<!-- Message list -->
284279
<div class="messages" #chatContainer>
285280
@for (message of chat.messages(); track $index) {
286-
@switch (message._getType()) {
287-
@case ('human') {
281+
@switch (message.role) {
282+
@case ('user') {
288283
<div class="message user">
289284
{{ message.content }}
290285
</div>
291286
}
292-
@case ('ai') {
287+
@case ('assistant') {
293288
<div class="message assistant">
294289
{{ message.content }}
295290
296291
<!-- Show tool calls if the assistant invoked any -->
297-
@for (tool of message.tool_calls ?? []; track tool.id) {
292+
@for (tool of chat.toolCalls(); track tool.id) {
298293
<div class="tool-call">
299294
Called: {{ tool.name }}
300295
</div>
@@ -460,14 +455,14 @@ import { agent } from '@ngaf/langgraph';
460455
changeDetection: ChangeDetectionStrategy.OnPush,
461456
template: `
462457
@for (msg of chat.messages(); track $index) {
463-
@switch (msg._getType()) {
464-
@case ('human') {
458+
@switch (msg.role) {
459+
@case ('user') {
465460
<div class="user">{{ msg.content }}</div>
466461
}
467-
@case ('ai') {
462+
@case ('assistant') {
468463
<div class="assistant">
469464
{{ msg.content }}
470-
@for (tc of msg.tool_calls ?? []; track tc.id) {
465+
@for (tc of chat.toolCalls(); track tc.id) {
471466
<span class="tool-badge">{{ tc.name }}</span>
472467
}
473468
</div>
@@ -491,7 +486,7 @@ export class ChatComponent {
491486
// Derived state from the Python agent's output
492487
toolsUsed = computed(() =>
493488
this.chat.messages()
494-
.filter(m => m._getType() === 'tool')
489+
.filter(m => m.role === 'tool')
495490
.map(m => m.name)
496491
);
497492

0 commit comments

Comments
 (0)