@skroyc/ag-ui-middleware-callbacks 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +199 -0
- package/dist/index.d.mts +690 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SkrOYC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# ag-ui-middleware-callbacks
|
|
2
|
+
|
|
3
|
+
LangChain.js integration providing both middleware and callbacks for AG-UI protocol compatibility.
|
|
4
|
+
|
|
5
|
+
Now with official `@ag-ui/core` types and `@ag-ui/proto` support for Protocol Buffer encoding!
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun install ag-ui-middleware-callbacks
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Official Protocol Types**: Uses `@ag-ui/core` for type definitions and validation schemas
|
|
16
|
+
- **Protocol Buffer Support**: Binary encoding via `@ag-ui/proto` (60-80% smaller payloads)
|
|
17
|
+
- **SSE Transport**: Traditional Server-Sent Events transport
|
|
18
|
+
- **Middleware**: Lifecycle and state management (beforeAgent, afterAgent, state snapshots)
|
|
19
|
+
- **Callbacks**: Streaming events (TEXT_MESSAGE_CONTENT, TOOL_CALL_ARGS, tool lifecycle)
|
|
20
|
+
- **Validation**: Optional runtime validation using official Zod schemas
|
|
21
|
+
|
|
22
|
+
For complete specifications and implementation details, see [SPEC.md](./SPEC.md).
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### SSE Transport (Default)
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { createAGUIAgent, createSSETransport, AGUICallbackHandler } from "ag-ui-middleware-callbacks";
|
|
30
|
+
|
|
31
|
+
// Create SSE transport
|
|
32
|
+
const transport = createSSETransport(req, res);
|
|
33
|
+
|
|
34
|
+
// Create AG-UI enabled agent
|
|
35
|
+
const agent = createAGUIAgent({
|
|
36
|
+
model,
|
|
37
|
+
tools,
|
|
38
|
+
transport,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Stream with callbacks (required for TEXT_MESSAGE events)
|
|
42
|
+
const eventStream = await agent.streamEvents(
|
|
43
|
+
{ messages },
|
|
44
|
+
{
|
|
45
|
+
version: "v2",
|
|
46
|
+
callbacks: [new AGUICallbackHandler(transport)]
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
for await (const event of eventStream) {
|
|
51
|
+
// Events automatically emitted via transport
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Protobuf Transport (New!)
|
|
56
|
+
|
|
57
|
+
For bandwidth-efficient binary encoding:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import {
|
|
61
|
+
createAGUIAgent,
|
|
62
|
+
createProtobufTransport,
|
|
63
|
+
AGUI_MEDIA_TYPE,
|
|
64
|
+
AGUICallbackHandler
|
|
65
|
+
} from "ag-ui-middleware-callbacks";
|
|
66
|
+
|
|
67
|
+
app.post('/api/agent', (req, res) => {
|
|
68
|
+
// Check client preference via Accept header
|
|
69
|
+
const acceptProtobuf = req.headers.accept?.includes(AGUI_MEDIA_TYPE);
|
|
70
|
+
|
|
71
|
+
const transport = acceptProtobuf
|
|
72
|
+
? createProtobufTransport(req, res)
|
|
73
|
+
: createSSETransport(req, res);
|
|
74
|
+
|
|
75
|
+
const agent = createAGUIAgent({
|
|
76
|
+
model,
|
|
77
|
+
tools,
|
|
78
|
+
transport,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ... stream events
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### Transports
|
|
88
|
+
|
|
89
|
+
| Function | Description |
|
|
90
|
+
|----------|-------------|
|
|
91
|
+
| `createSSETransport(req, res)` | Server-Sent Events (text/event-stream) |
|
|
92
|
+
| `createProtobufTransport(req, res)` | Protocol Buffer binary encoding |
|
|
93
|
+
|
|
94
|
+
### Protobuf Utilities
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import {
|
|
98
|
+
encodeEventWithFraming, // Encode event with 4-byte length prefix
|
|
99
|
+
decodeEventWithFraming, // Decode framed protobuf event
|
|
100
|
+
AGUI_MEDIA_TYPE, // "application/vnd.ag-ui.event+proto"
|
|
101
|
+
} from "ag-ui-middleware-callbacks";
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Validation
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import {
|
|
108
|
+
validateEvent, // Validate event against @ag-ui/core schemas
|
|
109
|
+
isValidEvent, // Boolean check for event validity
|
|
110
|
+
createValidatingTransport, // Wrap transport with validation
|
|
111
|
+
} from "ag-ui-middleware-callbacks";
|
|
112
|
+
|
|
113
|
+
// Optional: Enable validation in development
|
|
114
|
+
const validatingTransport = createValidatingTransport(transport, {
|
|
115
|
+
throwOnInvalid: false, // Log warnings instead of throwing
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### @ag-ui/core Re-exports
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import {
|
|
123
|
+
EventType, // Event type enum (RUN_STARTED, TEXT_MESSAGE_CONTENT, etc.)
|
|
124
|
+
EventSchemas, // Zod discriminated union for all events
|
|
125
|
+
encodeProtobuf, // Direct access to @ag-ui/proto encode
|
|
126
|
+
decodeProtobuf, // Direct access to @ag-ui/proto decode
|
|
127
|
+
} from "ag-ui-middleware-callbacks";
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
### Middleware Options
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const agent = createAGUIAgent({
|
|
136
|
+
model,
|
|
137
|
+
tools,
|
|
138
|
+
transport,
|
|
139
|
+
middlewareOptions: {
|
|
140
|
+
emitStateSnapshots: "initial", // "initial" | "final" | "none"
|
|
141
|
+
emitActivities: false,
|
|
142
|
+
validateEvents: false, // Enable for debugging
|
|
143
|
+
// ... other options
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Streaming Events
|
|
149
|
+
|
|
150
|
+
For streaming events (TEXT_MESSAGE_CONTENT, TOOL_CALL_ARGS), callbacks must be passed at runtime:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { AGUICallbackHandler } from "ag-ui-middleware-callbacks";
|
|
154
|
+
|
|
155
|
+
const eventStream = await agent.streamEvents(
|
|
156
|
+
{ messages },
|
|
157
|
+
{
|
|
158
|
+
version: "v2",
|
|
159
|
+
callbacks: [new AGUICallbackHandler(transport)] // REQUIRED for streaming
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
for await (const event of eventStream) {
|
|
164
|
+
// Handle events
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Note: The AGUICallbackHandler must be passed at runtime for streaming events to work correctly. See SPEC.md for details.
|
|
169
|
+
|
|
170
|
+
## Protocol Compliance
|
|
171
|
+
|
|
172
|
+
This package uses official `@ag-ui/core` (v0.0.42+) types and schemas:
|
|
173
|
+
- All 26 stable event types are supported
|
|
174
|
+
- Zod schemas for runtime validation
|
|
175
|
+
- Protocol Buffer encoding via `@ag-ui/proto`
|
|
176
|
+
|
|
177
|
+
### Known Limitations
|
|
178
|
+
|
|
179
|
+
Some events are not yet supported by `@ag-ui/proto` for binary encoding:
|
|
180
|
+
- `TOOL_CALL_RESULT`
|
|
181
|
+
- `ACTIVITY_SNAPSHOT`
|
|
182
|
+
- `ACTIVITY_DELTA`
|
|
183
|
+
|
|
184
|
+
These events will be encoded but may fail decoding. Use SSE transport for full event support.
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Install dependencies
|
|
190
|
+
bun install
|
|
191
|
+
|
|
192
|
+
# Run tests
|
|
193
|
+
bun test
|
|
194
|
+
|
|
195
|
+
# Build
|
|
196
|
+
bun run build
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
This project was created using `bun init` in bun v1.3.5. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
import * as langchain from 'langchain';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { Operation } from 'fast-json-patch';
|
|
4
|
+
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
5
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
6
|
+
export { EventSchemas, EventType } from '@ag-ui/core';
|
|
7
|
+
export { AGUI_MEDIA_TYPE, decode as decodeProtobuf, encode as encodeProtobuf } from '@ag-ui/proto';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AG-UI Protocol Event Types
|
|
11
|
+
*
|
|
12
|
+
* This module provides type definitions for the AG-UI protocol events.
|
|
13
|
+
* It maintains backward compatibility with existing code while leveraging
|
|
14
|
+
* @ag-ui/core for validation where applicable.
|
|
15
|
+
*
|
|
16
|
+
* Based on the AG-UI protocol specification:
|
|
17
|
+
* - Lifecycle Events: RUN_STARTED, RUN_FINISHED, RUN_ERROR, STEP_STARTED, STEP_FINISHED
|
|
18
|
+
* - Text Message Events: TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END
|
|
19
|
+
* - Tool Call Events: TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, TOOL_CALL_RESULT, TOOL_CALL_CHUNK
|
|
20
|
+
* - State Events: STATE_SNAPSHOT, STATE_DELTA, MESSAGES_SNAPSHOT
|
|
21
|
+
* - Activity Events: ACTIVITY_SNAPSHOT, ACTIVITY_DELTA
|
|
22
|
+
* - Thinking Events: THINKING_START, THINKING_TEXT_MESSAGE_START, THINKING_TEXT_MESSAGE_CONTENT, THINKING_TEXT_MESSAGE_END, THINKING_END
|
|
23
|
+
* - Special Events: RAW, CUSTOM
|
|
24
|
+
*
|
|
25
|
+
* @see https://docs.ag-ui.com/introduction
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
type MessageRole = "developer" | "system" | "assistant" | "user" | "tool" | "activity";
|
|
30
|
+
interface ToolCall {
|
|
31
|
+
id: string;
|
|
32
|
+
type: "function";
|
|
33
|
+
function: {
|
|
34
|
+
name: string;
|
|
35
|
+
arguments: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface Message {
|
|
39
|
+
id: string;
|
|
40
|
+
role: MessageRole;
|
|
41
|
+
content?: string;
|
|
42
|
+
name?: string;
|
|
43
|
+
toolCalls?: ToolCall[];
|
|
44
|
+
toolCallId?: string;
|
|
45
|
+
error?: string;
|
|
46
|
+
}
|
|
47
|
+
interface RunStartedEvent {
|
|
48
|
+
type: "RUN_STARTED";
|
|
49
|
+
threadId: string;
|
|
50
|
+
runId: string;
|
|
51
|
+
parentRunId?: string;
|
|
52
|
+
input?: unknown;
|
|
53
|
+
timestamp?: number;
|
|
54
|
+
}
|
|
55
|
+
interface RunFinishedEvent {
|
|
56
|
+
type: "RUN_FINISHED";
|
|
57
|
+
threadId: string;
|
|
58
|
+
runId: string;
|
|
59
|
+
result?: unknown;
|
|
60
|
+
timestamp?: number;
|
|
61
|
+
}
|
|
62
|
+
interface RunErrorEvent {
|
|
63
|
+
type: "RUN_ERROR";
|
|
64
|
+
message: string;
|
|
65
|
+
code?: string;
|
|
66
|
+
timestamp?: number;
|
|
67
|
+
}
|
|
68
|
+
interface StepStartedEvent {
|
|
69
|
+
type: "STEP_STARTED";
|
|
70
|
+
stepName: string;
|
|
71
|
+
timestamp?: number;
|
|
72
|
+
}
|
|
73
|
+
interface StepFinishedEvent {
|
|
74
|
+
type: "STEP_FINISHED";
|
|
75
|
+
stepName: string;
|
|
76
|
+
timestamp?: number;
|
|
77
|
+
}
|
|
78
|
+
interface TextMessageStartEvent {
|
|
79
|
+
type: "TEXT_MESSAGE_START";
|
|
80
|
+
messageId: string;
|
|
81
|
+
role?: "developer" | "system" | "assistant" | "user";
|
|
82
|
+
timestamp?: number;
|
|
83
|
+
}
|
|
84
|
+
interface TextMessageContentEvent {
|
|
85
|
+
type: "TEXT_MESSAGE_CONTENT";
|
|
86
|
+
messageId: string;
|
|
87
|
+
delta: string;
|
|
88
|
+
timestamp?: number;
|
|
89
|
+
}
|
|
90
|
+
interface TextMessageEndEvent {
|
|
91
|
+
type: "TEXT_MESSAGE_END";
|
|
92
|
+
messageId: string;
|
|
93
|
+
timestamp?: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* TextMessageChunk (convenience): Auto-expands to Start → Content → End
|
|
97
|
+
*/
|
|
98
|
+
interface TextMessageChunkEvent {
|
|
99
|
+
type: "TEXT_MESSAGE_CHUNK";
|
|
100
|
+
messageId?: string;
|
|
101
|
+
role?: "developer" | "system" | "assistant" | "user";
|
|
102
|
+
delta?: string;
|
|
103
|
+
timestamp?: number;
|
|
104
|
+
}
|
|
105
|
+
interface ToolCallStartEvent {
|
|
106
|
+
type: "TOOL_CALL_START";
|
|
107
|
+
toolCallId: string;
|
|
108
|
+
toolCallName: string;
|
|
109
|
+
parentMessageId?: string;
|
|
110
|
+
timestamp?: number;
|
|
111
|
+
}
|
|
112
|
+
interface ToolCallArgsEvent {
|
|
113
|
+
type: "TOOL_CALL_ARGS";
|
|
114
|
+
toolCallId: string;
|
|
115
|
+
delta: string;
|
|
116
|
+
timestamp?: number;
|
|
117
|
+
}
|
|
118
|
+
interface ToolCallEndEvent {
|
|
119
|
+
type: "TOOL_CALL_END";
|
|
120
|
+
toolCallId: string;
|
|
121
|
+
timestamp?: number;
|
|
122
|
+
}
|
|
123
|
+
interface ToolCallResultEvent {
|
|
124
|
+
type: "TOOL_CALL_RESULT";
|
|
125
|
+
messageId: string;
|
|
126
|
+
toolCallId: string;
|
|
127
|
+
content: string;
|
|
128
|
+
role?: "tool";
|
|
129
|
+
timestamp?: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* ToolCallChunk (convenience): Auto-expands to Start → Args → End
|
|
133
|
+
*/
|
|
134
|
+
interface ToolCallChunkEvent {
|
|
135
|
+
type: "TOOL_CALL_CHUNK";
|
|
136
|
+
toolCallId?: string;
|
|
137
|
+
toolCallName?: string;
|
|
138
|
+
parentMessageId?: string;
|
|
139
|
+
delta?: string;
|
|
140
|
+
timestamp?: number;
|
|
141
|
+
}
|
|
142
|
+
interface StateSnapshotEvent {
|
|
143
|
+
type: "STATE_SNAPSHOT";
|
|
144
|
+
snapshot: unknown;
|
|
145
|
+
timestamp?: number;
|
|
146
|
+
}
|
|
147
|
+
interface StateDeltaEvent {
|
|
148
|
+
type: "STATE_DELTA";
|
|
149
|
+
delta: Operation[];
|
|
150
|
+
timestamp?: number;
|
|
151
|
+
}
|
|
152
|
+
interface MessagesSnapshotEvent {
|
|
153
|
+
type: "MESSAGES_SNAPSHOT";
|
|
154
|
+
messages: Message[];
|
|
155
|
+
timestamp?: number;
|
|
156
|
+
}
|
|
157
|
+
interface ActivitySnapshotEvent {
|
|
158
|
+
type: "ACTIVITY_SNAPSHOT";
|
|
159
|
+
messageId: string;
|
|
160
|
+
activityType: string;
|
|
161
|
+
content: Record<string, unknown>;
|
|
162
|
+
replace?: boolean;
|
|
163
|
+
timestamp?: number;
|
|
164
|
+
}
|
|
165
|
+
interface ActivityDeltaEvent {
|
|
166
|
+
type: "ACTIVITY_DELTA";
|
|
167
|
+
messageId: string;
|
|
168
|
+
activityType: string;
|
|
169
|
+
patch: Operation[];
|
|
170
|
+
timestamp?: number;
|
|
171
|
+
}
|
|
172
|
+
interface ThinkingStartEvent {
|
|
173
|
+
type: "THINKING_START";
|
|
174
|
+
title?: string;
|
|
175
|
+
messageId?: string;
|
|
176
|
+
timestamp?: number;
|
|
177
|
+
}
|
|
178
|
+
interface ThinkingTextMessageStartEvent {
|
|
179
|
+
type: "THINKING_TEXT_MESSAGE_START";
|
|
180
|
+
messageId: string;
|
|
181
|
+
timestamp?: number;
|
|
182
|
+
}
|
|
183
|
+
interface ThinkingTextMessageContentEvent {
|
|
184
|
+
type: "THINKING_TEXT_MESSAGE_CONTENT";
|
|
185
|
+
messageId: string;
|
|
186
|
+
delta: string;
|
|
187
|
+
timestamp?: number;
|
|
188
|
+
}
|
|
189
|
+
interface ThinkingTextMessageEndEvent {
|
|
190
|
+
type: "THINKING_TEXT_MESSAGE_END";
|
|
191
|
+
messageId: string;
|
|
192
|
+
timestamp?: number;
|
|
193
|
+
}
|
|
194
|
+
interface ThinkingEndEvent {
|
|
195
|
+
type: "THINKING_END";
|
|
196
|
+
timestamp?: number;
|
|
197
|
+
}
|
|
198
|
+
interface RawEvent {
|
|
199
|
+
type: "RAW";
|
|
200
|
+
event: unknown;
|
|
201
|
+
source?: string;
|
|
202
|
+
}
|
|
203
|
+
interface CustomEvent {
|
|
204
|
+
type: "CUSTOM";
|
|
205
|
+
name: string;
|
|
206
|
+
value: unknown;
|
|
207
|
+
}
|
|
208
|
+
type AGUIEvent = RunStartedEvent | RunFinishedEvent | RunErrorEvent | StepStartedEvent | StepFinishedEvent | TextMessageStartEvent | TextMessageContentEvent | TextMessageEndEvent | TextMessageChunkEvent | ToolCallStartEvent | ToolCallArgsEvent | ToolCallEndEvent | ToolCallResultEvent | ToolCallChunkEvent | StateSnapshotEvent | StateDeltaEvent | MessagesSnapshotEvent | ActivitySnapshotEvent | ActivityDeltaEvent | ThinkingStartEvent | ThinkingTextMessageStartEvent | ThinkingTextMessageContentEvent | ThinkingTextMessageEndEvent | ThinkingEndEvent | RawEvent | CustomEvent;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* AGUI Transport Interface
|
|
212
|
+
*
|
|
213
|
+
* A custom abstraction for AG-UI event emission.
|
|
214
|
+
* The AG-UI protocol defines event formats but leaves transport mechanisms implementation-defined.
|
|
215
|
+
* This interface provides a simple, portable way to emit events that works with any backend transport.
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Transport interface for AG-UI event emission.
|
|
220
|
+
*/
|
|
221
|
+
interface AGUITransport {
|
|
222
|
+
/**
|
|
223
|
+
* Emit an AG-UI protocol event.
|
|
224
|
+
*/
|
|
225
|
+
emit(event: AGUIEvent): void;
|
|
226
|
+
/**
|
|
227
|
+
* Optional connection lifecycle methods.
|
|
228
|
+
*/
|
|
229
|
+
connect?(): Promise<void>;
|
|
230
|
+
disconnect?(): void;
|
|
231
|
+
isConnected?(): boolean;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Extended Protobuf transport interface with binary encoding utilities.
|
|
235
|
+
*
|
|
236
|
+
* Provides all base AGUITransport functionality plus:
|
|
237
|
+
* - Abort signal for client disconnect handling
|
|
238
|
+
* - Binary encoding/decoding utilities
|
|
239
|
+
*/
|
|
240
|
+
interface ProtobufTransport extends AGUITransport {
|
|
241
|
+
/** Abort signal triggered on client disconnect */
|
|
242
|
+
signal: AbortSignal;
|
|
243
|
+
/**
|
|
244
|
+
* Encode an event with 4-byte Big-Endian length prefix.
|
|
245
|
+
* Useful for manual encoding when needed.
|
|
246
|
+
*/
|
|
247
|
+
encodeEvent(event: AGUIEvent): Uint8Array;
|
|
248
|
+
/**
|
|
249
|
+
* Decode a framed event (with 4-byte length prefix).
|
|
250
|
+
* Useful for parsing received protobuf data.
|
|
251
|
+
*/
|
|
252
|
+
decodeEvent(data: Uint8Array): AGUIEvent;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* AG-UI Middleware Types and Configuration
|
|
257
|
+
*
|
|
258
|
+
* Defines the middleware options schema and types for AG-UI protocol integration.
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Middleware options schema with Zod validation.
|
|
263
|
+
*/
|
|
264
|
+
declare const AGUIMiddlewareOptionsSchema: z.ZodObject<{
|
|
265
|
+
transport: z.ZodType<AGUITransport, z.ZodTypeDef, AGUITransport>;
|
|
266
|
+
emitToolResults: z.ZodDefault<z.ZodBoolean>;
|
|
267
|
+
emitStateSnapshots: z.ZodDefault<z.ZodEnum<["initial", "final", "all", "none"]>>;
|
|
268
|
+
emitActivities: z.ZodDefault<z.ZodBoolean>;
|
|
269
|
+
maxUIPayloadSize: z.ZodDefault<z.ZodNumber>;
|
|
270
|
+
chunkLargeResults: z.ZodDefault<z.ZodBoolean>;
|
|
271
|
+
threadIdOverride: z.ZodOptional<z.ZodString>;
|
|
272
|
+
runIdOverride: z.ZodOptional<z.ZodString>;
|
|
273
|
+
errorDetailLevel: z.ZodDefault<z.ZodEnum<["full", "message", "code", "none"]>>;
|
|
274
|
+
stateMapper: z.ZodOptional<z.ZodType<(state: any) => any, z.ZodTypeDef, (state: any) => any>>;
|
|
275
|
+
resultMapper: z.ZodOptional<z.ZodType<(result: any) => any, z.ZodTypeDef, (result: any) => any>>;
|
|
276
|
+
activityMapper: z.ZodOptional<z.ZodType<(node: any) => any, z.ZodTypeDef, (node: any) => any>>;
|
|
277
|
+
/**
|
|
278
|
+
* Enable runtime validation of events against @ag-ui/core schemas.
|
|
279
|
+
* Disabled by default for performance. Enable in development for debugging.
|
|
280
|
+
*
|
|
281
|
+
* - false (default): No validation, events emitted as-is
|
|
282
|
+
* - true: Validate events, log warnings for invalid events
|
|
283
|
+
* - "strict": Validate events, throw on invalid events
|
|
284
|
+
*/
|
|
285
|
+
validateEvents: z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodLiteral<"strict">]>>;
|
|
286
|
+
}, "strip", z.ZodTypeAny, {
|
|
287
|
+
transport: AGUITransport;
|
|
288
|
+
emitToolResults: boolean;
|
|
289
|
+
emitStateSnapshots: "initial" | "final" | "all" | "none";
|
|
290
|
+
emitActivities: boolean;
|
|
291
|
+
maxUIPayloadSize: number;
|
|
292
|
+
chunkLargeResults: boolean;
|
|
293
|
+
errorDetailLevel: "code" | "message" | "none" | "full";
|
|
294
|
+
validateEvents: boolean | "strict";
|
|
295
|
+
threadIdOverride?: string | undefined;
|
|
296
|
+
runIdOverride?: string | undefined;
|
|
297
|
+
stateMapper?: ((state: any) => any) | undefined;
|
|
298
|
+
resultMapper?: ((result: any) => any) | undefined;
|
|
299
|
+
activityMapper?: ((node: any) => any) | undefined;
|
|
300
|
+
}, {
|
|
301
|
+
transport: AGUITransport;
|
|
302
|
+
emitToolResults?: boolean | undefined;
|
|
303
|
+
emitStateSnapshots?: "initial" | "final" | "all" | "none" | undefined;
|
|
304
|
+
emitActivities?: boolean | undefined;
|
|
305
|
+
maxUIPayloadSize?: number | undefined;
|
|
306
|
+
chunkLargeResults?: boolean | undefined;
|
|
307
|
+
threadIdOverride?: string | undefined;
|
|
308
|
+
runIdOverride?: string | undefined;
|
|
309
|
+
errorDetailLevel?: "code" | "message" | "none" | "full" | undefined;
|
|
310
|
+
stateMapper?: ((state: any) => any) | undefined;
|
|
311
|
+
resultMapper?: ((result: any) => any) | undefined;
|
|
312
|
+
activityMapper?: ((node: any) => any) | undefined;
|
|
313
|
+
validateEvents?: boolean | "strict" | undefined;
|
|
314
|
+
}>;
|
|
315
|
+
/**
|
|
316
|
+
* Inferred type for middleware options.
|
|
317
|
+
*/
|
|
318
|
+
type AGUIMiddlewareOptions = z.infer<typeof AGUIMiddlewareOptionsSchema>;
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Create AG-UI middleware for LangChain agents.
|
|
322
|
+
*
|
|
323
|
+
* @param options - Middleware configuration options
|
|
324
|
+
* @returns AgentMiddleware instance with lifecycle hooks
|
|
325
|
+
*/
|
|
326
|
+
declare function createAGUIMiddleware(options: AGUIMiddlewareOptions): langchain.AgentMiddleware<undefined, any, any>;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* AG-UI Callback Handler
|
|
330
|
+
*
|
|
331
|
+
* Handles streaming events for LLM tokens and tool calls.
|
|
332
|
+
*/
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Configuration options for the callback handler.
|
|
336
|
+
*/
|
|
337
|
+
interface AGUICallbackHandlerOptions {
|
|
338
|
+
/** Maximum payload size in bytes for UI events (default: 50KB) */
|
|
339
|
+
maxUIPayloadSize?: number;
|
|
340
|
+
/** Whether to chunk large payloads instead of truncating */
|
|
341
|
+
chunkLargeResults?: boolean;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Callback handler for AG-UI protocol streaming events.
|
|
345
|
+
* Handles LLM token streaming and tool call lifecycle events.
|
|
346
|
+
*/
|
|
347
|
+
declare class AGUICallbackHandler extends BaseCallbackHandler {
|
|
348
|
+
name: string;
|
|
349
|
+
private messageIds;
|
|
350
|
+
private latestMessageIds;
|
|
351
|
+
private agentRunIds;
|
|
352
|
+
private parentToAuthoritativeId;
|
|
353
|
+
private thinkingIds;
|
|
354
|
+
private toolCallInfo;
|
|
355
|
+
private toolCallNames;
|
|
356
|
+
private agentTurnTracker;
|
|
357
|
+
private pendingToolCalls;
|
|
358
|
+
private accumulatedToolArgs;
|
|
359
|
+
private transport;
|
|
360
|
+
private maxUIPayloadSize;
|
|
361
|
+
private chunkLargeResults;
|
|
362
|
+
constructor(transport: AGUITransport, options?: AGUICallbackHandlerOptions);
|
|
363
|
+
dispose(): void;
|
|
364
|
+
/**
|
|
365
|
+
* Emit a TEXT_MESSAGE_CHUNK event (convenience method)
|
|
366
|
+
* Auto-expands to START → CONTENT → END lifecycle
|
|
367
|
+
*
|
|
368
|
+
* Use this for simple cases where you have the complete message at once
|
|
369
|
+
* instead of handling the streaming lifecycle manually.
|
|
370
|
+
*
|
|
371
|
+
* @param messageId - Unique message identifier (auto-generated if not provided)
|
|
372
|
+
* @param role - Message role (defaults to "assistant")
|
|
373
|
+
* @param delta - Text content to emit
|
|
374
|
+
*/
|
|
375
|
+
emitTextChunk(messageId: string, role: "assistant" | "user" | "system" | "developer" | undefined, delta: string): Promise<void>;
|
|
376
|
+
/**
|
|
377
|
+
* Emit a TOOL_CALL_CHUNK event (convenience method)
|
|
378
|
+
* Auto-expands to START → ARGS → END lifecycle
|
|
379
|
+
*
|
|
380
|
+
* Use this for simple tool calls where you have the complete arguments at once
|
|
381
|
+
* instead of handling the streaming lifecycle manually.
|
|
382
|
+
*
|
|
383
|
+
* @param toolCallId - Unique tool call identifier (auto-generated if not provided)
|
|
384
|
+
* @param toolCallName - Name of the tool being called
|
|
385
|
+
* @param delta - Tool arguments (JSON string)
|
|
386
|
+
* @param parentMessageId - ID of the message that triggered this tool call
|
|
387
|
+
*/
|
|
388
|
+
emitToolChunk(toolCallId: string, toolCallName: string, delta: string, parentMessageId?: string): Promise<void>;
|
|
389
|
+
handleLLMStart(_llm: any, _prompts: string[], runId: string, _parentRunId?: string, _extraParams?: Record<string, unknown>, _tags?: string[], _metadata?: Record<string, unknown>, _runName?: string): Promise<void>;
|
|
390
|
+
handleLLMNewToken(token: string, _idx: any, runId: string, _parentRunId?: string, _tags?: string[], fields?: any): Promise<void>;
|
|
391
|
+
handleLLMEnd(_output: any, runId: string, _parentRunId?: string, _tags?: string[], _extraParams?: Record<string, unknown>): Promise<void>;
|
|
392
|
+
handleLLMError(_error: Error, runId: string, _parentRunId?: string): Promise<void>;
|
|
393
|
+
handleToolStart(tool: any, input: string, runId: string, parentRunId?: string, _tags?: string[], metadata?: Record<string, unknown>, runName?: string): Promise<void>;
|
|
394
|
+
handleToolEnd(output: any, runId: string, parentRunId?: string): Promise<void>;
|
|
395
|
+
handleToolError(_error: Error, runId: string, parentRunId?: string): Promise<void>;
|
|
396
|
+
private chunkString;
|
|
397
|
+
private emitToolResultWithPolicy;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* AG-UI Agent Factory
|
|
402
|
+
*
|
|
403
|
+
* Creates a LangChain agent with automatic AG-UI protocol integration.
|
|
404
|
+
*
|
|
405
|
+
* Architecture:
|
|
406
|
+
* - Uses createAgent() from langchain package
|
|
407
|
+
* - Returns agent with callbacks bound to graph via withConfig
|
|
408
|
+
* - Emits lifecycle events for agent execution (RUN_STARTED, RUN_FINISHED, etc.)
|
|
409
|
+
* - Callbacks are merged with user-provided callbacks by LangChain
|
|
410
|
+
* - Abort signal from context enables client disconnect handling
|
|
411
|
+
*/
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Configuration for creating an AG-UI enabled agent.
|
|
415
|
+
*/
|
|
416
|
+
interface AGUIAgentConfig {
|
|
417
|
+
/** The language model to use */
|
|
418
|
+
model: any;
|
|
419
|
+
/** The tools available to the agent */
|
|
420
|
+
tools: any[];
|
|
421
|
+
/** The transport for AG-UI events */
|
|
422
|
+
transport: AGUITransport;
|
|
423
|
+
/** Optional middleware configuration */
|
|
424
|
+
middlewareOptions?: Partial<AGUIMiddlewareOptions>;
|
|
425
|
+
/** Optional callback handler configuration */
|
|
426
|
+
callbackOptions?: AGUICallbackHandlerOptions;
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Create an AG-UI enabled agent.
|
|
430
|
+
*
|
|
431
|
+
* This function creates a LangChain agent with automatic AG-UI protocol integration:
|
|
432
|
+
* - Middleware handles lifecycle events (RUN_STARTED, RUN_FINISHED, etc.)
|
|
433
|
+
* - Callbacks handle streaming events (TEXT_MESSAGE_CONTENT, TOOL_CALL_ARGS, etc.)
|
|
434
|
+
* - Callbacks must be passed at runtime via agent.streamEvents() config
|
|
435
|
+
* - Guaranteed cleanup via middleware wrapModelCall with try-finally
|
|
436
|
+
*
|
|
437
|
+
* Note: Callbacks are not bound to the model here because:
|
|
438
|
+
* 1. Some models (like MockChatModel in tests) don't properly support withConfig()
|
|
439
|
+
* 2. Users should pass callbacks at runtime for proper streaming
|
|
440
|
+
*
|
|
441
|
+
* @param config - Agent configuration
|
|
442
|
+
* @returns An agent with AG-UI protocol support
|
|
443
|
+
*/
|
|
444
|
+
declare function createAGUIAgent(config: AGUIAgentConfig): any;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* SSE Transport Implementation
|
|
448
|
+
*
|
|
449
|
+
* Server-Sent Events transport for AG-UI protocol.
|
|
450
|
+
* Provides:
|
|
451
|
+
* - Proper SSE headers
|
|
452
|
+
* - Fail-safe emission (never throws on client disconnect)
|
|
453
|
+
* - Abort signal integration for client disconnect handling
|
|
454
|
+
* - Backpressure handling with queue-based emission
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Extended SSE transport interface with abort signal.
|
|
459
|
+
*/
|
|
460
|
+
interface SSETransport extends AGUITransport {
|
|
461
|
+
/** Abort signal triggered on client disconnect */
|
|
462
|
+
signal: AbortSignal;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* HTTP request interface for SSE transport.
|
|
466
|
+
*/
|
|
467
|
+
interface SSETransportRequest {
|
|
468
|
+
on(event: string, callback: () => void): void;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* HTTP response interface for SSE transport.
|
|
472
|
+
*/
|
|
473
|
+
interface SSETransportResponse {
|
|
474
|
+
setHeader(name: string, value: string): SSETransportResponse;
|
|
475
|
+
write(data: string): boolean;
|
|
476
|
+
end?(): void;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Create an SSE transport for Server-Sent Events.
|
|
480
|
+
*
|
|
481
|
+
* @param req - HTTP request object (listens for 'close' event)
|
|
482
|
+
* @param res - HTTP response object
|
|
483
|
+
* @returns SSETransport with emit method and abort signal
|
|
484
|
+
*/
|
|
485
|
+
declare function createSSETransport(req: SSETransportRequest, res: SSETransportResponse): SSETransport;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Protobuf Transport Implementation
|
|
489
|
+
*
|
|
490
|
+
* Protocol Buffer transport for AG-UI protocol.
|
|
491
|
+
* Provides:
|
|
492
|
+
* - Binary encoding using @ag-ui/proto
|
|
493
|
+
* - 4-byte Big-Endian length prefix per protocol spec
|
|
494
|
+
* - Fail-safe emission (never throws on client disconnect)
|
|
495
|
+
* - Abort signal integration for client disconnect handling
|
|
496
|
+
* - Backpressure handling with queue-based emission
|
|
497
|
+
*
|
|
498
|
+
* Protobuf provides 60-80% smaller payloads compared to JSON/SSE.
|
|
499
|
+
*
|
|
500
|
+
* @see https://docs.ag-ui.com/introduction
|
|
501
|
+
*/
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* HTTP request interface for Protobuf transport.
|
|
505
|
+
*/
|
|
506
|
+
interface ProtobufTransportRequest {
|
|
507
|
+
on(event: string, callback: () => void): void;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* HTTP response interface for Protobuf transport.
|
|
511
|
+
*/
|
|
512
|
+
interface ProtobufTransportResponse {
|
|
513
|
+
setHeader(name: string, value: string): ProtobufTransportResponse;
|
|
514
|
+
write(data: Buffer | Uint8Array): boolean;
|
|
515
|
+
end?(): void;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Encode an AG-UI event with 4-byte Big-Endian length prefix.
|
|
519
|
+
*
|
|
520
|
+
* Per AG-UI protocol spec:
|
|
521
|
+
* ┌─────────────────┬──────────────────────────────────┐
|
|
522
|
+
* │ Length (4 BE) │ Protobuf Event Bytes │
|
|
523
|
+
* └─────────────────┴──────────────────────────────────┘
|
|
524
|
+
*
|
|
525
|
+
* @param event - The AG-UI event to encode
|
|
526
|
+
* @returns Uint8Array with length prefix + protobuf bytes
|
|
527
|
+
*/
|
|
528
|
+
declare function encodeEventWithFraming(event: AGUIEvent): Uint8Array;
|
|
529
|
+
/**
|
|
530
|
+
* Decode a framed protobuf event (with 4-byte length prefix).
|
|
531
|
+
*
|
|
532
|
+
* @param data - Buffer containing length prefix + protobuf bytes
|
|
533
|
+
* @returns The decoded AG-UI event
|
|
534
|
+
*/
|
|
535
|
+
declare function decodeEventWithFraming(data: Uint8Array): AGUIEvent;
|
|
536
|
+
/**
|
|
537
|
+
* Create a Protobuf transport for binary AG-UI protocol communication.
|
|
538
|
+
*
|
|
539
|
+
* @param req - HTTP request object (listens for 'close' event)
|
|
540
|
+
* @param res - HTTP response object
|
|
541
|
+
* @returns ProtobufTransport with emit method and abort signal
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* app.post('/api/agent', (req, res) => {
|
|
546
|
+
* const acceptProtobuf = req.headers.accept?.includes(AGUI_MEDIA_TYPE);
|
|
547
|
+
*
|
|
548
|
+
* if (acceptProtobuf) {
|
|
549
|
+
* const transport = createProtobufTransport(req, res);
|
|
550
|
+
* // Use transport.emit() for binary encoding
|
|
551
|
+
* } else {
|
|
552
|
+
* const transport = createSSETransport(req, res);
|
|
553
|
+
* // Use transport.emit() for JSON/SSE
|
|
554
|
+
* }
|
|
555
|
+
* });
|
|
556
|
+
* ```
|
|
557
|
+
*/
|
|
558
|
+
declare function createProtobufTransport(req: ProtobufTransportRequest, res: ProtobufTransportResponse): ProtobufTransport;
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* ID Generator Utility
|
|
562
|
+
*
|
|
563
|
+
* Generates unique IDs using crypto.randomUUID() or deterministic hashing.
|
|
564
|
+
*/
|
|
565
|
+
/**
|
|
566
|
+
* Generate a unique ID using crypto.randomUUID()
|
|
567
|
+
*
|
|
568
|
+
* @returns A UUID v4 string (e.g., "550e8400-e29b-41d4-a716-446655440000")
|
|
569
|
+
*/
|
|
570
|
+
declare function generateId(): string;
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* State Diff Utility
|
|
574
|
+
*
|
|
575
|
+
* Computes JSON Patch deltas between two state objects.
|
|
576
|
+
* Uses fast-json-patch's compare function to generate RFC 6902 patch operations.
|
|
577
|
+
*/
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Compute the delta between two state objects using JSON Patch (RFC 6902).
|
|
581
|
+
*
|
|
582
|
+
* @param oldState - The previous state object
|
|
583
|
+
* @param newState - The updated state object
|
|
584
|
+
* @returns An array of JSON Patch operations describing the changes
|
|
585
|
+
*/
|
|
586
|
+
declare function computeStateDelta(oldState: unknown, newState: unknown): Operation[];
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Maps a LangChain BaseMessage to an AG-UI Protocol Message.
|
|
590
|
+
*
|
|
591
|
+
* @param message - The LangChain message to map
|
|
592
|
+
* @returns An AG-UI Protocol compliant Message object
|
|
593
|
+
*/
|
|
594
|
+
declare function mapLangChainMessageToAGUI(message: BaseMessage): Message;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Utility to clean up LangChain serialized objects from state/output.
|
|
598
|
+
*/
|
|
599
|
+
/**
|
|
600
|
+
* Recursively removes 'lc', 'type', 'id' (LangChain internal) fields and
|
|
601
|
+
* flattens 'kwargs' if present.
|
|
602
|
+
*/
|
|
603
|
+
declare function cleanLangChainData(data: any): any;
|
|
604
|
+
/**
|
|
605
|
+
* Extracts content from a tool output if it's a serialized ToolMessage or object.
|
|
606
|
+
*/
|
|
607
|
+
declare function extractToolOutput(output: any): string;
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Normalizes and expands convenience events into their explicit counterparts.
|
|
611
|
+
*
|
|
612
|
+
* @param event - The event to expand
|
|
613
|
+
* @returns An array of explicit AG-UI events
|
|
614
|
+
*/
|
|
615
|
+
declare function expandEvent(event: AGUIEvent): AGUIEvent[];
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* AG-UI Event Validation Utilities
|
|
619
|
+
*
|
|
620
|
+
* Provides optional runtime validation of AG-UI events using @ag-ui/core Zod schemas.
|
|
621
|
+
* Validation is disabled by default for performance; enable in development for debugging.
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* ```typescript
|
|
625
|
+
* import { validateEvent, isValidEvent } from './utils/validation';
|
|
626
|
+
*
|
|
627
|
+
* // Safe validation (returns result object)
|
|
628
|
+
* const result = validateEvent(event);
|
|
629
|
+
* if (result.success) {
|
|
630
|
+
* console.log('Valid event:', result.data);
|
|
631
|
+
* } else {
|
|
632
|
+
* console.error('Invalid event:', result.error);
|
|
633
|
+
* }
|
|
634
|
+
*
|
|
635
|
+
* // Boolean check
|
|
636
|
+
* if (isValidEvent(event)) {
|
|
637
|
+
* // event is valid
|
|
638
|
+
* }
|
|
639
|
+
* ```
|
|
640
|
+
*/
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Result of event validation.
|
|
644
|
+
*/
|
|
645
|
+
interface ValidationResult<T = AGUIEvent> {
|
|
646
|
+
success: boolean;
|
|
647
|
+
data?: T;
|
|
648
|
+
error?: {
|
|
649
|
+
message: string;
|
|
650
|
+
issues: Array<{
|
|
651
|
+
path: (string | number)[];
|
|
652
|
+
message: string;
|
|
653
|
+
}>;
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Validate an AG-UI event against @ag-ui/core schemas.
|
|
658
|
+
*
|
|
659
|
+
* Events are now emitted with camelCase field names (toolCalls, toolCallId)
|
|
660
|
+
* which matches the @ag-ui/core schema directly.
|
|
661
|
+
*
|
|
662
|
+
* @param event - The event to validate
|
|
663
|
+
* @returns ValidationResult with success status and any errors
|
|
664
|
+
*/
|
|
665
|
+
declare function validateEvent(event: unknown): ValidationResult;
|
|
666
|
+
/**
|
|
667
|
+
* Check if an event is valid according to @ag-ui/core schemas.
|
|
668
|
+
*
|
|
669
|
+
* @param event - The event to check
|
|
670
|
+
* @returns true if valid, false otherwise
|
|
671
|
+
*/
|
|
672
|
+
declare function isValidEvent(event: unknown): event is AGUIEvent;
|
|
673
|
+
/**
|
|
674
|
+
* Create a validating transport wrapper.
|
|
675
|
+
* Wraps any AGUITransport to add validation before emission.
|
|
676
|
+
*
|
|
677
|
+
* @param transport - The transport to wrap
|
|
678
|
+
* @param options - Validation options
|
|
679
|
+
* @returns Wrapped transport with validation
|
|
680
|
+
*/
|
|
681
|
+
declare function createValidatingTransport<T extends {
|
|
682
|
+
emit: (event: AGUIEvent) => void;
|
|
683
|
+
}>(transport: T, options?: {
|
|
684
|
+
/** Throw on invalid events (default: false - just log warning) */
|
|
685
|
+
throwOnInvalid?: boolean;
|
|
686
|
+
/** Custom logger for validation errors */
|
|
687
|
+
onValidationError?: (event: AGUIEvent, error: ValidationResult['error']) => void;
|
|
688
|
+
}): T;
|
|
689
|
+
|
|
690
|
+
export { type AGUIAgentConfig, AGUICallbackHandler, type AGUIEvent, type AGUIMiddlewareOptions, AGUIMiddlewareOptionsSchema, type AGUITransport, type Message, type MessageRole, type ProtobufTransport, type SSETransport, type ToolCall, type ValidationResult, cleanLangChainData, computeStateDelta, createAGUIAgent, createAGUIMiddleware, createProtobufTransport, createSSETransport, createValidatingTransport, decodeEventWithFraming, encodeEventWithFraming, expandEvent, extractToolOutput, generateId, isValidEvent, mapLangChainMessageToAGUI, validateEvent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import {createMiddleware,createAgent}from'langchain';import {z as z$1}from'zod';import {compare}from'fast-json-patch';import {HumanMessage,AIMessage,ToolMessage,SystemMessage,ChatMessage}from'@langchain/core/messages';import {EventSchemas}from'@ag-ui/core';export{EventSchemas,EventType}from'@ag-ui/core';import {BaseCallbackHandler}from'@langchain/core/callbacks/base';import {encode,decode,AGUI_MEDIA_TYPE}from'@ag-ui/proto';export{AGUI_MEDIA_TYPE,decode as decodeProtobuf,encode as encodeProtobuf}from'@ag-ui/proto';function T(){return crypto.randomUUID()}function E(n,e){if(!n)throw new Error("baseId is required for deterministic ID generation");let t=`${n}-${e}`,s=0;for(let o=0;o<t.length;o++){let c=t.charCodeAt(o);s=(s<<5)-s+c,s=s&s;}let r=Math.abs(s).toString(16).padStart(8,"0");return `${n}-${r}`}function A(n,e){return compare(n,e)}function I(n){let e=n.id||T(),t="assistant",s,r,o=typeof n.content=="string"?n.content:JSON.stringify(n.content);if(n instanceof HumanMessage||n.role==="user"||n._getType?.()==="human")t="user";else if(n instanceof AIMessage||n.role==="assistant"||n._getType?.()==="ai"){t="assistant";let c=n.tool_calls||n.kwargs?.tool_calls;c&&c.length>0&&(s=c.map(p=>({id:p.id,type:"function",function:{name:p.name,arguments:typeof p.args=="string"?p.args:JSON.stringify(p.args)}})));}else n instanceof ToolMessage||n.role==="tool"||n._getType?.()==="tool"?(t="tool",r=n.tool_call_id||n.kwargs?.tool_call_id):n instanceof SystemMessage||n.role==="system"||n._getType?.()==="system"?t="system":(n instanceof ChatMessage||n.role)&&(t=n.role);return {id:e,role:t,content:o,toolCalls:s,toolCallId:r,name:n.name}}function y(n){if(n==null)return n;if(Array.isArray(n))return n.map(y);if(typeof n=="object"){if((n.lc===1||n.lc_serializable===true)&&(n.kwargs||n.lc_kwargs)){let t=n.kwargs||n.lc_kwargs;return y(t)}let e={};for(let[t,s]of Object.entries(n))t==="lc"||t==="type"||t==="id"||t.startsWith("lc_")||(e[t]=y(s));return e}return n}function _(n){if(n==null)return "";let e=n;if(typeof n=="string")try{e=JSON.parse(n);}catch{return n}if(typeof e!="object")return String(e);e.lc===1||e.lc_serializable===true||e.type==="constructor"&&Array.isArray(e.id);let s=e.kwargs||e.lc_kwargs||e;return s&&s.content!==void 0?typeof s.content=="string"?s.content:JSON.stringify(s.content):e.result!==void 0?typeof e.result=="string"?e.result:JSON.stringify(e.result):e.output!==void 0?typeof e.output=="string"?e.output:JSON.stringify(e.output):JSON.stringify(y(e))}var C=z$1.object({transport:z$1.custom(n=>n&&typeof n.emit=="function",{message:"Transport must have an emit function"}),emitToolResults:z$1.boolean().default(true),emitStateSnapshots:z$1.enum(["initial","final","all","none"]).default("initial"),emitActivities:z$1.boolean().default(false),maxUIPayloadSize:z$1.number().positive().default(50*1024),chunkLargeResults:z$1.boolean().default(false),threadIdOverride:z$1.string().optional(),runIdOverride:z$1.string().optional(),errorDetailLevel:z$1.enum(["full","message","code","none"]).default("message"),stateMapper:z$1.custom().optional(),resultMapper:z$1.custom().optional(),activityMapper:z$1.custom().optional(),validateEvents:z$1.union([z$1.boolean(),z$1.literal("strict")]).default(false)});function M(n){try{let e=EventSchemas.safeParse(n);return e.success?{success:!0,data:n}:{success:!1,error:{message:"Event validation failed",issues:e.error.issues.map(t=>({path:t.path,message:t.message}))}}}catch(e){return {success:false,error:{message:e instanceof Error?e.message:"Unknown validation error",issues:[]}}}}function K(n){return M(n).success}function w(n,e={}){let{throwOnInvalid:t=false,onValidationError:s}=e;return {...n,emit:r=>{let o=M(r);if(!o.success&&(s?s(r,o.error):console.warn("[AG-UI Validation] Invalid event:",r.type,o.error),t))throw new Error(`Invalid AG-UI event: ${o.error?.message}`);n.emit(r);}}}function z(n){return n===true||n==="strict"}function F(n){let e=n;if(e.messages&&Array.isArray(e.messages)){let t=e.messages[e.messages.length-1];if(t&&typeof t.content=="string")return t.content.substring(0,100)+(t.content.length>100?"...":"")}return "[no input preview]"}function j(n){let e=n;if(e.messages&&Array.isArray(e.messages)){let t=e.messages[e.messages.length-1];if(t?.toolCalls?.length)return "tool_calls";if(t?.content)return "text"}return "unknown"}function B(n){let e=n;return !!(e.messages&&e.messages.some(t=>t.toolCalls?.length>0))}async function U(n,e,t,s,r,o,c){if(!e)return;let p=`activity-${e}-${t}`,d={status:r,timestamp:Date.now(),...c},l=o?o(d):d;if(!s.currentActivityId||s.currentActivityId!==p)s.currentActivityId=p,s.currentActivityType="AGENT_STEP",s.activityContent=l,n.emit({type:"ACTIVITY_SNAPSHOT",messageId:p,activityType:"AGENT_STEP",content:l,replace:true});else {let g=A(s.activityContent,l);g.length>0&&(s.activityContent=l,n.emit({type:"ACTIVITY_DELTA",messageId:p,activityType:"AGENT_STEP",patch:g}));}}function x(n){let e=C.parse(n),t=e.transport;z(e.validateEvents)&&(t=w(e.transport,{throwOnInvalid:e.validateEvents==="strict"}));let s,r,o,c=0,p={currentActivityId:void 0,currentActivityType:"AGENT_STEP",activityContent:{}};return createMiddleware({name:"ag-ui-lifecycle",contextSchema:z$1.object({run_id:z$1.string().optional(),runId:z$1.string().optional(),thread_id:z$1.string().optional(),threadId:z$1.string().optional()}),beforeAgent:async(l,g)=>{c=0;let i=g,a=i.config?.configurable||i.configurable;s=a?.threadId||a?.thread_id||a?.checkpoint_id||e.threadIdOverride||i.context?.threadId||i.context?.thread_id||"",r=e.runIdOverride||a?.run_id||i.runId||i.id||i.context?.runId||i.context?.run_id||i.config?.runId||crypto.randomUUID();try{if(t.emit({type:"RUN_STARTED",threadId:s,runId:r,input:y(i.config?.input),timestamp:Date.now()}),e.emitStateSnapshots==="initial"||e.emitStateSnapshots==="all"){let h=e.stateMapper?e.stateMapper(l):y(l);!e.stateMapper&&h&&typeof h=="object"&&delete h.messages,t.emit({type:"STATE_SNAPSHOT",snapshot:h,timestamp:Date.now()});}let f=l;f.messages&&Array.isArray(f.messages)&&t.emit({type:"MESSAGES_SNAPSHOT",messages:f.messages.map(I),timestamp:Date.now()});}catch{}let m=i.config;return m&&(m.metadata={...m.metadata||{},agui_runId:r}),{}},beforeModel:async(l,g)=>{let i=c++,a=E(r,i),m=`model_call_${a}`;o=m;let h=g.config;h&&(h.metadata={...h.metadata||{},agui_messageId:a});try{t.emit({type:"STEP_STARTED",stepName:m,timestamp:Date.now()}),e.emitActivities&&await U(t,r,i,p,"started",e.activityMapper,{stepName:m,modelName:g.config?.model?._modelType||"unknown",inputPreview:F(l)});}catch{}return {}},afterModel:async(l,g)=>{try{if(t.emit({type:"STEP_FINISHED",stepName:o||"",timestamp:Date.now()}),e.emitActivities&&o){let i=c-1;await U(t,r,i,p,"completed",e.activityMapper,{stepName:o,outputType:j(l),hasToolCalls:B(l)});}if(e.emitStateSnapshots!=="none"){let i=y(l),a=e.stateMapper?e.stateMapper(i):i;!e.stateMapper&&a&&typeof a=="object"&&delete a.messages,(a?Object.keys(a).filter(f=>a[f]!==void 0&&a[f]!==null):[]).length>0&&t.emit({type:"STATE_SNAPSHOT",snapshot:a,timestamp:Date.now()});}}catch{}return o=void 0,{}},afterAgent:async(l,g)=>{try{if(e.emitStateSnapshots==="final"||e.emitStateSnapshots==="all"){let a=e.stateMapper?e.stateMapper(l):y(l);!e.stateMapper&&a&&typeof a=="object"&&delete a.messages,t.emit({type:"STATE_SNAPSHOT",snapshot:a,timestamp:Date.now()});}let i=l;if(i.error){let a=i.error,m=a instanceof Error?a.message:String(a);t.emit({type:"RUN_ERROR",message:e.errorDetailLevel==="full"||e.errorDetailLevel==="message"?m:"",code:"AGENT_EXECUTION_ERROR",timestamp:Date.now()});}else t.emit({type:"RUN_FINISHED",threadId:s,runId:r,result:e.resultMapper?e.resultMapper(l):void 0,timestamp:Date.now()});}catch{}return {}}})}function S(n){switch(n.type){case "TEXT_MESSAGE_CHUNK":{let e=n.messageId||T(),t=[];return n.role&&t.push({type:"TEXT_MESSAGE_START",messageId:e,role:n.role}),n.delta&&t.push({type:"TEXT_MESSAGE_CONTENT",messageId:e,delta:n.delta}),n.role&&n.delta&&t.push({type:"TEXT_MESSAGE_END",messageId:e}),t.length>0?t:[n]}case "TOOL_CALL_CHUNK":{let e=n.toolCallId||T(),t=[];return n.toolCallName&&t.push({type:"TOOL_CALL_START",toolCallId:e,toolCallName:n.toolCallName,parentMessageId:n.parentMessageId}),n.delta&&t.push({type:"TOOL_CALL_ARGS",toolCallId:e,delta:n.delta}),n.toolCallName&&n.delta&&t.push({type:"TOOL_CALL_END",toolCallId:e,parentMessageId:n.parentMessageId}),t.length>0?t:[n]}default:return [n]}}var b=class extends BaseCallbackHandler{name="ag-ui-callback";messageIds=new Map;latestMessageIds=new Map;agentRunIds=new Map;parentToAuthoritativeId=new Map;thinkingIds=new Map;toolCallInfo=new Map;toolCallNames=new Map;agentTurnTracker=new Map;pendingToolCalls=new Map;accumulatedToolArgs=new Map;transport;maxUIPayloadSize;chunkLargeResults;constructor(e,t){super({raiseError:false}),this.transport=e,this.maxUIPayloadSize=t?.maxUIPayloadSize??50*1024,this.chunkLargeResults=t?.chunkLargeResults??false;}dispose(){this.messageIds.clear(),this.latestMessageIds.clear(),this.agentRunIds.clear(),this.parentToAuthoritativeId.clear(),this.thinkingIds.clear(),this.toolCallInfo.clear(),this.toolCallNames.clear(),this.agentTurnTracker.clear(),this.pendingToolCalls.clear(),this.accumulatedToolArgs.clear();}async emitTextChunk(e,t="assistant",s){let r=S({type:"TEXT_MESSAGE_CHUNK",messageId:e,role:t,delta:s});for(let o of r)await this.transport.emit(o);}async emitToolChunk(e,t,s,r){let o=S({type:"TOOL_CALL_CHUNK",toolCallId:e,toolCallName:t,delta:s,parentMessageId:r});for(let c of o)await this.transport.emit(c);}async handleLLMStart(e,t,s,r,o,c,p,d){let l=p?.agui_runId||p?.run_id||p?.configurable?.run_id||r||s;this.agentRunIds.set(s,l),r&&this.parentToAuthoritativeId.set(r,l);let g=p?.agui_messageId;if(g)this.messageIds.set(s,g),this.latestMessageIds.set(l,g),this.transport.emit({type:"TEXT_MESSAGE_START",messageId:g,role:"assistant",timestamp:Date.now()});else {let i=this.agentTurnTracker.get(l)||0;this.agentTurnTracker.set(l,i+1);let a=E(l,i);this.messageIds.set(s,a),this.latestMessageIds.set(l,a),this.transport.emit({type:"TEXT_MESSAGE_START",messageId:a,role:"assistant",timestamp:Date.now()});}}async handleLLMNewToken(e,t,s,r,o,c){let p=this.messageIds.get(s);if(p)try{let d=c?.chunk?.message?.additional_kwargs?.reasoning_content||c?.chunk?.message?.additional_kwargs?.reasoning;if(d){let g=this.thinkingIds.get(s);if(!g){let a=this.agentRunIds.get(s)||(r?this.parentToAuthoritativeId.get(r):null)||r||s;g=E(a,(this.agentTurnTracker.get(a)||1)+100),this.thinkingIds.set(s,g),this.transport.emit({type:"THINKING_START",timestamp:Date.now()}),this.transport.emit({type:"THINKING_TEXT_MESSAGE_START",messageId:g,timestamp:Date.now()});}let i=typeof d=="string"?d:d.text||JSON.stringify(d);this.transport.emit({type:"THINKING_TEXT_MESSAGE_CONTENT",messageId:g,delta:i,timestamp:Date.now()});}e&&e.length>0&&this.transport.emit({type:"TEXT_MESSAGE_CONTENT",messageId:p,delta:e,timestamp:Date.now()});let l=c?.chunk?.message?.tool_call_chunks;if(l&&Array.isArray(l)){let g=this.agentRunIds.get(s)||(r?this.parentToAuthoritativeId.get(r):null)||r||s,i=this.pendingToolCalls.get(g)||[];for(let a of l)if(a.id&&a.args){let m=this.accumulatedToolArgs.get(a.id)||"",f=m+a.args;f!==m&&this.accumulatedToolArgs.set(a.id,f),i.includes(a.id)||i.push(a.id);}i.length>0&&this.pendingToolCalls.set(g,i);}}catch{}}async handleLLMEnd(e,t,s,r,o){let c=this.messageIds.get(t),p=this.thinkingIds.get(t);try{if(e&&typeof e=="object"){let d=e.tool_calls||e.kwargs?.tool_calls;if(Array.isArray(d)){let l=this.agentRunIds.get(t)||(s?this.parentToAuthoritativeId.get(s):null)||s||t,g=this.pendingToolCalls.get(l)||[];for(let i of d)i.id&&!g.includes(i.id)&&(g.push(i.id),i.function?.name&&this.toolCallNames.set(i.id,i.function.name),i.function?.arguments&&this.accumulatedToolArgs.set(i.id,i.function.arguments));this.pendingToolCalls.set(l,g);}}c&&this.transport.emit({type:"TEXT_MESSAGE_END",messageId:c,timestamp:Date.now()}),p&&(this.transport.emit({type:"THINKING_TEXT_MESSAGE_END",messageId:p,timestamp:Date.now()}),this.transport.emit({type:"THINKING_END",timestamp:Date.now()}),this.thinkingIds.delete(t)),this.messageIds.delete(t);}catch{}}async handleLLMError(e,t,s){this.messageIds.delete(t),this.thinkingIds.delete(t);let r=this.agentRunIds.get(t)||(s?this.parentToAuthoritativeId.get(s):null)||s||t;this.pendingToolCalls.delete(r),this.agentRunIds.delete(t);}async handleToolStart(e,t,s,r,o,c,p){let d=s,l=p||e.kwargs?.name||e.name||e.func?.name||e.getName?.()||e.toolName||e._name||"unknown_tool";try{if(c?.tool_call_id&&typeof c.tool_call_id=="string"){d=c.tool_call_id;let a=this.toolCallNames.get(d);a&&a!=="unknown_tool"&&(l=a);}else if(t)try{let a=typeof t=="string"?JSON.parse(t):t;a&&typeof a=="object"&&(a.tool_call_id?d=a.tool_call_id:a.id&&(d=a.id),a.name&&(l=a.name));}catch{}if(d===s&&this.accumulatedToolArgs.size>0&&t){for(let[a,m]of this.accumulatedToolArgs)if(t.includes(m)||m.includes(t)){d=a;let f=this.toolCallNames.get(a);f&&f!=="unknown_tool"&&(l=f);break}}}catch{}try{if(c?.tool_call_id&&typeof c.tool_call_id=="string")d=c.tool_call_id;else if(t)try{let a=typeof t=="string"?JSON.parse(t):t;a&&typeof a=="object"&&(a.tool_call_id?d=a.tool_call_id:a.id&&(d=a.id),a.name&&(l=a.name));}catch{}if(d===s&&this.accumulatedToolArgs.size>0&&t){for(let[a,m]of this.accumulatedToolArgs)if(t.includes(m)||m.includes(t)){d=a;break}}}catch{}this.toolCallInfo.set(s,{id:d,name:l});let g=(r?this.parentToAuthoritativeId.get(r):null)||r||"",i=this.latestMessageIds.get(g);try{this.transport.emit({type:"TOOL_CALL_START",toolCallId:d,toolCallName:l,parentMessageId:i,timestamp:Date.now()});let a=this.accumulatedToolArgs.get(d);a&&(this.transport.emit({type:"TOOL_CALL_ARGS",toolCallId:d,delta:a,timestamp:Date.now()}),this.accumulatedToolArgs.delete(d));}catch{}}async handleToolEnd(e,t,s){let r=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),r?.id&&this.toolCallNames.delete(r.id);let o=(s?this.parentToAuthoritativeId.get(s):null)||s||"",c=this.latestMessageIds.get(o);try{let d=r?.id??t;if(e&&typeof e=="object"){let l=e.kwargs||e.lc_kwargs;l?.tool_call_id&&(d=l.tool_call_id);}this.transport.emit({type:"TOOL_CALL_END",toolCallId:d,timestamp:Date.now()}),this.emitToolResultWithPolicy(e,d,c,r?.name);}catch{}}async handleToolError(e,t,s){let r=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),r?.id&&this.accumulatedToolArgs.delete(r.id);let o=(s?this.parentToAuthoritativeId.get(s):null)||s||"";this.latestMessageIds.get(o);try{this.transport.emit({type:"TOOL_CALL_END",toolCallId:r?.id??t,timestamp:Date.now()});}catch{}}chunkString(e,t){let s=[],r=e;for(;r.length>0;){if(new Blob([r]).size<=t){s.push(r);break}let o=t,c=r.lastIndexOf(" ",t),p=r.lastIndexOf(`
|
|
2
|
+
`,t),d=Math.max(c,p);if(d>t*.5)o=d;else {for(;o>0&&r.charCodeAt(o-1)>127;)o--;o===0&&(o=t);}s.push(r.substring(0,o)),r=r.substring(o).trim();}return s}emitToolResultWithPolicy(e,t,s,r){let o=_(e),c=T(),p=new Blob([o]).size;if(p<=this.maxUIPayloadSize){this.transport.emit({type:"TOOL_CALL_RESULT",messageId:c,toolCallId:t,content:o,role:"tool",timestamp:Date.now()});return}if(this.chunkLargeResults){let i=this.chunkString(o,this.maxUIPayloadSize);for(let a=0;a<i.length;a++)this.transport.emit({type:"CUSTOM",name:"LARGE_RESULT_CHUNK",value:{toolCallId:t,chunk:i[a],index:a,total:i.length}});return}let d=` [Truncated: ${p-this.maxUIPayloadSize+50} bytes]`,l=this.maxUIPayloadSize-d.length,g=o.substring(0,Math.max(0,l))+d;this.transport.emit({type:"TOOL_CALL_RESULT",messageId:c,toolCallId:t,content:g,role:"tool",timestamp:Date.now()});}};function W(n){let e=x({transport:n.transport,emitToolResults:n.middlewareOptions?.emitToolResults??true,emitStateSnapshots:n.middlewareOptions?.emitStateSnapshots??"initial",emitActivities:n.middlewareOptions?.emitActivities??false,maxUIPayloadSize:n.middlewareOptions?.maxUIPayloadSize??51200,chunkLargeResults:n.middlewareOptions?.chunkLargeResults??false,threadIdOverride:n.middlewareOptions?.threadIdOverride,runIdOverride:n.middlewareOptions?.runIdOverride,errorDetailLevel:n.middlewareOptions?.errorDetailLevel??"message",stateMapper:n.middlewareOptions?.stateMapper,resultMapper:n.middlewareOptions?.resultMapper,activityMapper:n.middlewareOptions?.activityMapper,validateEvents:n.middlewareOptions?.validateEvents??false}),t=createAgent({model:n.model,tools:n.tools,middleware:[e]});return t&&typeof t.withListeners=="function"?t.withListeners({onError:s=>{try{let r=s.config?.configurable?.threadId,o=s.config?.configurable?.runId;n.transport.emit({type:"RUN_ERROR",message:typeof s.error=="string"?s.error:s.error?.message||"Agent execution failed",code:"AGENT_EXECUTION_ERROR",timestamp:Date.now()});}catch{}}}):t}function q(n,e){e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.setHeader("X-Accel-Buffering","no");let t=new AbortController;n.on("close",()=>t.abort());let s=[],r=false;async function o(){for(r=true;s.length>0&&e.write;){let c=s.shift();try{e.write(`data: ${JSON.stringify(c)}
|
|
3
|
+
|
|
4
|
+
`);}catch{break}}r=false;}return {emit:c=>{s.push(c),r||o();},signal:t.signal,disconnect:e.end?()=>{e.end?.();}:void 0,isConnected:()=>!t.signal.aborted}}function O(n){let e=Z(n),t=encode(e),s=new DataView(new ArrayBuffer(4));s.setUint32(0,t.length,false);let r=new Uint8Array(4+t.length);return r.set(new Uint8Array(s.buffer),0),r.set(t,4),r}function N(n){if(n.length<4)throw new Error("Invalid protobuf frame: insufficient data for length prefix");let e=new DataView(n.buffer,n.byteOffset).getUint32(0,false);if(n.length<4+e)throw new Error("Invalid protobuf frame: insufficient data for payload");let t=n.slice(4,4+e),s=decode(t);return ee(s)}function Z(n){let e={...n};return n.type==="MESSAGES_SNAPSHOT"&&n.messages&&(e.messages=n.messages.map(t=>({...t,toolCalls:t.tool_calls?.map(s=>({id:s.id,type:s.type,function:s.function})),tool_calls:void 0,toolCallId:t.tool_call_id,tool_call_id:void 0}))),e}function ee(n){let e={...n};return n.type==="MESSAGES_SNAPSHOT"&&n.messages&&(e.messages=n.messages.map(t=>({...t,tool_calls:t.toolCalls?.map(s=>({id:s.id,type:s.type,function:s.function})),toolCalls:void 0,tool_call_id:t.toolCallId,toolCallId:void 0}))),e}function te(n,e){e.setHeader("Content-Type",AGUI_MEDIA_TYPE),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),e.setHeader("X-Accel-Buffering","no");let t=new AbortController;n.on("close",()=>t.abort());let s=[],r=false;async function o(){for(r=true;s.length>0&&e.write;){let c=s.shift();try{let p=O(c);e.write(p);}catch{break}}r=false;}return {emit:c=>{s.push(c),r||o();},signal:t.signal,disconnect:e.end?()=>{e.end?.();}:void 0,isConnected:()=>!t.signal.aborted,encodeEvent:O,decodeEvent:N}}export{b as AGUICallbackHandler,C as AGUIMiddlewareOptionsSchema,y as cleanLangChainData,A as computeStateDelta,W as createAGUIAgent,x as createAGUIMiddleware,te as createProtobufTransport,q as createSSETransport,w as createValidatingTransport,N as decodeEventWithFraming,O as encodeEventWithFraming,S as expandEvent,_ as extractToolOutput,T as generateId,K as isValidEvent,I as mapLangChainMessageToAGUI,M as validateEvent};//# sourceMappingURL=index.js.map
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/idGenerator.ts","../src/utils/stateDiff.ts","../src/utils/messageMapper.ts","../src/utils/cleaner.ts","../src/middleware/types.ts","../src/utils/validation.ts","../src/middleware/createAGUIMiddleware.ts","../src/utils/eventNormalizer.ts","../src/callbacks/AGUICallbackHandler.ts","../src/createAGUIAgent.ts","../src/transports/createSSETransport.ts","../src/transports/createProtobufTransport.ts"],"names":["generateId","generateDeterministicId","baseId","index","str","hash","i","char","hex","computeStateDelta","oldState","newState","compare","mapLangChainMessageToAGUI","message","id","role","toolCalls","toolCallId","content","HumanMessage","AIMessage","toolCallsFromLLM","tc","ToolMessage","SystemMessage","ChatMessage","cleanLangChainData","data","kwargs","result","key","value","extractToolOutput","output","parsed","AGUIMiddlewareOptionsSchema","z","val","validateEvent","event","EventSchemas","issue","err","isValidEvent","createValidatingTransport","transport","options","throwOnInvalid","onValidationError","isValidationEnabled","validateEvents","getInputPreview","state","stateAny","lastMessage","getOutputType","hasToolCalls","m","emitActivityUpdate","currentRunId","stepIndex","activityTracker","status","activityMapper","details","activityId","baseContent","finalContent","patch","createAGUIMiddleware","validated","threadId","runId","currentStepName","modelTurnIndex","createMiddleware","runtime","runtimeAny","configurable","snapshot","configAny","turnIndex","messageId","stepName","_runtime","filteredState","k","error","errorMessage","expandEvent","results","AGUICallbackHandler","BaseCallbackHandler","delta","events","toolCallName","parentMessageId","_llm","_prompts","_parentRunId","_extraParams","_tags","_metadata","_runName","agentRunId","middlewareMessageId","token","_idx","fields","reasoningContent","thinkingId","toolCallChunks","pending","chunk","previousArgs","newArgs","_output","_error","tool","input","parentRunId","metadata","runName","storedName","args","accumulatedArgs","toolInfo","finalToolCallId","maxChunkSize","chunks","remaining","splitPoint","spaceIndex","newlineIndex","boundaryIndex","resultMessageId","contentSize","truncationMessage","availableSpace","truncatedContent","createAGUIAgent","config","middleware","agent","createAgent","run","createSSETransport","req","res","controller","queue","draining","drain","encodeEventWithFraming","coreEvent","convertToProtobufEvent","eventBytes","encode","lengthPrefix","decodeEventWithFraming","length","decoded","decode","convertFromProtobufEvent","baseEvent","msg","createProtobufTransport","AGUI_MEDIA_TYPE","framedData"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ID Generator Utility\n * \n * Generates unique IDs using crypto.randomUUID() or deterministic hashing.\n */\n\n/**\n * Generate a unique ID using crypto.randomUUID()\n * \n * @returns A UUID v4 string (e.g., \"550e8400-e29b-41d4-a716-446655440000\")\n */\nexport function generateId(): string {\n return crypto.randomUUID();\n}\n\n/**\n * Generate a deterministic ID from a base ID and an index.\n * Useful for coordinating between Middleware and Callbacks without direct communication.\n * \n * @param baseId - The base ID (e.g., runId)\n * @param index - The turn index\n * @returns A deterministic hyphenated string [prefix]-[hash]\n */\nexport function generateDeterministicId(baseId: string, index: number): string {\n if (!baseId) {\n throw new Error(\"baseId is required for deterministic ID generation\");\n }\n\n const str = `${baseId}-${index}`;\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n \n // Return a stable hex string\n const hex = Math.abs(hash).toString(16).padStart(8, '0');\n \n // Use the baseId as the prefix to ensure uniqueness across different runs.\n // We keep the full baseId to avoid any ambiguity or collision risk.\n return `${baseId}-${hex}`;\n}\n","/**\n * State Diff Utility\n * \n * Computes JSON Patch deltas between two state objects.\n * Uses fast-json-patch's compare function to generate RFC 6902 patch operations.\n */\n\nimport { compare, type Operation } from \"fast-json-patch\";\n\n/**\n * Compute the delta between two state objects using JSON Patch (RFC 6902).\n * \n * @param oldState - The previous state object\n * @param newState - The updated state object\n * @returns An array of JSON Patch operations describing the changes\n */\nexport function computeStateDelta(\n oldState: unknown,\n newState: unknown\n): Operation[] {\n return compare(oldState as any, newState as any);\n}\n","import { \n BaseMessage, \n HumanMessage, \n AIMessage, \n ToolMessage, \n SystemMessage,\n ChatMessage\n} from \"@langchain/core/messages\";\nimport { generateId } from \"./idGenerator\";\nimport type { Message, ToolCall } from \"../events\";\n\n/**\n * Maps a LangChain BaseMessage to an AG-UI Protocol Message.\n * \n * @param message - The LangChain message to map\n * @returns An AG-UI Protocol compliant Message object\n */\nexport function mapLangChainMessageToAGUI(message: BaseMessage): Message {\n const id = (message as any).id || generateId();\n let role: Message[\"role\"] = \"assistant\";\n let toolCalls: ToolCall[] | undefined;\n let toolCallId: string | undefined;\n let content = typeof message.content === \"string\" ? message.content : JSON.stringify(message.content);\n\n if (message instanceof HumanMessage || (message as any).role === \"user\" || (message as any)._getType?.() === \"human\") {\n role = \"user\";\n } else if (message instanceof AIMessage || (message as any).role === \"assistant\" || (message as any)._getType?.() === \"ai\") {\n role = \"assistant\";\n const toolCallsFromLLM = (message as any).tool_calls || (message as any).kwargs?.tool_calls;\n if (toolCallsFromLLM && toolCallsFromLLM.length > 0) {\n toolCalls = toolCallsFromLLM.map((tc: any) => ({\n id: tc.id!,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: typeof tc.args === \"string\" ? tc.args : JSON.stringify(tc.args)\n }\n }));\n }\n } else if (message instanceof ToolMessage || (message as any).role === \"tool\" || (message as any)._getType?.() === \"tool\") {\n role = \"tool\";\n toolCallId = (message as any).tool_call_id || (message as any).kwargs?.tool_call_id;\n } else if (message instanceof SystemMessage || (message as any).role === \"system\" || (message as any)._getType?.() === \"system\") {\n role = \"system\";\n } else if (message instanceof ChatMessage) {\n role = message.role as any;\n } else if ((message as any).role) {\n role = (message as any).role;\n }\n\n return {\n id,\n role,\n content,\n toolCalls,\n toolCallId,\n name: (message as any).name\n };\n}\n","/**\n * Utility to clean up LangChain serialized objects from state/output.\n */\n\n/**\n * Recursively removes 'lc', 'type', 'id' (LangChain internal) fields and \n * flattens 'kwargs' if present.\n */\nexport function cleanLangChainData(data: any): any {\n if (data === null || data === undefined) {\n return data;\n }\n\n if (Array.isArray(data)) {\n return data.map(cleanLangChainData);\n }\n\n if (typeof data === \"object\") {\n // Check if it's a LangChain serialized object\n if ((data.lc === 1 || data.lc_serializable === true) && (data.kwargs || data.lc_kwargs)) {\n const kwargs = data.kwargs || data.lc_kwargs;\n const cleaned = cleanLangChainData(kwargs);\n return cleaned;\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(data)) {\n // Skip internal metadata often found in LangChain objects\n if (key === \"lc\" || key === \"type\" || key === \"id\" || key.startsWith(\"lc_\")) {\n continue;\n }\n result[key] = cleanLangChainData(value);\n }\n return result;\n }\n\n return data;\n}\n\n/**\n * Extracts content from a tool output if it's a serialized ToolMessage or object.\n */\nexport function extractToolOutput(output: any): string {\n if (output === null || output === undefined) {\n return \"\";\n }\n\n // If it's already a string, try to parse it (it might be a JSON-encoded LangChain message)\n let parsed = output;\n if (typeof output === \"string\") {\n try {\n parsed = JSON.parse(output);\n } catch {\n return output;\n }\n }\n\n // Now 'parsed' is either an object or the original output if it wasn't valid JSON\n\n if (typeof parsed !== \"object\") {\n return String(parsed);\n }\n\n // Handle LangChain message structures (lc: 1 or lc_serializable: true)\n const isLangChainMessage = parsed.lc === 1 || parsed.lc_serializable === true || (parsed.type === \"constructor\" && Array.isArray(parsed.id));\n const kwargs = parsed.kwargs || parsed.lc_kwargs || parsed;\n\n if (kwargs && kwargs.content !== undefined) {\n return typeof kwargs.content === \"string\" \n ? kwargs.content \n : JSON.stringify(kwargs.content);\n }\n\n // If it's a plain object but has a 'result' or 'output' field\n if (parsed.result !== undefined) return typeof parsed.result === \"string\" ? parsed.result : JSON.stringify(parsed.result);\n if (parsed.output !== undefined) return typeof parsed.output === \"string\" ? parsed.output : JSON.stringify(parsed.output);\n\n // If no specific field found, return stringified version of the object (but cleaned)\n return JSON.stringify(cleanLangChainData(parsed));\n}\n","/**\n * AG-UI Middleware Types and Configuration\n * \n * Defines the middleware options schema and types for AG-UI protocol integration.\n */\n\nimport { z } from \"zod\";\nimport type { AGUITransport } from \"../transports/types\";\n\n/**\n * Middleware options schema with Zod validation.\n */\nexport const AGUIMiddlewareOptionsSchema = z.object({\n // Transport (required)\n transport: z.custom<AGUITransport>(\n (val) => val && typeof (val as AGUITransport).emit === \"function\",\n {\n message: \"Transport must have an emit function\",\n }\n ),\n\n // Event control\n emitToolResults: z.boolean().default(true),\n emitStateSnapshots: z.enum([\"initial\", \"final\", \"all\", \"none\"]).default(\"initial\"),\n emitActivities: z.boolean().default(false),\n\n // Smart Emission Policy\n maxUIPayloadSize: z.number().positive().default(50 * 1024), // 50KB\n chunkLargeResults: z.boolean().default(false),\n\n // Session Override\n threadIdOverride: z.string().optional(),\n runIdOverride: z.string().optional(),\n\n // Error Handling\n errorDetailLevel: z.enum([\"full\", \"message\", \"code\", \"none\"]).default(\"message\"),\n\n // Data Mappers (New in Protocol Compliance)\n stateMapper: z.custom<(state: any) => any>().optional(),\n resultMapper: z.custom<(result: any) => any>().optional(),\n activityMapper: z.custom<(node: any) => any>().optional(),\n \n // Validation (New - @ag-ui/core integration)\n /**\n * Enable runtime validation of events against @ag-ui/core schemas.\n * Disabled by default for performance. Enable in development for debugging.\n * \n * - false (default): No validation, events emitted as-is\n * - true: Validate events, log warnings for invalid events\n * - \"strict\": Validate events, throw on invalid events\n */\n validateEvents: z.union([\n z.boolean(),\n z.literal(\"strict\"),\n ]).default(false),\n});\n\n/**\n * Inferred type for middleware options.\n */\nexport type AGUIMiddlewareOptions = z.infer<typeof AGUIMiddlewareOptionsSchema>;\n","/**\n * AG-UI Event Validation Utilities\n * \n * Provides optional runtime validation of AG-UI events using @ag-ui/core Zod schemas.\n * Validation is disabled by default for performance; enable in development for debugging.\n * \n * @example\n * ```typescript\n * import { validateEvent, isValidEvent } from './utils/validation';\n * \n * // Safe validation (returns result object)\n * const result = validateEvent(event);\n * if (result.success) {\n * console.log('Valid event:', result.data);\n * } else {\n * console.error('Invalid event:', result.error);\n * }\n * \n * // Boolean check\n * if (isValidEvent(event)) {\n * // event is valid\n * }\n * ```\n */\n\nimport { EventSchemas } from '@ag-ui/core';\nimport type { AGUIEvent } from '../events';\n\n/**\n * Result of event validation.\n */\nexport interface ValidationResult<T = AGUIEvent> {\n success: boolean;\n data?: T;\n error?: {\n message: string;\n issues: Array<{\n path: (string | number)[];\n message: string;\n }>;\n };\n}\n\n/**\n * Validate an AG-UI event against @ag-ui/core schemas.\n * \n * Events are now emitted with camelCase field names (toolCalls, toolCallId)\n * which matches the @ag-ui/core schema directly.\n * \n * @param event - The event to validate\n * @returns ValidationResult with success status and any errors\n */\nexport function validateEvent(event: unknown): ValidationResult {\n try {\n const result = EventSchemas.safeParse(event);\n \n if (result.success) {\n return {\n success: true,\n data: event as AGUIEvent,\n };\n }\n \n return {\n success: false,\n error: {\n message: 'Event validation failed',\n issues: result.error.issues.map(issue => ({\n path: issue.path,\n message: issue.message,\n })),\n },\n };\n } catch (err) {\n return {\n success: false,\n error: {\n message: err instanceof Error ? err.message : 'Unknown validation error',\n issues: [],\n },\n };\n }\n}\n\n/**\n * Check if an event is valid according to @ag-ui/core schemas.\n * \n * @param event - The event to check\n * @returns true if valid, false otherwise\n */\nexport function isValidEvent(event: unknown): event is AGUIEvent {\n return validateEvent(event).success;\n}\n\n/**\n * Create a validating transport wrapper.\n * Wraps any AGUITransport to add validation before emission.\n * \n * @param transport - The transport to wrap\n * @param options - Validation options\n * @returns Wrapped transport with validation\n */\nexport function createValidatingTransport<T extends { emit: (event: AGUIEvent) => void }>(\n transport: T,\n options: {\n /** Throw on invalid events (default: false - just log warning) */\n throwOnInvalid?: boolean;\n /** Custom logger for validation errors */\n onValidationError?: (event: AGUIEvent, error: ValidationResult['error']) => void;\n } = {}\n): T {\n const { throwOnInvalid = false, onValidationError } = options;\n \n return {\n ...transport,\n emit: (event: AGUIEvent) => {\n const result = validateEvent(event);\n \n if (!result.success) {\n if (onValidationError) {\n onValidationError(event, result.error);\n } else {\n console.warn('[AG-UI Validation] Invalid event:', event.type, result.error);\n }\n \n if (throwOnInvalid) {\n throw new Error(`Invalid AG-UI event: ${result.error?.message}`);\n }\n }\n \n // Always emit (validation is advisory)\n transport.emit(event);\n },\n };\n}\n","/**\n * AG-UI Middleware Factory\n *\n * Creates middleware that integrates LangChain agents with the AG-UI protocol.\n */\n\nimport { createMiddleware } from \"langchain\";\nimport { z } from \"zod\";\nimport { generateDeterministicId } from \"../utils/idGenerator\";\nimport { computeStateDelta } from \"../utils/stateDiff\";\nimport { mapLangChainMessageToAGUI } from \"../utils/messageMapper\";\nimport { cleanLangChainData } from \"../utils/cleaner\";\nimport {\n AGUIMiddlewareOptionsSchema,\n type AGUIMiddlewareOptions,\n} from \"./types\";\nimport { createValidatingTransport } from \"../utils/validation\";\n\n/**\n * Check if validateEvents mode is truthy (true or \"strict\").\n */\nfunction isValidationEnabled(validateEvents: AGUIMiddlewareOptions['validateEvents']): boolean {\n return validateEvents === true || validateEvents === \"strict\";\n}\n\n/**\n * Interface for tracking agent execution activities.\n */\ninterface ActivityTracker {\n currentActivityId: string | undefined;\n currentActivityType: string;\n activityContent: Record<string, any>;\n}\n\n/**\n * Helper function to get a preview of the input for activity content.\n */\nfunction getInputPreview(state: unknown): string {\n const stateAny = state as any;\n if (stateAny.messages && Array.isArray(stateAny.messages)) {\n const lastMessage = stateAny.messages[stateAny.messages.length - 1];\n if (lastMessage && typeof lastMessage.content === \"string\") {\n return lastMessage.content.substring(0, 100) + (lastMessage.content.length > 100 ? \"...\" : \"\");\n }\n }\n return \"[no input preview]\";\n}\n\n/**\n * Helper function to get the type of output from state.\n */\nfunction getOutputType(state: unknown): string {\n const stateAny = state as any;\n if (stateAny.messages && Array.isArray(stateAny.messages)) {\n const lastMessage = stateAny.messages[stateAny.messages.length - 1];\n if (lastMessage?.toolCalls?.length) return \"tool_calls\";\n if (lastMessage?.content) return \"text\";\n }\n return \"unknown\";\n}\n\n/**\n * Helper function to check if state contains tool calls.\n */\nfunction hasToolCalls(state: unknown): boolean {\n const stateAny = state as any;\n return !!(stateAny.messages && stateAny.messages.some((m: any) => m.toolCalls?.length > 0));\n}\n\n/**\n * Emit ACTIVITY_SNAPSHOT or ACTIVITY_DELTA based on current state.\n * ACTIVITY_SNAPSHOT = new activity or significant change\n * ACTIVITY_DELTA = incremental update\n */\nasync function emitActivityUpdate(\n transport: any,\n currentRunId: string | undefined,\n stepIndex: number,\n activityTracker: ActivityTracker,\n status: \"started\" | \"processing\" | \"completed\",\n activityMapper: ((node: any) => any) | undefined,\n details?: Record<string, any>\n): Promise<void> {\n if (!currentRunId) return;\n\n const activityId = `activity-${currentRunId}-${stepIndex}`;\n const baseContent = {\n status,\n timestamp: Date.now(),\n ...details,\n };\n\n // Apply activityMapper if provided\n const finalContent = activityMapper ? activityMapper(baseContent) : baseContent;\n\n if (!activityTracker.currentActivityId || activityTracker.currentActivityId !== activityId) {\n // New activity - emit SNAPSHOT\n activityTracker.currentActivityId = activityId;\n activityTracker.currentActivityType = \"AGENT_STEP\";\n activityTracker.activityContent = finalContent;\n\n transport.emit({\n type: \"ACTIVITY_SNAPSHOT\",\n messageId: activityId,\n activityType: \"AGENT_STEP\",\n content: finalContent,\n replace: true,\n });\n } else {\n // Existing activity - emit DELTA\n const patch = computeStateDelta(activityTracker.activityContent, finalContent);\n if (patch.length > 0) {\n activityTracker.activityContent = finalContent;\n\n transport.emit({\n type: \"ACTIVITY_DELTA\",\n messageId: activityId,\n activityType: \"AGENT_STEP\",\n patch,\n });\n }\n }\n}\n\n/**\n * Create AG-UI middleware for LangChain agents.\n *\n * @param options - Middleware configuration options\n * @returns AgentMiddleware instance with lifecycle hooks\n */\nexport function createAGUIMiddleware(options: AGUIMiddlewareOptions) {\n // Validate options at creation time\n const validated = AGUIMiddlewareOptionsSchema.parse(options);\n \n // Wrap transport with validation if enabled\n // In \"strict\" mode, throw on invalid events; in true mode, log warnings\n let transport = validated.transport;\n if (isValidationEnabled(validated.validateEvents)) {\n transport = createValidatingTransport(validated.transport, {\n throwOnInvalid: validated.validateEvents === \"strict\",\n });\n }\n \n let threadId: string | undefined;\n let runId: string | undefined;\n let currentStepName: string | undefined = undefined;\n let modelTurnIndex = 0;\n\n const activityTracker: ActivityTracker = {\n currentActivityId: undefined,\n currentActivityType: \"AGENT_STEP\",\n activityContent: {},\n };\n\n const activityStates = new Map<string, any>();\n\n return createMiddleware({\n name: \"ag-ui-lifecycle\",\n contextSchema: z.object({\n run_id: z.string().optional(),\n runId: z.string().optional(),\n thread_id: z.string().optional(),\n threadId: z.string().optional(),\n }) as any,\n\n beforeAgent: async (state, runtime) => {\n modelTurnIndex = 0;\n const runtimeAny = runtime as any;\n const configurable = runtimeAny.config?.configurable || runtimeAny.configurable;\n \n threadId =\n (configurable?.threadId as string | undefined) ||\n (configurable?.thread_id as string | undefined) ||\n (configurable?.checkpoint_id as string | undefined) ||\n validated.threadIdOverride ||\n (runtimeAny.context?.threadId as string | undefined) ||\n (runtimeAny.context?.thread_id as string | undefined) ||\n \"\";\n\n // Exhaustive search for Run ID - generate fallback if not found\n runId =\n validated.runIdOverride ||\n (configurable?.run_id as string | undefined) ||\n (runtimeAny.runId as string | undefined) ||\n (runtimeAny.id as string | undefined) ||\n (runtimeAny.context?.runId as string | undefined) ||\n (runtimeAny.context?.run_id as string | undefined) ||\n (runtimeAny.config?.runId as string | undefined) ||\n crypto.randomUUID(); // Generate fallback for streamEvents compatibility\n\n try {\n transport.emit({\n type: \"RUN_STARTED\",\n threadId,\n runId,\n input: cleanLangChainData(runtimeAny.config?.input),\n timestamp: Date.now(),\n });\n\n if (\n validated.emitStateSnapshots === \"initial\" ||\n validated.emitStateSnapshots === \"all\"\n ) {\n const snapshot = validated.stateMapper \n ? validated.stateMapper(state) \n : cleanLangChainData(state);\n \n // Remove messages from state snapshot by default to avoid redundancy\n if (!validated.stateMapper && snapshot && typeof snapshot === \"object\") {\n delete (snapshot as any).messages;\n }\n\n transport.emit({\n type: \"STATE_SNAPSHOT\",\n snapshot,\n timestamp: Date.now(),\n });\n }\n \n const stateAny = state as any;\n if (stateAny.messages && Array.isArray(stateAny.messages)) {\n transport.emit({\n type: \"MESSAGES_SNAPSHOT\",\n messages: stateAny.messages.map(mapLangChainMessageToAGUI),\n timestamp: Date.now(),\n });\n }\n } catch {\n // Fail-safe\n }\n\n // Store runId in metadata for callback coordination\n // This allows callbacks to use the same runId as middleware\n const configAny = runtimeAny.config as any;\n if (configAny) {\n configAny.metadata = {\n ...(configAny.metadata || {}),\n agui_runId: runId,\n };\n }\n\n return {};\n },\n\n beforeModel: async (state, runtime) => {\n const turnIndex = modelTurnIndex++;\n const messageId = generateDeterministicId(runId!, turnIndex);\n const stepName = `model_call_${messageId}`;\n currentStepName = stepName;\n\n // Store messageId in metadata for callback coordination\n // This ensures callbacks use the same messageId as middleware\n const runtimeAny = runtime as any;\n const configAny = runtimeAny.config as any;\n if (configAny) {\n configAny.metadata = {\n ...(configAny.metadata || {}),\n agui_messageId: messageId,\n };\n }\n\n try {\n transport.emit({\n type: \"STEP_STARTED\",\n stepName,\n timestamp: Date.now(),\n // REMOVED: runId, threadId\n });\n\n // Emit ACTIVITY_SNAPSHOT for new activity if activities are enabled\n if (validated.emitActivities) {\n await emitActivityUpdate(\n transport,\n runId,\n turnIndex,\n activityTracker,\n \"started\",\n validated.activityMapper,\n {\n stepName,\n modelName: (runtime as any).config?.model?._modelType || \"unknown\",\n inputPreview: getInputPreview(state),\n } as Record<string, any>\n );\n }\n\n // TEXT_MESSAGE_START is handled by AGUICallbackHandler\n // It reads messageId from metadata in handleLLMStart\n } catch {\n // Fail-safe\n }\n\n return {};\n },\n\n afterModel: async (state, _runtime) => {\n try {\n // TEXT_MESSAGE_END is handled by AGUICallbackHandler\n // It uses the same messageId from metadata coordination\n\n transport.emit({\n type: \"STEP_FINISHED\",\n stepName: currentStepName || \"\",\n timestamp: Date.now(),\n // REMOVED: runId, threadId\n });\n\n // Emit ACTIVITY_DELTA for completed activity if activities are enabled\n if (validated.emitActivities && currentStepName) {\n const turnIndex = modelTurnIndex - 1;\n await emitActivityUpdate(\n transport,\n runId,\n turnIndex,\n activityTracker,\n \"completed\",\n validated.activityMapper,\n {\n stepName: currentStepName,\n outputType: getOutputType(state),\n hasToolCalls: hasToolCalls(state),\n } as Record<string, any>\n );\n }\n\n // Emit STATE_SNAPSHOT after state-stabilizing events (not during streaming)\n // Per AG-UI spec and LangGraph implementation: emit only when streaming has completed\n // and state is stable. STATE_DELTA is NOT used in actual LangGraph implementations.\n if (validated.emitStateSnapshots !== \"none\") {\n // Only emit STATE_SNAPSHOT after streaming completes (state-stabilizing event)\n // This follows the LangGraph pattern: emit after tool/text streaming ends\n const filteredState = cleanLangChainData(state);\n const snapshot = validated.stateMapper \n ? validated.stateMapper(filteredState) \n : filteredState;\n \n // Remove messages from state snapshot (messages are in MESSAGES_SNAPSHOT)\n if (!validated.stateMapper && snapshot && typeof snapshot === \"object\") {\n delete (snapshot as any).messages;\n }\n \n // Only emit if we have meaningful state to share\n const stateKeys = snapshot ? Object.keys(snapshot).filter(k => snapshot[k] !== undefined && snapshot[k] !== null) : [];\n if (stateKeys.length > 0) {\n transport.emit({\n type: \"STATE_SNAPSHOT\",\n snapshot,\n timestamp: Date.now(),\n });\n }\n }\n } catch {\n // Fail-safe\n }\n\n currentStepName = undefined;\n return {};\n },\n\n afterAgent: async (state, _runtime) => {\n try {\n if (\n validated.emitStateSnapshots === \"final\" ||\n validated.emitStateSnapshots === \"all\"\n ) {\n const snapshot = validated.stateMapper \n ? validated.stateMapper(state) \n : cleanLangChainData(state);\n \n // Remove messages from state snapshot by default to avoid redundancy\n if (!validated.stateMapper && snapshot && typeof snapshot === \"object\") {\n delete (snapshot as any).messages;\n }\n\n transport.emit({\n type: \"STATE_SNAPSHOT\",\n snapshot,\n timestamp: Date.now(),\n });\n }\n\n const stateAny = state as any;\n if (stateAny.error) {\n const error = stateAny.error;\n const errorMessage = error instanceof Error ? error.message : String(error);\n transport.emit({\n type: \"RUN_ERROR\",\n message:\n validated.errorDetailLevel === \"full\" ||\n validated.errorDetailLevel === \"message\"\n ? errorMessage\n : \"\",\n code: \"AGENT_EXECUTION_ERROR\",\n timestamp: Date.now(),\n // REMOVED: threadId, runId, parentRunId\n });\n } else {\n transport.emit({\n type: \"RUN_FINISHED\",\n threadId: threadId!,\n runId: runId!,\n result: validated.resultMapper ? validated.resultMapper(state) : undefined,\n timestamp: Date.now(),\n });\n }\n } catch {\n // Fail-safe\n }\n\n return {};\n },\n });\n}\n","import type {\n AGUIEvent,\n TextMessageStartEvent,\n TextMessageContentEvent,\n TextMessageEndEvent,\n ToolCallStartEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n} from \"../events\";\nimport { generateId } from \"./idGenerator\";\n\n/**\n * Normalizes and expands convenience events into their explicit counterparts.\n *\n * @param event - The event to expand\n * @returns An array of explicit AG-UI events\n */\nexport function expandEvent(event: AGUIEvent): AGUIEvent[] {\n switch (event.type) {\n case \"TEXT_MESSAGE_CHUNK\": {\n const messageId = event.messageId || generateId();\n const results: AGUIEvent[] = [];\n\n if (event.role) {\n results.push({\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: event.role,\n } as TextMessageStartEvent);\n }\n\n if (event.delta) {\n results.push({\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: event.delta,\n } as TextMessageContentEvent);\n }\n\n // If it has a role and delta, we assume it's a complete short message\n if (event.role && event.delta) {\n results.push({\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as TextMessageEndEvent);\n }\n\n return results.length > 0 ? results : [event];\n }\n\n case \"TOOL_CALL_CHUNK\": {\n const toolCallId = event.toolCallId || generateId();\n const results: AGUIEvent[] = [];\n\n if (event.toolCallName) {\n results.push({\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName: event.toolCallName,\n parentMessageId: event.parentMessageId,\n } as ToolCallStartEvent);\n }\n\n if (event.delta) {\n results.push({\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: event.delta,\n } as ToolCallArgsEvent);\n }\n\n if (event.toolCallName && event.delta) {\n results.push({\n type: \"TOOL_CALL_END\",\n toolCallId,\n parentMessageId: event.parentMessageId,\n } as ToolCallEndEvent);\n }\n\n return results.length > 0 ? results : [event];\n }\n\n default:\n return [event];\n }\n}\n","/**\n * AG-UI Callback Handler\n * \n * Handles streaming events for LLM tokens and tool calls.\n */\n\nimport { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport { generateId, generateDeterministicId } from \"../utils/idGenerator\";\nimport { extractToolOutput } from \"../utils/cleaner\";\nimport { expandEvent } from \"../utils/eventNormalizer\";\nimport type { AGUITransport } from \"../transports/types\";\n\n/**\n * Configuration options for the callback handler.\n */\nexport interface AGUICallbackHandlerOptions {\n /** Maximum payload size in bytes for UI events (default: 50KB) */\n maxUIPayloadSize?: number;\n /** Whether to chunk large payloads instead of truncating */\n chunkLargeResults?: boolean;\n}\n\n/**\n * Callback handler for AG-UI protocol streaming events.\n * Handles LLM token streaming and tool call lifecycle events.\n */\nexport class AGUICallbackHandler extends BaseCallbackHandler {\n name = \"ag-ui-callback\";\n\n private messageIds = new Map<string, string>();\n private latestMessageIds = new Map<string, string>();\n private agentRunIds = new Map<string, string>(); // Maps current runId to authoritative agentRunId\n private parentToAuthoritativeId = new Map<string, string>(); // Maps internal parentRunId to authoritative agentRunId\n private thinkingIds = new Map<string, string>();\n private toolCallInfo = new Map<string, { id: string; name: string }>();\n private toolCallNames = new Map<string, string>(); // Maps toolCallId to tool name from LLM tool_calls\n private agentTurnTracker = new Map<string, number>();\n private pendingToolCalls = new Map<string, string[]>();\n private accumulatedToolArgs = new Map<string, string>(); // Accumulates partial args for streaming tool calls\n private transport: AGUITransport;\n \n private maxUIPayloadSize: number;\n private chunkLargeResults: boolean;\n\n constructor(transport: AGUITransport, options?: AGUICallbackHandlerOptions) {\n super({ raiseError: false });\n this.transport = transport;\n this.maxUIPayloadSize = options?.maxUIPayloadSize ?? 50 * 1024;\n this.chunkLargeResults = options?.chunkLargeResults ?? false;\n }\n\n dispose(): void {\n this.messageIds.clear();\n this.latestMessageIds.clear();\n this.agentRunIds.clear();\n this.parentToAuthoritativeId.clear();\n this.thinkingIds.clear();\n this.toolCallInfo.clear();\n this.toolCallNames.clear();\n this.agentTurnTracker.clear();\n this.pendingToolCalls.clear();\n this.accumulatedToolArgs.clear();\n }\n\n // ==================== Convenience Methods for Chunk Events ====================\n\n /**\n * Emit a TEXT_MESSAGE_CHUNK event (convenience method)\n * Auto-expands to START → CONTENT → END lifecycle\n * \n * Use this for simple cases where you have the complete message at once\n * instead of handling the streaming lifecycle manually.\n * \n * @param messageId - Unique message identifier (auto-generated if not provided)\n * @param role - Message role (defaults to \"assistant\")\n * @param delta - Text content to emit\n */\n async emitTextChunk(\n messageId: string,\n role: \"assistant\" | \"user\" | \"system\" | \"developer\" = \"assistant\",\n delta: string\n ): Promise<void> {\n const events = expandEvent({\n type: \"TEXT_MESSAGE_CHUNK\",\n messageId,\n role,\n delta,\n } as any);\n \n for (const event of events) {\n await this.transport.emit(event);\n }\n }\n\n /**\n * Emit a TOOL_CALL_CHUNK event (convenience method)\n * Auto-expands to START → ARGS → END lifecycle\n * \n * Use this for simple tool calls where you have the complete arguments at once\n * instead of handling the streaming lifecycle manually.\n * \n * @param toolCallId - Unique tool call identifier (auto-generated if not provided)\n * @param toolCallName - Name of the tool being called\n * @param delta - Tool arguments (JSON string)\n * @param parentMessageId - ID of the message that triggered this tool call\n */\n async emitToolChunk(\n toolCallId: string,\n toolCallName: string,\n delta: string,\n parentMessageId?: string\n ): Promise<void> {\n const events = expandEvent({\n type: \"TOOL_CALL_CHUNK\",\n toolCallId,\n toolCallName,\n delta,\n parentMessageId,\n } as any);\n \n for (const event of events) {\n await this.transport.emit(event);\n }\n }\n\n // ==================== LLM Callbacks ====================\n\n override async handleLLMStart(\n _llm: any,\n _prompts: string[],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n _tags?: string[],\n _metadata?: Record<string, unknown>,\n _runName?: string\n ): Promise<void> {\n // Priority: metadata.agui_messageId (from middleware) > metadata.run_id > parentRunId > runId\n const agentRunId =\n ((_metadata as any)?.agui_runId as string | undefined) ||\n ((_metadata as any)?.run_id as string | undefined) ||\n ((_metadata as any)?.configurable?.run_id as string | undefined) ||\n _parentRunId ||\n runId;\n\n this.agentRunIds.set(runId, agentRunId);\n if (_parentRunId) {\n this.parentToAuthoritativeId.set(_parentRunId, agentRunId);\n }\n\n // Check if middleware sent us a messageId via metadata\n const middlewareMessageId = (_metadata as any)?.agui_messageId as string | undefined;\n \n if (middlewareMessageId) {\n // Use middleware's messageId for coordination\n this.messageIds.set(runId, middlewareMessageId);\n this.latestMessageIds.set(agentRunId, middlewareMessageId);\n \n // Emit TEXT_MESSAGE_START (coordination with middleware)\n this.transport.emit({\n type: \"TEXT_MESSAGE_START\",\n messageId: middlewareMessageId,\n role: \"assistant\",\n timestamp: Date.now(),\n });\n } else {\n // Generate our own messageId if middleware didn't provide one\n const turnIndex = this.agentTurnTracker.get(agentRunId) || 0;\n this.agentTurnTracker.set(agentRunId, turnIndex + 1);\n\n const messageId = generateDeterministicId(agentRunId, turnIndex);\n this.messageIds.set(runId, messageId);\n this.latestMessageIds.set(agentRunId, messageId);\n \n // Emit TEXT_MESSAGE_START (no middleware coordination)\n this.transport.emit({\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n timestamp: Date.now(),\n });\n }\n }\n\n override async handleLLMNewToken(\n token: string,\n _idx: any,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n fields?: any\n ): Promise<void> {\n const messageId = this.messageIds.get(runId);\n if (!messageId) return;\n\n try {\n // Handle Reasoning Tokens (e.g., DeepSeek, OpenAI o1)\n const reasoningContent = fields?.chunk?.message?.additional_kwargs?.reasoning_content ||\n fields?.chunk?.message?.additional_kwargs?.reasoning;\n if (reasoningContent) {\n let thinkingId = this.thinkingIds.get(runId);\n if (!thinkingId) {\n const agentRunId = this.agentRunIds.get(runId) ||\n (_parentRunId ? this.parentToAuthoritativeId.get(_parentRunId) : null) ||\n _parentRunId ||\n runId;\n thinkingId = generateDeterministicId(agentRunId, (this.agentTurnTracker.get(agentRunId) || 1) + 100); // Offset for thinking\n this.thinkingIds.set(runId, thinkingId);\n this.transport.emit({\n type: \"THINKING_START\",\n timestamp: Date.now(),\n });\n this.transport.emit({\n type: \"THINKING_TEXT_MESSAGE_START\",\n messageId: thinkingId,\n timestamp: Date.now(),\n });\n }\n\n const delta = typeof reasoningContent === 'string'\n ? reasoningContent\n : ((reasoningContent as any).text || JSON.stringify(reasoningContent));\n\n this.transport.emit({\n type: \"THINKING_TEXT_MESSAGE_CONTENT\",\n messageId: thinkingId,\n delta,\n timestamp: Date.now(),\n });\n }\n\n // Emit TEXT_MESSAGE_CONTENT for streaming tokens\n if (token && token.length > 0) {\n this.transport.emit({\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: token,\n timestamp: Date.now(),\n });\n }\n\n // Emit TOOL_CALL_ARGS for streaming tool arguments (may contain partial JSON fragments)\n const toolCallChunks = fields?.chunk?.message?.tool_call_chunks;\n if (toolCallChunks && Array.isArray(toolCallChunks)) {\n const agentRunId = this.agentRunIds.get(runId) || \n (_parentRunId ? this.parentToAuthoritativeId.get(_parentRunId) : null) || \n _parentRunId || \n runId;\n \n // Track tool call IDs for correlation with handleToolStart\n const pending = this.pendingToolCalls.get(agentRunId) || [];\n \n for (const chunk of toolCallChunks) {\n if (chunk.id && chunk.args) {\n // Accumulate partial args by toolCallId\n const previousArgs = this.accumulatedToolArgs.get(chunk.id) || \"\";\n const newArgs = previousArgs + chunk.args;\n \n // Only accumulate if args have changed (avoid duplicate accumulations)\n if (newArgs !== previousArgs) {\n this.accumulatedToolArgs.set(chunk.id, newArgs);\n }\n \n // Track this tool call ID for later correlation\n if (!pending.includes(chunk.id)) {\n pending.push(chunk.id);\n }\n }\n }\n \n if (pending.length > 0) {\n this.pendingToolCalls.set(agentRunId, pending);\n }\n }\n } catch {\n // Fail-safe\n }\n }\n\n override async handleLLMEnd(\n _output: any,\n runId: string,\n _parentRunId?: string,\n _tags?: string[],\n _extraParams?: Record<string, unknown>\n ): Promise<void> {\n const messageId = this.messageIds.get(runId);\n const thinkingId = this.thinkingIds.get(runId);\n\n try {\n // Collect any tool calls from final output that we missed during streaming\n if (_output && typeof _output === \"object\") {\n const toolCalls = _output.tool_calls || (_output.kwargs?.tool_calls);\n if (Array.isArray(toolCalls)) {\n const agentRunId = this.agentRunIds.get(runId) ||\n (_parentRunId ? this.parentToAuthoritativeId.get(_parentRunId) : null) ||\n _parentRunId ||\n runId;\n const pending = this.pendingToolCalls.get(agentRunId) || [];\n for (const tc of toolCalls) {\n if (tc.id && !pending.includes(tc.id)) {\n pending.push(tc.id);\n \n // Store tool name for later use in handleToolStart\n if (tc.function?.name) {\n this.toolCallNames.set(tc.id, tc.function.name);\n }\n \n // Accumulate tool call args for later emission in handleToolStart\n if (tc.function?.arguments) {\n this.accumulatedToolArgs.set(tc.id, tc.function.arguments);\n }\n }\n }\n this.pendingToolCalls.set(agentRunId, pending);\n }\n }\n\n // Emit TEXT_MESSAGE_END\n if (messageId) {\n this.transport.emit({\n type: \"TEXT_MESSAGE_END\",\n messageId,\n timestamp: Date.now(),\n });\n }\n\n if (thinkingId) {\n this.transport.emit({\n type: \"THINKING_TEXT_MESSAGE_END\",\n messageId: thinkingId,\n timestamp: Date.now(),\n });\n this.transport.emit({\n type: \"THINKING_END\",\n timestamp: Date.now(),\n });\n this.thinkingIds.delete(runId);\n }\n\n // Cleanup\n this.messageIds.delete(runId);\n } catch {\n // Fail-safe\n }\n }\n\n override async handleLLMError(\n _error: Error,\n runId: string,\n _parentRunId?: string\n ): Promise<void> {\n this.messageIds.delete(runId);\n this.thinkingIds.delete(runId);\n const agentRunId = this.agentRunIds.get(runId) ||\n (_parentRunId ? this.parentToAuthoritativeId.get(_parentRunId) : null) ||\n _parentRunId ||\n runId;\n this.pendingToolCalls.delete(agentRunId);\n this.agentRunIds.delete(runId);\n }\n\n // ==================== Tool Callbacks ====================\n\n override async handleToolStart(\n tool: any,\n input: string,\n runId: string,\n parentRunId?: string,\n _tags?: string[],\n metadata?: Record<string, unknown>,\n runName?: string\n ): Promise<void> {\n let toolCallId = runId;\n \n // Try to get tool name from various sources (in priority order):\n // 1. runName parameter (most direct - provided by LangChain)\n // 2. From tool object properties (tool.kwargs.name)\n // 3. From stored tool names (populated in handleLLMEnd from LLM tool_calls)\n // 4. From input JSON\n // 5. Default to \"unknown_tool\"\n let toolCallName = runName || \n (tool as any).kwargs?.name ||\n (tool as any).name || \n (tool as any).func?.name || \n (tool as any).getName?.() || \n (tool as any).toolName ||\n (tool as any)._name ||\n \"unknown_tool\"; // Ensure always populated\n\n try {\n // Priority order for toolCallId (MUST use LangChain IDs only):\n // 1. metadata.tool_call_id (modern LangChain pattern)\n // 2. Input's tool_call_id or id field (from tool invocation)\n // 3. Match accumulated streaming args by content\n \n // 1. Check metadata for tool_call_id (if provided)\n if (metadata?.tool_call_id && typeof metadata.tool_call_id === \"string\") {\n toolCallId = metadata.tool_call_id;\n \n // If we have a stored tool name for this ID, use it\n const storedName = this.toolCallNames.get(toolCallId);\n if (storedName && storedName !== \"unknown_tool\") {\n toolCallName = storedName;\n }\n }\n // 2. Check input for tool_call_id or id\n else if (input) {\n try {\n const parsed = typeof input === \"string\" ? JSON.parse(input) : input;\n if (parsed && typeof parsed === \"object\") {\n if (parsed.tool_call_id) {\n toolCallId = parsed.tool_call_id;\n } else if (parsed.id) {\n toolCallId = parsed.id;\n }\n if (parsed.name) {\n toolCallName = parsed.name;\n }\n }\n } catch {\n // Not JSON, ignore\n }\n }\n // 3. Match accumulated streaming args by content comparison\n if (toolCallId === runId && this.accumulatedToolArgs.size > 0 && input) {\n // Find matching accumulated ID by comparing args content\n for (const [id, args] of this.accumulatedToolArgs) {\n if (input.includes(args) || args.includes(input)) {\n toolCallId = id;\n \n // If we have a stored tool name for this ID, use it\n const storedName = this.toolCallNames.get(id);\n if (storedName && storedName !== \"unknown_tool\") {\n toolCallName = storedName;\n }\n break;\n }\n }\n }\n } catch {\n // Use defaults\n }\n\n try {\n // Priority order for toolCallId (MUST use LangChain IDs only):\n // 1. metadata.tool_call_id (modern LangChain pattern)\n // 2. Input's tool_call_id or id field (from tool invocation)\n // 3. Match accumulated streaming args by content\n \n // 1. Check metadata for tool_call_id (if provided)\n if (metadata?.tool_call_id && typeof metadata.tool_call_id === \"string\") {\n toolCallId = metadata.tool_call_id;\n }\n // 2. Check input for tool_call_id or id\n else if (input) {\n try {\n const parsed = typeof input === \"string\" ? JSON.parse(input) : input;\n if (parsed && typeof parsed === \"object\") {\n if (parsed.tool_call_id) {\n toolCallId = parsed.tool_call_id;\n } else if (parsed.id) {\n toolCallId = parsed.id;\n }\n if (parsed.name) {\n toolCallName = parsed.name;\n }\n }\n } catch {\n // Not JSON, ignore\n }\n }\n // 3. Match accumulated streaming args by content comparison\n if (toolCallId === runId && this.accumulatedToolArgs.size > 0 && input) {\n // Find matching accumulated ID by comparing args content\n for (const [id, args] of this.accumulatedToolArgs) {\n if (input.includes(args) || args.includes(input)) {\n toolCallId = id;\n break;\n }\n }\n }\n } catch {\n // Use defaults\n }\n\n this.toolCallInfo.set(runId, { id: toolCallId, name: toolCallName });\n\n const agentRunId = (parentRunId ? this.parentToAuthoritativeId.get(parentRunId) : null) || parentRunId || \"\";\n const messageId = this.latestMessageIds.get(agentRunId);\n\n try {\n // Emit TOOL_CALL_START first\n this.transport.emit({\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName,\n parentMessageId: messageId,\n timestamp: Date.now(),\n });\n\n // Emit accumulated TOOL_CALL_ARGS (from streaming in handleLLMNewToken)\n // This preserves real-time streaming while maintaining protocol sequence\n const accumulatedArgs = this.accumulatedToolArgs.get(toolCallId);\n if (accumulatedArgs) {\n this.transport.emit({\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: accumulatedArgs,\n timestamp: Date.now(),\n });\n // Clean up accumulated args\n this.accumulatedToolArgs.delete(toolCallId);\n }\n } catch {\n // Fail-safe\n }\n }\n\n override async handleToolEnd(\n output: any,\n runId: string,\n parentRunId?: string\n ): Promise<void> {\n const toolInfo = this.toolCallInfo.get(runId);\n this.toolCallInfo.delete(runId);\n\n // Cleanup tool name mapping\n if (toolInfo?.id) {\n this.toolCallNames.delete(toolInfo.id);\n }\n\n const agentRunId = (parentRunId ? this.parentToAuthoritativeId.get(parentRunId) : null) || parentRunId || \"\";\n const messageId = this.latestMessageIds.get(agentRunId);\n\n try {\n const endToolCallId = toolInfo?.id ?? runId;\n\n // If output is a LangChain message, it might contain the real tool_call_id\n let finalToolCallId = endToolCallId;\n if (output && typeof output === \"object\") {\n const kwargs = output.kwargs || output.lc_kwargs;\n if (kwargs?.tool_call_id) {\n finalToolCallId = kwargs.tool_call_id;\n }\n }\n\n this.transport.emit({\n type: \"TOOL_CALL_END\",\n toolCallId: finalToolCallId,\n timestamp: Date.now(),\n });\n\n this.emitToolResultWithPolicy(output, finalToolCallId, messageId, toolInfo?.name);\n } catch {\n // Fail-safe\n }\n }\n\n override async handleToolError(\n _error: Error,\n runId: string,\n parentRunId?: string\n ): Promise<void> {\n const toolInfo = this.toolCallInfo.get(runId);\n this.toolCallInfo.delete(runId);\n \n // Cleanup accumulated tool args for this tool call\n if (toolInfo?.id) {\n this.accumulatedToolArgs.delete(toolInfo.id);\n }\n \n const agentRunId = (parentRunId ? this.parentToAuthoritativeId.get(parentRunId) : null) || parentRunId || \"\";\n const messageId = this.latestMessageIds.get(agentRunId);\n\n try {\n this.transport.emit({\n type: \"TOOL_CALL_END\",\n toolCallId: toolInfo?.id ?? runId,\n timestamp: Date.now(),\n });\n } catch {\n // Fail-safe\n }\n }\n\n // ==================== Smart Emission ====================\n\n private chunkString(content: string, maxChunkSize: number): string[] {\n const chunks: string[] = [];\n let remaining = content;\n \n while (remaining.length > 0) {\n if (new Blob([remaining]).size <= maxChunkSize) {\n chunks.push(remaining);\n break;\n }\n \n let splitPoint = maxChunkSize;\n const spaceIndex = remaining.lastIndexOf(' ', maxChunkSize);\n const newlineIndex = remaining.lastIndexOf('\\n', maxChunkSize);\n const boundaryIndex = Math.max(spaceIndex, newlineIndex);\n \n if (boundaryIndex > maxChunkSize * 0.5) {\n splitPoint = boundaryIndex;\n } else {\n while (splitPoint > 0 && remaining.charCodeAt(splitPoint - 1) > 127) {\n splitPoint--;\n }\n if (splitPoint === 0) {\n splitPoint = maxChunkSize;\n }\n }\n \n chunks.push(remaining.substring(0, splitPoint));\n remaining = remaining.substring(splitPoint).trim();\n }\n \n return chunks;\n }\n\n private emitToolResultWithPolicy(\n output: any,\n toolCallId: string,\n messageId: string | undefined,\n toolCallName?: string\n ): void {\n let content = extractToolOutput(output);\n const resultMessageId = generateId();\n const contentSize = new Blob([content]).size;\n \n if (contentSize <= this.maxUIPayloadSize) {\n this.transport.emit({\n type: \"TOOL_CALL_RESULT\",\n messageId: resultMessageId,\n toolCallId,\n content,\n role: \"tool\",\n timestamp: Date.now(),\n });\n return;\n }\n \n if (this.chunkLargeResults) {\n const chunks = this.chunkString(content, this.maxUIPayloadSize);\n for (let i = 0; i < chunks.length; i++) {\n // Use CUSTOM event or a new event type for large result chunks\n // to avoid collision with ToolCallChunk which is for arguments\n this.transport.emit({\n type: \"CUSTOM\",\n name: \"LARGE_RESULT_CHUNK\",\n value: {\n toolCallId,\n chunk: chunks[i],\n index: i,\n total: chunks.length\n }\n });\n }\n return;\n }\n\n const truncationMessage = ` [Truncated: ${contentSize - this.maxUIPayloadSize + 50} bytes]`;\n const availableSpace = this.maxUIPayloadSize - truncationMessage.length;\n const truncatedContent = content.substring(0, Math.max(0, availableSpace)) + truncationMessage;\n\n this.transport.emit({\n type: \"TOOL_CALL_RESULT\",\n messageId: resultMessageId,\n toolCallId,\n content: truncatedContent,\n role: \"tool\",\n timestamp: Date.now(),\n });\n }\n}\n","/**\n * AG-UI Agent Factory\n *\n * Creates a LangChain agent with automatic AG-UI protocol integration.\n *\n * Architecture:\n * - Uses createAgent() from langchain package\n * - Returns agent with callbacks bound to graph via withConfig\n * - Emits lifecycle events for agent execution (RUN_STARTED, RUN_FINISHED, etc.)\n * - Callbacks are merged with user-provided callbacks by LangChain\n * - Abort signal from context enables client disconnect handling\n */\n\nimport { createAgent } from \"langchain\";\nimport { AGUICallbackHandler, type AGUICallbackHandlerOptions } from \"./callbacks/AGUICallbackHandler\";\nimport { createAGUIMiddleware } from \"./middleware/createAGUIMiddleware\";\nimport type { AGUITransport } from \"./transports/types\";\nimport type { AGUIMiddlewareOptions } from \"./middleware/types\";\n\n/**\n * Configuration for creating an AG-UI enabled agent.\n */\nexport interface AGUIAgentConfig {\n /** The language model to use */\n model: any;\n /** The tools available to the agent */\n tools: any[];\n /** The transport for AG-UI events */\n transport: AGUITransport;\n /** Optional middleware configuration */\n middlewareOptions?: Partial<AGUIMiddlewareOptions>;\n /** Optional callback handler configuration */\n callbackOptions?: AGUICallbackHandlerOptions;\n}\n\n/**\n * Create an AG-UI enabled agent.\n *\n * This function creates a LangChain agent with automatic AG-UI protocol integration:\n * - Middleware handles lifecycle events (RUN_STARTED, RUN_FINISHED, etc.)\n * - Callbacks handle streaming events (TEXT_MESSAGE_CONTENT, TOOL_CALL_ARGS, etc.)\n * - Callbacks must be passed at runtime via agent.streamEvents() config\n * - Guaranteed cleanup via middleware wrapModelCall with try-finally\n *\n * Note: Callbacks are not bound to the model here because:\n * 1. Some models (like MockChatModel in tests) don't properly support withConfig()\n * 2. Users should pass callbacks at runtime for proper streaming\n *\n * @param config - Agent configuration\n * @returns An agent with AG-UI protocol support\n */\nexport function createAGUIAgent(config: AGUIAgentConfig) {\n // Create middleware with transport\n const middleware = createAGUIMiddleware({\n transport: config.transport,\n emitToolResults: config.middlewareOptions?.emitToolResults ?? true,\n emitStateSnapshots: config.middlewareOptions?.emitStateSnapshots ?? \"initial\",\n emitActivities: config.middlewareOptions?.emitActivities ?? false,\n maxUIPayloadSize: config.middlewareOptions?.maxUIPayloadSize ?? 50 * 1024,\n chunkLargeResults: config.middlewareOptions?.chunkLargeResults ?? false,\n threadIdOverride: config.middlewareOptions?.threadIdOverride,\n runIdOverride: config.middlewareOptions?.runIdOverride,\n errorDetailLevel: config.middlewareOptions?.errorDetailLevel ?? \"message\",\n stateMapper: config.middlewareOptions?.stateMapper,\n resultMapper: config.middlewareOptions?.resultMapper,\n activityMapper: config.middlewareOptions?.activityMapper,\n validateEvents: config.middlewareOptions?.validateEvents ?? false,\n });\n\n // Create base agent with middleware\n // Note: Callbacks are NOT bound here - they must be passed at runtime\n const agent = createAgent({\n model: config.model,\n tools: config.tools,\n middleware: [middleware],\n });\n\n // Attach global listeners for guaranteed cleanup and error handling if supported\n if (agent && typeof (agent as any).withListeners === \"function\") {\n return (agent as any).withListeners({\n onError: (run: any) => {\n try {\n // Extract threadId and runId from run config if available\n const threadId = run.config?.configurable?.threadId as string | undefined;\n const agentRunId = run.config?.configurable?.runId as string | undefined;\n config.transport.emit({\n type: \"RUN_ERROR\",\n message: typeof run.error === \"string\" ? run.error : (run.error as any)?.message || \"Agent execution failed\",\n code: \"AGENT_EXECUTION_ERROR\",\n timestamp: Date.now(),\n // REMOVED: threadId, runId\n });\n } catch {\n // Fail-safe\n }\n },\n });\n }\n\n return agent;\n}\n","/**\n * SSE Transport Implementation\n * \n * Server-Sent Events transport for AG-UI protocol.\n * Provides:\n * - Proper SSE headers\n * - Fail-safe emission (never throws on client disconnect)\n * - Abort signal integration for client disconnect handling\n * - Backpressure handling with queue-based emission\n */\n\nimport type { AGUIEvent } from \"../events\";\nimport type { AGUITransport } from \"./types\";\n\n/**\n * Extended SSE transport interface with abort signal.\n */\nexport interface SSETransport extends AGUITransport {\n /** Abort signal triggered on client disconnect */\n signal: AbortSignal;\n}\n\n/**\n * HTTP request interface for SSE transport.\n */\ninterface SSETransportRequest {\n on(event: string, callback: () => void): void;\n}\n\n/**\n * HTTP response interface for SSE transport.\n */\ninterface SSETransportResponse {\n setHeader(name: string, value: string): SSETransportResponse;\n write(data: string): boolean;\n end?(): void;\n}\n\n/**\n * Create an SSE transport for Server-Sent Events.\n * \n * @param req - HTTP request object (listens for 'close' event)\n * @param res - HTTP response object\n * @returns SSETransport with emit method and abort signal\n */\nexport function createSSETransport(\n req: SSETransportRequest,\n res: SSETransportResponse\n): SSETransport {\n // Set proper SSE headers\n res.setHeader(\"Content-Type\", \"text/event-stream\");\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n res.setHeader(\"X-Accel-Buffering\", \"no\");\n\n // Create abort controller for client disconnect handling\n const controller = new AbortController();\n req.on(\"close\", () => controller.abort());\n\n // Backpressure queue\n const queue: AGUIEvent[] = [];\n let draining = false;\n\n /**\n * Drain the event queue to the response.\n */\n async function drain(): Promise<void> {\n draining = true;\n while (queue.length > 0 && res.write) {\n const event = queue.shift()!;\n try {\n res.write(`data: ${JSON.stringify(event)}\\n\\n`);\n } catch {\n // Client disconnected - stop draining\n break;\n }\n }\n draining = false;\n }\n\n return {\n emit: (event: AGUIEvent) => {\n queue.push(event);\n if (!draining) {\n drain();\n }\n },\n\n signal: controller.signal,\n\n disconnect: res.end\n ? () => {\n res.end?.();\n }\n : undefined,\n\n isConnected: () => !controller.signal.aborted,\n };\n}\n","/**\n * Protobuf Transport Implementation\n * \n * Protocol Buffer transport for AG-UI protocol.\n * Provides:\n * - Binary encoding using @ag-ui/proto\n * - 4-byte Big-Endian length prefix per protocol spec\n * - Fail-safe emission (never throws on client disconnect)\n * - Abort signal integration for client disconnect handling\n * - Backpressure handling with queue-based emission\n * \n * Protobuf provides 60-80% smaller payloads compared to JSON/SSE.\n * \n * @see https://docs.ag-ui.com/introduction\n */\n\nimport { encode, decode, AGUI_MEDIA_TYPE } from '@ag-ui/proto';\nimport type { AGUIEvent } from \"../events\";\nimport type { AGUITransport, ProtobufTransport } from \"./types\";\n\n/**\n * Re-export the official AG-UI media type for content negotiation.\n */\nexport { AGUI_MEDIA_TYPE };\n\n/**\n * HTTP request interface for Protobuf transport.\n */\ninterface ProtobufTransportRequest {\n on(event: string, callback: () => void): void;\n}\n\n/**\n * HTTP response interface for Protobuf transport.\n */\ninterface ProtobufTransportResponse {\n setHeader(name: string, value: string): ProtobufTransportResponse;\n write(data: Buffer | Uint8Array): boolean;\n end?(): void;\n}\n\n/**\n * Encode an AG-UI event with 4-byte Big-Endian length prefix.\n * \n * Per AG-UI protocol spec:\n * ┌─────────────────┬──────────────────────────────────┐\n * │ Length (4 BE) │ Protobuf Event Bytes │\n * └─────────────────┴──────────────────────────────────┘\n * \n * @param event - The AG-UI event to encode\n * @returns Uint8Array with length prefix + protobuf bytes\n */\nexport function encodeEventWithFraming(event: AGUIEvent): Uint8Array {\n // Convert our event type to @ag-ui/core BaseEvent format\n // The @ag-ui/proto encode function expects a BaseEvent from @ag-ui/core\n const coreEvent = convertToProtobufEvent(event);\n \n // Encode to protobuf bytes\n const eventBytes = encode(coreEvent);\n \n // Create 4-byte Big-Endian length prefix\n const lengthPrefix = new DataView(new ArrayBuffer(4));\n lengthPrefix.setUint32(0, eventBytes.length, false); // false = Big-Endian\n \n // Concatenate length + payload\n const result = new Uint8Array(4 + eventBytes.length);\n result.set(new Uint8Array(lengthPrefix.buffer), 0);\n result.set(eventBytes, 4);\n \n return result;\n}\n\n/**\n * Decode a framed protobuf event (with 4-byte length prefix).\n * \n * @param data - Buffer containing length prefix + protobuf bytes\n * @returns The decoded AG-UI event\n */\nexport function decodeEventWithFraming(data: Uint8Array): AGUIEvent {\n if (data.length < 4) {\n throw new Error(\"Invalid protobuf frame: insufficient data for length prefix\");\n }\n \n const length = new DataView(data.buffer, data.byteOffset).getUint32(0, false); // Big-Endian\n \n if (data.length < 4 + length) {\n throw new Error(\"Invalid protobuf frame: insufficient data for payload\");\n }\n \n const eventBytes = data.slice(4, 4 + length);\n const decoded = decode(eventBytes);\n \n // Convert back to our event format\n return convertFromProtobufEvent(decoded) as AGUIEvent;\n}\n\n/**\n * Convert our event format to @ag-ui/core BaseEvent format.\n * Handles field name differences (e.g., tool_calls → toolCalls).\n */\nfunction convertToProtobufEvent(event: AGUIEvent): any {\n const baseEvent: any = { ...event };\n \n // Handle Message objects in MESSAGES_SNAPSHOT\n if (event.type === \"MESSAGES_SNAPSHOT\" && event.messages) {\n baseEvent.messages = event.messages.map((msg: any) => ({\n ...msg,\n // Convert tool_calls to toolCalls if present\n toolCalls: msg.tool_calls?.map((tc: any) => ({\n id: tc.id,\n type: tc.type,\n function: tc.function,\n })),\n // Remove snake_case version\n tool_calls: undefined,\n // Convert tool_call_id to toolCallId\n toolCallId: msg.tool_call_id,\n tool_call_id: undefined,\n }));\n }\n \n return baseEvent;\n}\n\n/**\n * Convert @ag-ui/core BaseEvent format back to our event format.\n * Handles field name differences (e.g., toolCalls → tool_calls).\n */\nfunction convertFromProtobufEvent(event: any): AGUIEvent {\n const result: any = { ...event };\n \n // Handle Message objects in MESSAGES_SNAPSHOT\n if (event.type === \"MESSAGES_SNAPSHOT\" && event.messages) {\n result.messages = event.messages.map((msg: any) => ({\n ...msg,\n // Convert toolCalls to tool_calls if present\n tool_calls: msg.toolCalls?.map((tc: any) => ({\n id: tc.id,\n type: tc.type,\n function: tc.function,\n })),\n // Remove camelCase version\n toolCalls: undefined,\n // Convert toolCallId to tool_call_id\n tool_call_id: msg.toolCallId,\n toolCallId: undefined,\n }));\n }\n \n return result;\n}\n\n/**\n * Create a Protobuf transport for binary AG-UI protocol communication.\n * \n * @param req - HTTP request object (listens for 'close' event)\n * @param res - HTTP response object\n * @returns ProtobufTransport with emit method and abort signal\n * \n * @example\n * ```typescript\n * app.post('/api/agent', (req, res) => {\n * const acceptProtobuf = req.headers.accept?.includes(AGUI_MEDIA_TYPE);\n * \n * if (acceptProtobuf) {\n * const transport = createProtobufTransport(req, res);\n * // Use transport.emit() for binary encoding\n * } else {\n * const transport = createSSETransport(req, res);\n * // Use transport.emit() for JSON/SSE\n * }\n * });\n * ```\n */\nexport function createProtobufTransport(\n req: ProtobufTransportRequest,\n res: ProtobufTransportResponse\n): ProtobufTransport {\n // Set proper Protobuf headers\n res.setHeader(\"Content-Type\", AGUI_MEDIA_TYPE);\n res.setHeader(\"Cache-Control\", \"no-cache\");\n res.setHeader(\"Connection\", \"keep-alive\");\n res.setHeader(\"X-Accel-Buffering\", \"no\");\n\n // Create abort controller for client disconnect handling\n const controller = new AbortController();\n req.on(\"close\", () => controller.abort());\n\n // Backpressure queue\n const queue: AGUIEvent[] = [];\n let draining = false;\n\n /**\n * Drain the event queue to the response.\n */\n async function drain(): Promise<void> {\n draining = true;\n while (queue.length > 0 && res.write) {\n const event = queue.shift()!;\n try {\n const framedData = encodeEventWithFraming(event);\n res.write(framedData);\n } catch {\n // Client disconnected or encoding error - stop draining\n break;\n }\n }\n draining = false;\n }\n\n return {\n emit: (event: AGUIEvent) => {\n queue.push(event);\n if (!draining) {\n drain();\n }\n },\n\n signal: controller.signal,\n\n disconnect: res.end\n ? () => {\n res.end?.();\n }\n : undefined,\n\n isConnected: () => !controller.signal.aborted,\n \n // Protobuf-specific utilities\n encodeEvent: encodeEventWithFraming,\n decodeEvent: decodeEventWithFraming,\n };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skroyc/ag-ui-middleware-callbacks",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "LangChain.js integration providing middleware and callbacks for AG-UI protocol compatibility",
|
|
5
|
+
"keywords": ["langchain", "ag-ui", "middleware", "callbacks", "agent", "streaming"],
|
|
6
|
+
"author": "SkrOYC <oscar@ocmasesorias.com>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/skrOYC/langchain-middlewares-callbacks-ts",
|
|
11
|
+
"directory": "packages/ag-ui-middleware-callbacks"
|
|
12
|
+
},
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18.0.0"
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist/", "package.json", "README.md", "LICENSE"],
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"typescript": ">=5"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@ag-ui/core": "^0.0.42",
|
|
32
|
+
"@ag-ui/proto": "^0.0.42",
|
|
33
|
+
"langchain": "^1.2.3",
|
|
34
|
+
"zod": "^3.22.4",
|
|
35
|
+
"fast-json-patch": "^3.1.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"tsup": "^8.5.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"test": "bun test",
|
|
44
|
+
"lint": "bun lint"
|
|
45
|
+
}
|
|
46
|
+
}
|