@uix-ai/adapter-agui 0.0.1

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/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # @uix-ai/adapter-agui
2
+
3
+ Adapter to convert [AG-UI protocol](https://docs.ag-ui.com) streaming events to UIX Lucid IR format.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @uix-ai/adapter-agui
9
+ ```
10
+
11
+ Peer dependencies: `react`, `@uix-ai/core`
12
+
13
+ ## Quick Start
14
+
15
+ ### Using the `useAGUI` hook (recommended)
16
+
17
+ ```tsx
18
+ import { AgentChat } from '@uix-ai/agent'
19
+ import { useAGUI } from '@uix-ai/adapter-agui/react'
20
+
21
+ function App() {
22
+ const { conversations, status, send, stop } = useAGUI({ url: '/api/agent' })
23
+
24
+ return (
25
+ <AgentChat
26
+ conversations={conversations}
27
+ status={status}
28
+ onSend={send}
29
+ onStop={stop}
30
+ />
31
+ )
32
+ }
33
+ ```
34
+
35
+ ### `useAGUI` Options
36
+
37
+ | Option | Type | Default | Description |
38
+ |--------|------|---------|-------------|
39
+ | `url` | `string` | *required* | AG-UI agent endpoint URL |
40
+ | `threadId` | `string` | auto-generated | Thread ID for conversation continuity |
41
+ | `headers` | `Record<string, string>` | -- | Custom headers for SSE connection |
42
+ | `processorOptions` | `AGUIProcessorOptions` | -- | Event processor configuration |
43
+ | `autoConnect` | `boolean` | `false` | Connect on mount |
44
+ | `onError` | `(error: Error) => void` | -- | Error callback |
45
+ | `onFinish` | `() => void` | -- | Run finished callback |
46
+
47
+ **Returns:** `{ conversations, status, send, stop, isLoading, reset, error }`
48
+
49
+ ### With thread persistence
50
+
51
+ ```tsx
52
+ const { conversations, send } = useAGUI({
53
+ url: '/api/agent',
54
+ threadId: 'thread-abc-123',
55
+ headers: { Authorization: 'Bearer ...' },
56
+ })
57
+ ```
58
+
59
+ ## Manual `AGUIEventProcessor` Usage
60
+
61
+ For non-React use cases or custom event sources, use the stateful processor directly:
62
+
63
+ ```typescript
64
+ import { AGUIEventProcessor } from '@uix-ai/adapter-agui'
65
+
66
+ const processor = new AGUIEventProcessor({
67
+ onUpdate: (conversations) => {
68
+ // Called after each event is processed
69
+ renderUI(conversations)
70
+ },
71
+ })
72
+
73
+ // Feed events from any source
74
+ eventSource.onmessage = (event) => {
75
+ processor.processEvent(JSON.parse(event.data))
76
+ }
77
+
78
+ // Read current state at any time
79
+ const conversations = processor.getConversations()
80
+
81
+ // Reset all state
82
+ processor.reset()
83
+ ```
84
+
85
+ ### Batch conversion (stateless)
86
+
87
+ For one-shot conversion of a complete event array:
88
+
89
+ ```typescript
90
+ import { fromAGUIEvents } from '@uix-ai/adapter-agui'
91
+
92
+ const conversations = fromAGUIEvents(events)
93
+ ```
94
+
95
+ ## Supported Event Types
96
+
97
+ ### Lifecycle Events
98
+
99
+ | Event | Description |
100
+ |-------|-------------|
101
+ | `RunStarted` | Agent run begins (with `threadId`, `runId`) |
102
+ | `RunFinished` | Agent run completes; all streaming messages marked completed |
103
+ | `RunError` | Agent run failed; last assistant message marked as error |
104
+ | `StepStarted` | Agent step begins |
105
+ | `StepFinished` | Agent step completes |
106
+
107
+ ### Text Message Events
108
+
109
+ | Event | Description |
110
+ |-------|-------------|
111
+ | `TextMessageStart` | New message created with role and ID |
112
+ | `TextMessageContent` | Text delta appended to current message |
113
+ | `TextMessageEnd` | Message streaming complete |
114
+
115
+ ### Tool Call Events
116
+
117
+ | Event | Description |
118
+ |-------|-------------|
119
+ | `ToolCallStart` | Tool invocation begins (attached to parent message) |
120
+ | `ToolCallArgs` | Streamed tool input argument deltas |
121
+ | `ToolCallEnd` | Tool input complete |
122
+ | `ToolCallResult` | Tool output received |
123
+
124
+ ### Reasoning Events
125
+
126
+ | Event | Description |
127
+ |-------|-------------|
128
+ | `ReasoningMessageStart` | Thinking/reasoning block begins |
129
+ | `ReasoningMessageContent` | Reasoning text delta |
130
+ | `ReasoningMessageEnd` | Reasoning complete |
131
+
132
+ ### State Events
133
+
134
+ | Event | Description |
135
+ |-------|-------------|
136
+ | `StateSnapshot` | Full state snapshot |
137
+ | `StateDelta` | JSON Patch delta for state |
138
+ | `MessagesSnapshot` | Full messages snapshot |
139
+
140
+ State events (`StateSnapshot`, `StateDelta`, `MessagesSnapshot`) are received but do not produce blocks in the current implementation.
141
+
142
+ ## Links
143
+
144
+ - [UIX Repository](https://github.com/Deepractice/UIX)
145
+ - [AG-UI Protocol Documentation](https://docs.ag-ui.com)
@@ -0,0 +1,267 @@
1
+ // src/index.ts
2
+ var blockIdCounter = 0;
3
+ function defaultGenerateBlockId() {
4
+ return `agui-block-${Date.now()}-${++blockIdCounter}`;
5
+ }
6
+ function mapRole(role) {
7
+ switch (role) {
8
+ case "user":
9
+ return "user";
10
+ case "system":
11
+ case "developer":
12
+ return "system";
13
+ case "assistant":
14
+ case "tool":
15
+ default:
16
+ return "assistant";
17
+ }
18
+ }
19
+ var AGUIEventProcessor = class {
20
+ constructor(options = {}) {
21
+ this.messages = /* @__PURE__ */ new Map();
22
+ this.messageOrder = [];
23
+ this.currentRunId = null;
24
+ this.generateId = options.generateBlockId ?? defaultGenerateBlockId;
25
+ this.onUpdate = options.onUpdate;
26
+ }
27
+ /**
28
+ * Process a single AG-UI event and update internal state
29
+ */
30
+ processEvent(event) {
31
+ switch (event.type) {
32
+ case "RunStarted":
33
+ this.handleRunStarted(event);
34
+ break;
35
+ case "RunFinished":
36
+ this.handleRunFinished(event);
37
+ break;
38
+ case "RunError":
39
+ this.handleRunError(event);
40
+ break;
41
+ case "TextMessageStart":
42
+ this.handleTextMessageStart(event);
43
+ break;
44
+ case "TextMessageContent":
45
+ this.handleTextMessageContent(event);
46
+ break;
47
+ case "TextMessageEnd":
48
+ this.handleTextMessageEnd(event);
49
+ break;
50
+ case "ToolCallStart":
51
+ this.handleToolCallStart(event);
52
+ break;
53
+ case "ToolCallArgs":
54
+ this.handleToolCallArgs(event);
55
+ break;
56
+ case "ToolCallEnd":
57
+ this.handleToolCallEnd(event);
58
+ break;
59
+ case "ToolCallResult":
60
+ this.handleToolCallResult(event);
61
+ break;
62
+ case "ReasoningMessageStart":
63
+ this.handleReasoningStart(event);
64
+ break;
65
+ case "ReasoningMessageContent":
66
+ this.handleReasoningContent(event);
67
+ break;
68
+ case "ReasoningMessageEnd":
69
+ this.handleReasoningEnd(event);
70
+ break;
71
+ default:
72
+ break;
73
+ }
74
+ this.onUpdate?.(this.getConversations());
75
+ }
76
+ /**
77
+ * Process multiple AG-UI events in order
78
+ */
79
+ processEvents(events) {
80
+ for (const event of events) {
81
+ this.processEvent(event);
82
+ }
83
+ }
84
+ /**
85
+ * Get the current state as UIX LucidConversations
86
+ */
87
+ getConversations() {
88
+ return this.messageOrder.map((msgId) => {
89
+ const state = this.messages.get(msgId);
90
+ return this.buildConversation(state);
91
+ });
92
+ }
93
+ /**
94
+ * Reset all state
95
+ */
96
+ reset() {
97
+ this.messages.clear();
98
+ this.messageOrder = [];
99
+ this.currentRunId = null;
100
+ }
101
+ // -- Lifecycle Handlers --
102
+ handleRunStarted(event) {
103
+ this.currentRunId = event.runId;
104
+ }
105
+ handleRunFinished(_event) {
106
+ for (const state of this.messages.values()) {
107
+ if (state.status === "streaming") {
108
+ state.status = "completed";
109
+ }
110
+ }
111
+ this.currentRunId = null;
112
+ }
113
+ handleRunError(event) {
114
+ const lastAssistant = this.findLastAssistantMessage();
115
+ if (lastAssistant) {
116
+ lastAssistant.status = "error";
117
+ }
118
+ }
119
+ // -- Text Message Handlers --
120
+ handleTextMessageStart(event) {
121
+ const blockId = this.generateId();
122
+ const state = {
123
+ conversationId: event.messageId,
124
+ role: mapRole(event.role),
125
+ textBlockId: blockId,
126
+ textContent: "",
127
+ thinkingBlockId: null,
128
+ thinkingContent: "",
129
+ toolBlocks: /* @__PURE__ */ new Map(),
130
+ status: "streaming",
131
+ timestamp: event.timestamp ?? Date.now()
132
+ };
133
+ this.messages.set(event.messageId, state);
134
+ this.messageOrder.push(event.messageId);
135
+ }
136
+ handleTextMessageContent(event) {
137
+ const state = this.messages.get(event.messageId);
138
+ if (!state) return;
139
+ state.textContent += event.delta;
140
+ }
141
+ handleTextMessageEnd(event) {
142
+ const state = this.messages.get(event.messageId);
143
+ if (!state) return;
144
+ state.status = "completed";
145
+ }
146
+ // -- Tool Call Handlers --
147
+ handleToolCallStart(event) {
148
+ const parentId = event.parentMessageId ?? this.findLastAssistantMessageId();
149
+ if (!parentId) return;
150
+ const state = this.messages.get(parentId);
151
+ if (!state) return;
152
+ state.toolBlocks.set(event.toolCallId, {
153
+ blockId: this.generateId(),
154
+ name: event.toolCallName,
155
+ argsJson: ""
156
+ });
157
+ }
158
+ handleToolCallArgs(event) {
159
+ const tool = this.findToolBlock(event.toolCallId);
160
+ if (!tool) return;
161
+ tool.argsJson += event.delta;
162
+ }
163
+ handleToolCallEnd(event) {
164
+ }
165
+ handleToolCallResult(event) {
166
+ const tool = this.findToolBlock(event.toolCallId);
167
+ if (!tool) return;
168
+ tool.output = event.content;
169
+ tool.hasResult = true;
170
+ }
171
+ // -- Reasoning Handlers --
172
+ handleReasoningStart(event) {
173
+ const state = this.messages.get(event.messageId);
174
+ if (!state) return;
175
+ state.thinkingBlockId = this.generateId();
176
+ state.thinkingContent = "";
177
+ }
178
+ handleReasoningContent(event) {
179
+ const state = this.messages.get(event.messageId);
180
+ if (!state) return;
181
+ state.thinkingContent += event.delta;
182
+ }
183
+ handleReasoningEnd(event) {
184
+ }
185
+ // -- Helpers --
186
+ findLastAssistantMessageId() {
187
+ for (let i = this.messageOrder.length - 1; i >= 0; i--) {
188
+ const id = this.messageOrder[i];
189
+ const state = this.messages.get(id);
190
+ if (state?.role === "assistant") return id;
191
+ }
192
+ return void 0;
193
+ }
194
+ findLastAssistantMessage() {
195
+ const id = this.findLastAssistantMessageId();
196
+ return id ? this.messages.get(id) : void 0;
197
+ }
198
+ findToolBlock(toolCallId) {
199
+ for (const state of this.messages.values()) {
200
+ const tool = state.toolBlocks.get(toolCallId);
201
+ if (tool) return tool;
202
+ }
203
+ return void 0;
204
+ }
205
+ buildConversation(state) {
206
+ const blocks = [];
207
+ if (state.thinkingBlockId && state.thinkingContent) {
208
+ blocks.push({
209
+ id: state.thinkingBlockId,
210
+ type: "thinking",
211
+ status: state.status === "streaming" ? "streaming" : "completed",
212
+ content: {
213
+ reasoning: state.thinkingContent
214
+ }
215
+ });
216
+ }
217
+ if (state.textBlockId && state.textContent) {
218
+ blocks.push({
219
+ id: state.textBlockId,
220
+ type: "text",
221
+ status: state.status === "streaming" ? "streaming" : "completed",
222
+ content: {
223
+ text: state.textContent
224
+ }
225
+ });
226
+ }
227
+ for (const [_toolCallId, tool] of state.toolBlocks) {
228
+ let input = {};
229
+ try {
230
+ input = tool.argsJson ? JSON.parse(tool.argsJson) : {};
231
+ } catch {
232
+ input = tool.argsJson;
233
+ }
234
+ const hasResult = tool.hasResult === true;
235
+ const toolStatus = hasResult ? "success" : "running";
236
+ blocks.push({
237
+ id: tool.blockId,
238
+ type: "tool",
239
+ status: hasResult ? "completed" : "streaming",
240
+ content: {
241
+ name: tool.name,
242
+ input,
243
+ output: tool.output,
244
+ status: toolStatus
245
+ }
246
+ });
247
+ }
248
+ return {
249
+ id: state.conversationId,
250
+ role: state.role,
251
+ status: state.status,
252
+ blocks,
253
+ timestamp: state.timestamp
254
+ };
255
+ }
256
+ };
257
+ function fromAGUIEvents(events, options = {}) {
258
+ const processor = new AGUIEventProcessor(options);
259
+ processor.processEvents(events);
260
+ return processor.getConversations();
261
+ }
262
+
263
+ export {
264
+ AGUIEventProcessor,
265
+ fromAGUIEvents
266
+ };
267
+ //# sourceMappingURL=chunk-MI5X6OBV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @uix-ai/adapter-agui\n *\n * Adapter to convert AG-UI protocol events to UIX Lucid IR format.\n *\n * AG-UI (Agent-User Interaction Protocol) is an open, event-based protocol\n * that standardizes how AI agent backends connect to frontend applications.\n *\n * This adapter converts AG-UI's streaming events into UIX LucidConversation\n * and LucidBlock structures for rendering with UIX components.\n *\n * @see https://docs.ag-ui.com\n *\n * @example\n * ```typescript\n * import { AGUIEventProcessor } from '@uix-ai/adapter-agui'\n * import { MessageList } from '@uix-ai/agent'\n *\n * function Chat() {\n * const processor = new AGUIEventProcessor()\n * // Feed AG-UI events from your agent backend\n * processor.processEvent(event)\n * const conversations = processor.getConversations()\n *\n * return <MessageList conversations={conversations} />\n * }\n * ```\n */\n\nimport type {\n LucidConversation,\n LucidBlock,\n ContentStatus,\n ToolStatus,\n TextBlockContent,\n ToolBlockContent,\n ThinkingBlockContent,\n} from '@uix-ai/core'\n\n// ============================================================================\n// AG-UI Protocol Event Types\n// ============================================================================\n\n/**\n * AG-UI base event interface\n */\nexport interface AGUIBaseEvent {\n type: string\n timestamp?: number\n rawEvent?: unknown\n}\n\n// -- Lifecycle Events --\n\nexport interface AGUIRunStartedEvent extends AGUIBaseEvent {\n type: 'RunStarted'\n threadId: string\n runId: string\n parentRunId?: string\n input?: unknown\n}\n\nexport interface AGUIRunFinishedEvent extends AGUIBaseEvent {\n type: 'RunFinished'\n threadId: string\n runId: string\n result?: unknown\n outcome?: 'success' | 'interrupt'\n interrupt?: unknown\n}\n\nexport interface AGUIRunErrorEvent extends AGUIBaseEvent {\n type: 'RunError'\n message: string\n code?: string\n}\n\nexport interface AGUIStepStartedEvent extends AGUIBaseEvent {\n type: 'StepStarted'\n stepName: string\n}\n\nexport interface AGUIStepFinishedEvent extends AGUIBaseEvent {\n type: 'StepFinished'\n stepName: string\n}\n\n// -- Text Message Events --\n\nexport interface AGUITextMessageStartEvent extends AGUIBaseEvent {\n type: 'TextMessageStart'\n messageId: string\n role: 'developer' | 'system' | 'assistant' | 'user' | 'tool'\n}\n\nexport interface AGUITextMessageContentEvent extends AGUIBaseEvent {\n type: 'TextMessageContent'\n messageId: string\n delta: string\n}\n\nexport interface AGUITextMessageEndEvent extends AGUIBaseEvent {\n type: 'TextMessageEnd'\n messageId: string\n}\n\n// -- Tool Call Events --\n\nexport interface AGUIToolCallStartEvent extends AGUIBaseEvent {\n type: 'ToolCallStart'\n toolCallId: string\n toolCallName: string\n parentMessageId?: string\n}\n\nexport interface AGUIToolCallArgsEvent extends AGUIBaseEvent {\n type: 'ToolCallArgs'\n toolCallId: string\n delta: string\n}\n\nexport interface AGUIToolCallEndEvent extends AGUIBaseEvent {\n type: 'ToolCallEnd'\n toolCallId: string\n}\n\nexport interface AGUIToolCallResultEvent extends AGUIBaseEvent {\n type: 'ToolCallResult'\n messageId: string\n toolCallId: string\n content: unknown\n role?: 'tool'\n}\n\n// -- State Events --\n\nexport interface AGUIStateSnapshotEvent extends AGUIBaseEvent {\n type: 'StateSnapshot'\n snapshot: Record<string, unknown>\n}\n\nexport interface AGUIStateDeltaEvent extends AGUIBaseEvent {\n type: 'StateDelta'\n delta: Array<{\n op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test'\n path: string\n value?: unknown\n from?: string\n }>\n}\n\nexport interface AGUIMessagesSnapshotEvent extends AGUIBaseEvent {\n type: 'MessagesSnapshot'\n messages: unknown[]\n}\n\n// -- Reasoning Events --\n\nexport interface AGUIReasoningMessageStartEvent extends AGUIBaseEvent {\n type: 'ReasoningMessageStart'\n messageId: string\n role: 'assistant'\n}\n\nexport interface AGUIReasoningMessageContentEvent extends AGUIBaseEvent {\n type: 'ReasoningMessageContent'\n messageId: string\n delta: string\n}\n\nexport interface AGUIReasoningMessageEndEvent extends AGUIBaseEvent {\n type: 'ReasoningMessageEnd'\n messageId: string\n}\n\n/**\n * Union of all supported AG-UI event types\n */\nexport type AGUIEvent =\n | AGUIRunStartedEvent\n | AGUIRunFinishedEvent\n | AGUIRunErrorEvent\n | AGUIStepStartedEvent\n | AGUIStepFinishedEvent\n | AGUITextMessageStartEvent\n | AGUITextMessageContentEvent\n | AGUITextMessageEndEvent\n | AGUIToolCallStartEvent\n | AGUIToolCallArgsEvent\n | AGUIToolCallEndEvent\n | AGUIToolCallResultEvent\n | AGUIStateSnapshotEvent\n | AGUIStateDeltaEvent\n | AGUIMessagesSnapshotEvent\n | AGUIReasoningMessageStartEvent\n | AGUIReasoningMessageContentEvent\n | AGUIReasoningMessageEndEvent\n | AGUIBaseEvent\n\n// ============================================================================\n// Processor Options\n// ============================================================================\n\nexport interface AGUIProcessorOptions {\n /**\n * Custom ID generator for blocks\n * @default () => `block-${Date.now()}-${counter}`\n */\n generateBlockId?: () => string\n\n /**\n * Callback when conversations are updated\n */\n onUpdate?: (conversations: LucidConversation[]) => void\n}\n\n// ============================================================================\n// Internal State Types\n// ============================================================================\n\ninterface MessageState {\n conversationId: string\n role: 'user' | 'assistant' | 'system'\n textBlockId: string | null\n textContent: string\n thinkingBlockId: string | null\n thinkingContent: string\n toolBlocks: Map<string, { blockId: string; name: string; argsJson: string }>\n status: ContentStatus\n timestamp: number\n}\n\n// ============================================================================\n// AG-UI Event Processor\n// ============================================================================\n\nlet blockIdCounter = 0\n\nfunction defaultGenerateBlockId(): string {\n return `agui-block-${Date.now()}-${++blockIdCounter}`\n}\n\n/**\n * Map AG-UI role to UIX ConversationRole\n */\nfunction mapRole(role: string): 'user' | 'assistant' | 'system' {\n switch (role) {\n case 'user':\n return 'user'\n case 'system':\n case 'developer':\n return 'system'\n case 'assistant':\n case 'tool':\n default:\n return 'assistant'\n }\n}\n\n/**\n * Stateful processor that converts AG-UI streaming events to UIX LucidConversations.\n *\n * AG-UI uses a streaming event model (start → content/delta → end) while UIX\n * uses a snapshot model (LucidConversation[]). This processor accumulates\n * events and maintains the current conversation state.\n *\n * @example\n * ```typescript\n * const processor = new AGUIEventProcessor({\n * onUpdate: (conversations) => setConversations(conversations)\n * })\n *\n * // Connect to AG-UI event source\n * eventSource.onmessage = (event) => {\n * processor.processEvent(JSON.parse(event.data))\n * }\n * ```\n */\nexport class AGUIEventProcessor {\n private messages: Map<string, MessageState> = new Map()\n private messageOrder: string[] = []\n private generateId: () => string\n private onUpdate?: (conversations: LucidConversation[]) => void\n private currentRunId: string | null = null\n\n constructor(options: AGUIProcessorOptions = {}) {\n this.generateId = options.generateBlockId ?? defaultGenerateBlockId\n this.onUpdate = options.onUpdate\n }\n\n /**\n * Process a single AG-UI event and update internal state\n */\n processEvent(event: AGUIEvent): void {\n switch (event.type) {\n case 'RunStarted':\n this.handleRunStarted(event as AGUIRunStartedEvent)\n break\n case 'RunFinished':\n this.handleRunFinished(event as AGUIRunFinishedEvent)\n break\n case 'RunError':\n this.handleRunError(event as AGUIRunErrorEvent)\n break\n case 'TextMessageStart':\n this.handleTextMessageStart(event as AGUITextMessageStartEvent)\n break\n case 'TextMessageContent':\n this.handleTextMessageContent(event as AGUITextMessageContentEvent)\n break\n case 'TextMessageEnd':\n this.handleTextMessageEnd(event as AGUITextMessageEndEvent)\n break\n case 'ToolCallStart':\n this.handleToolCallStart(event as AGUIToolCallStartEvent)\n break\n case 'ToolCallArgs':\n this.handleToolCallArgs(event as AGUIToolCallArgsEvent)\n break\n case 'ToolCallEnd':\n this.handleToolCallEnd(event as AGUIToolCallEndEvent)\n break\n case 'ToolCallResult':\n this.handleToolCallResult(event as AGUIToolCallResultEvent)\n break\n case 'ReasoningMessageStart':\n this.handleReasoningStart(event as AGUIReasoningMessageStartEvent)\n break\n case 'ReasoningMessageContent':\n this.handleReasoningContent(event as AGUIReasoningMessageContentEvent)\n break\n case 'ReasoningMessageEnd':\n this.handleReasoningEnd(event as AGUIReasoningMessageEndEvent)\n break\n default:\n // Unknown events are silently ignored\n break\n }\n\n this.onUpdate?.(this.getConversations())\n }\n\n /**\n * Process multiple AG-UI events in order\n */\n processEvents(events: AGUIEvent[]): void {\n for (const event of events) {\n this.processEvent(event)\n }\n }\n\n /**\n * Get the current state as UIX LucidConversations\n */\n getConversations(): LucidConversation[] {\n return this.messageOrder.map((msgId) => {\n const state = this.messages.get(msgId)!\n return this.buildConversation(state)\n })\n }\n\n /**\n * Reset all state\n */\n reset(): void {\n this.messages.clear()\n this.messageOrder = []\n this.currentRunId = null\n }\n\n // -- Lifecycle Handlers --\n\n private handleRunStarted(event: AGUIRunStartedEvent): void {\n this.currentRunId = event.runId\n }\n\n private handleRunFinished(_event: AGUIRunFinishedEvent): void {\n // Mark all streaming messages as completed\n for (const state of this.messages.values()) {\n if (state.status === 'streaming') {\n state.status = 'completed'\n }\n }\n this.currentRunId = null\n }\n\n private handleRunError(event: AGUIRunErrorEvent): void {\n // Find the last assistant message or create an error conversation\n const lastAssistant = this.findLastAssistantMessage()\n if (lastAssistant) {\n lastAssistant.status = 'error'\n }\n }\n\n // -- Text Message Handlers --\n\n private handleTextMessageStart(event: AGUITextMessageStartEvent): void {\n const blockId = this.generateId()\n const state: MessageState = {\n conversationId: event.messageId,\n role: mapRole(event.role),\n textBlockId: blockId,\n textContent: '',\n thinkingBlockId: null,\n thinkingContent: '',\n toolBlocks: new Map(),\n status: 'streaming',\n timestamp: event.timestamp ?? Date.now(),\n }\n this.messages.set(event.messageId, state)\n this.messageOrder.push(event.messageId)\n }\n\n private handleTextMessageContent(event: AGUITextMessageContentEvent): void {\n const state = this.messages.get(event.messageId)\n if (!state) return\n state.textContent += event.delta\n }\n\n private handleTextMessageEnd(event: AGUITextMessageEndEvent): void {\n const state = this.messages.get(event.messageId)\n if (!state) return\n state.status = 'completed'\n }\n\n // -- Tool Call Handlers --\n\n private handleToolCallStart(event: AGUIToolCallStartEvent): void {\n // Attach tool to parent message or last assistant message\n const parentId = event.parentMessageId ?? this.findLastAssistantMessageId()\n if (!parentId) return\n\n const state = this.messages.get(parentId)\n if (!state) return\n\n state.toolBlocks.set(event.toolCallId, {\n blockId: this.generateId(),\n name: event.toolCallName,\n argsJson: '',\n })\n }\n\n private handleToolCallArgs(event: AGUIToolCallArgsEvent): void {\n const tool = this.findToolBlock(event.toolCallId)\n if (!tool) return\n tool.argsJson += event.delta\n }\n\n private handleToolCallEnd(event: AGUIToolCallEndEvent): void {\n // Tool input is complete, waiting for result\n // No state change needed - tool status will update on result\n }\n\n private handleToolCallResult(event: AGUIToolCallResultEvent): void {\n const tool = this.findToolBlock(event.toolCallId)\n if (!tool) return\n // Tool result is stored in the block content output\n ;(tool as any).output = event.content\n ;(tool as any).hasResult = true\n }\n\n // -- Reasoning Handlers --\n\n private handleReasoningStart(event: AGUIReasoningMessageStartEvent): void {\n const state = this.messages.get(event.messageId)\n if (!state) return\n state.thinkingBlockId = this.generateId()\n state.thinkingContent = ''\n }\n\n private handleReasoningContent(event: AGUIReasoningMessageContentEvent): void {\n const state = this.messages.get(event.messageId)\n if (!state) return\n state.thinkingContent += event.delta\n }\n\n private handleReasoningEnd(event: AGUIReasoningMessageEndEvent): void {\n // Reasoning block is now complete, no explicit status change needed\n // as the block status is derived from conversation status\n }\n\n // -- Helpers --\n\n private findLastAssistantMessageId(): string | undefined {\n for (let i = this.messageOrder.length - 1; i >= 0; i--) {\n const id = this.messageOrder[i]\n const state = this.messages.get(id)\n if (state?.role === 'assistant') return id\n }\n return undefined\n }\n\n private findLastAssistantMessage(): MessageState | undefined {\n const id = this.findLastAssistantMessageId()\n return id ? this.messages.get(id) : undefined\n }\n\n private findToolBlock(\n toolCallId: string\n ): { blockId: string; name: string; argsJson: string; output?: unknown; hasResult?: boolean } | undefined {\n for (const state of this.messages.values()) {\n const tool = state.toolBlocks.get(toolCallId)\n if (tool) return tool as any\n }\n return undefined\n }\n\n private buildConversation(state: MessageState): LucidConversation {\n const blocks: LucidBlock[] = []\n\n // Add thinking block first (if present)\n if (state.thinkingBlockId && state.thinkingContent) {\n blocks.push({\n id: state.thinkingBlockId,\n type: 'thinking',\n status: state.status === 'streaming' ? 'streaming' : 'completed',\n content: {\n reasoning: state.thinkingContent,\n } as ThinkingBlockContent,\n })\n }\n\n // Add text block\n if (state.textBlockId && state.textContent) {\n blocks.push({\n id: state.textBlockId,\n type: 'text',\n status: state.status === 'streaming' ? 'streaming' : 'completed',\n content: {\n text: state.textContent,\n } as TextBlockContent,\n })\n }\n\n // Add tool blocks\n for (const [_toolCallId, tool] of state.toolBlocks) {\n let input: unknown = {}\n try {\n input = tool.argsJson ? JSON.parse(tool.argsJson) : {}\n } catch {\n input = tool.argsJson\n }\n\n const hasResult = (tool as any).hasResult === true\n const toolStatus: ToolStatus = hasResult ? 'success' : 'running'\n\n blocks.push({\n id: tool.blockId,\n type: 'tool',\n status: hasResult ? 'completed' : 'streaming',\n content: {\n name: tool.name,\n input,\n output: (tool as any).output,\n status: toolStatus,\n } as ToolBlockContent,\n })\n }\n\n return {\n id: state.conversationId,\n role: state.role,\n status: state.status,\n blocks,\n timestamp: state.timestamp,\n }\n }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Convert a batch of AG-UI events to UIX LucidConversations (stateless)\n *\n * For streaming use cases, prefer AGUIEventProcessor which maintains state.\n *\n * @example\n * ```typescript\n * const conversations = fromAGUIEvents(events)\n * ```\n */\nexport function fromAGUIEvents(\n events: AGUIEvent[],\n options: AGUIProcessorOptions = {}\n): LucidConversation[] {\n const processor = new AGUIEventProcessor(options)\n processor.processEvents(events)\n return processor.getConversations()\n}\n"],"mappings":";AA4OA,IAAI,iBAAiB;AAErB,SAAS,yBAAiC;AACxC,SAAO,cAAc,KAAK,IAAI,CAAC,IAAI,EAAE,cAAc;AACrD;AAKA,SAAS,QAAQ,MAA+C;AAC9D,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAqBO,IAAM,qBAAN,MAAyB;AAAA,EAO9B,YAAY,UAAgC,CAAC,GAAG;AANhD,SAAQ,WAAsC,oBAAI,IAAI;AACtD,SAAQ,eAAyB,CAAC;AAGlC,SAAQ,eAA8B;AAGpC,SAAK,aAAa,QAAQ,mBAAmB;AAC7C,SAAK,WAAW,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAwB;AACnC,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,aAAK,iBAAiB,KAA4B;AAClD;AAAA,MACF,KAAK;AACH,aAAK,kBAAkB,KAA6B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,eAAe,KAA0B;AAC9C;AAAA,MACF,KAAK;AACH,aAAK,uBAAuB,KAAkC;AAC9D;AAAA,MACF,KAAK;AACH,aAAK,yBAAyB,KAAoC;AAClE;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,KAAgC;AAC1D;AAAA,MACF,KAAK;AACH,aAAK,oBAAoB,KAA+B;AACxD;AAAA,MACF,KAAK;AACH,aAAK,mBAAmB,KAA8B;AACtD;AAAA,MACF,KAAK;AACH,aAAK,kBAAkB,KAA6B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,KAAgC;AAC1D;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,KAAuC;AACjE;AAAA,MACF,KAAK;AACH,aAAK,uBAAuB,KAAyC;AACrE;AAAA,MACF,KAAK;AACH,aAAK,mBAAmB,KAAqC;AAC7D;AAAA,MACF;AAEE;AAAA,IACJ;AAEA,SAAK,WAAW,KAAK,iBAAiB,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAA2B;AACvC,eAAW,SAAS,QAAQ;AAC1B,WAAK,aAAa,KAAK;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAwC;AACtC,WAAO,KAAK,aAAa,IAAI,CAAC,UAAU;AACtC,YAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;AACrC,aAAO,KAAK,kBAAkB,KAAK;AAAA,IACrC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS,MAAM;AACpB,SAAK,eAAe,CAAC;AACrB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA,EAIQ,iBAAiB,OAAkC;AACzD,SAAK,eAAe,MAAM;AAAA,EAC5B;AAAA,EAEQ,kBAAkB,QAAoC;AAE5D,eAAW,SAAS,KAAK,SAAS,OAAO,GAAG;AAC1C,UAAI,MAAM,WAAW,aAAa;AAChC,cAAM,SAAS;AAAA,MACjB;AAAA,IACF;AACA,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,eAAe,OAAgC;AAErD,UAAM,gBAAgB,KAAK,yBAAyB;AACpD,QAAI,eAAe;AACjB,oBAAc,SAAS;AAAA,IACzB;AAAA,EACF;AAAA;AAAA,EAIQ,uBAAuB,OAAwC;AACrE,UAAM,UAAU,KAAK,WAAW;AAChC,UAAM,QAAsB;AAAA,MAC1B,gBAAgB,MAAM;AAAA,MACtB,MAAM,QAAQ,MAAM,IAAI;AAAA,MACxB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,YAAY,oBAAI,IAAI;AAAA,MACpB,QAAQ;AAAA,MACR,WAAW,MAAM,aAAa,KAAK,IAAI;AAAA,IACzC;AACA,SAAK,SAAS,IAAI,MAAM,WAAW,KAAK;AACxC,SAAK,aAAa,KAAK,MAAM,SAAS;AAAA,EACxC;AAAA,EAEQ,yBAAyB,OAA0C;AACzE,UAAM,QAAQ,KAAK,SAAS,IAAI,MAAM,SAAS;AAC/C,QAAI,CAAC,MAAO;AACZ,UAAM,eAAe,MAAM;AAAA,EAC7B;AAAA,EAEQ,qBAAqB,OAAsC;AACjE,UAAM,QAAQ,KAAK,SAAS,IAAI,MAAM,SAAS;AAC/C,QAAI,CAAC,MAAO;AACZ,UAAM,SAAS;AAAA,EACjB;AAAA;AAAA,EAIQ,oBAAoB,OAAqC;AAE/D,UAAM,WAAW,MAAM,mBAAmB,KAAK,2BAA2B;AAC1E,QAAI,CAAC,SAAU;AAEf,UAAM,QAAQ,KAAK,SAAS,IAAI,QAAQ;AACxC,QAAI,CAAC,MAAO;AAEZ,UAAM,WAAW,IAAI,MAAM,YAAY;AAAA,MACrC,SAAS,KAAK,WAAW;AAAA,MACzB,MAAM,MAAM;AAAA,MACZ,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEQ,mBAAmB,OAAoC;AAC7D,UAAM,OAAO,KAAK,cAAc,MAAM,UAAU;AAChD,QAAI,CAAC,KAAM;AACX,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA,EAEQ,kBAAkB,OAAmC;AAAA,EAG7D;AAAA,EAEQ,qBAAqB,OAAsC;AACjE,UAAM,OAAO,KAAK,cAAc,MAAM,UAAU;AAChD,QAAI,CAAC,KAAM;AAEV,IAAC,KAAa,SAAS,MAAM;AAC7B,IAAC,KAAa,YAAY;AAAA,EAC7B;AAAA;AAAA,EAIQ,qBAAqB,OAA6C;AACxE,UAAM,QAAQ,KAAK,SAAS,IAAI,MAAM,SAAS;AAC/C,QAAI,CAAC,MAAO;AACZ,UAAM,kBAAkB,KAAK,WAAW;AACxC,UAAM,kBAAkB;AAAA,EAC1B;AAAA,EAEQ,uBAAuB,OAA+C;AAC5E,UAAM,QAAQ,KAAK,SAAS,IAAI,MAAM,SAAS;AAC/C,QAAI,CAAC,MAAO;AACZ,UAAM,mBAAmB,MAAM;AAAA,EACjC;AAAA,EAEQ,mBAAmB,OAA2C;AAAA,EAGtE;AAAA;AAAA,EAIQ,6BAAiD;AACvD,aAAS,IAAI,KAAK,aAAa,SAAS,GAAG,KAAK,GAAG,KAAK;AACtD,YAAM,KAAK,KAAK,aAAa,CAAC;AAC9B,YAAM,QAAQ,KAAK,SAAS,IAAI,EAAE;AAClC,UAAI,OAAO,SAAS,YAAa,QAAO;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,2BAAqD;AAC3D,UAAM,KAAK,KAAK,2BAA2B;AAC3C,WAAO,KAAK,KAAK,SAAS,IAAI,EAAE,IAAI;AAAA,EACtC;AAAA,EAEQ,cACN,YACwG;AACxG,eAAW,SAAS,KAAK,SAAS,OAAO,GAAG;AAC1C,YAAM,OAAO,MAAM,WAAW,IAAI,UAAU;AAC5C,UAAI,KAAM,QAAO;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,OAAwC;AAChE,UAAM,SAAuB,CAAC;AAG9B,QAAI,MAAM,mBAAmB,MAAM,iBAAiB;AAClD,aAAO,KAAK;AAAA,QACV,IAAI,MAAM;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,MAAM,WAAW,cAAc,cAAc;AAAA,QACrD,SAAS;AAAA,UACP,WAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,MAAM,eAAe,MAAM,aAAa;AAC1C,aAAO,KAAK;AAAA,QACV,IAAI,MAAM;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,MAAM,WAAW,cAAc,cAAc;AAAA,QACrD,SAAS;AAAA,UACP,MAAM,MAAM;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACH;AAGA,eAAW,CAAC,aAAa,IAAI,KAAK,MAAM,YAAY;AAClD,UAAI,QAAiB,CAAC;AACtB,UAAI;AACF,gBAAQ,KAAK,WAAW,KAAK,MAAM,KAAK,QAAQ,IAAI,CAAC;AAAA,MACvD,QAAQ;AACN,gBAAQ,KAAK;AAAA,MACf;AAEA,YAAM,YAAa,KAAa,cAAc;AAC9C,YAAM,aAAyB,YAAY,YAAY;AAEvD,aAAO,KAAK;AAAA,QACV,IAAI,KAAK;AAAA,QACT,MAAM;AAAA,QACN,QAAQ,YAAY,cAAc;AAAA,QAClC,SAAS;AAAA,UACP,MAAM,KAAK;AAAA,UACX;AAAA,UACA,QAAS,KAAa;AAAA,UACtB,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd;AAAA,MACA,WAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACF;AAgBO,SAAS,eACd,QACA,UAAgC,CAAC,GACZ;AACrB,QAAM,YAAY,IAAI,mBAAmB,OAAO;AAChD,YAAU,cAAc,MAAM;AAC9B,SAAO,UAAU,iBAAiB;AACpC;","names":[]}
@@ -0,0 +1,222 @@
1
+ import { LucidConversation } from '@uix-ai/core';
2
+
3
+ /**
4
+ * @uix-ai/adapter-agui
5
+ *
6
+ * Adapter to convert AG-UI protocol events to UIX Lucid IR format.
7
+ *
8
+ * AG-UI (Agent-User Interaction Protocol) is an open, event-based protocol
9
+ * that standardizes how AI agent backends connect to frontend applications.
10
+ *
11
+ * This adapter converts AG-UI's streaming events into UIX LucidConversation
12
+ * and LucidBlock structures for rendering with UIX components.
13
+ *
14
+ * @see https://docs.ag-ui.com
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { AGUIEventProcessor } from '@uix-ai/adapter-agui'
19
+ * import { MessageList } from '@uix-ai/agent'
20
+ *
21
+ * function Chat() {
22
+ * const processor = new AGUIEventProcessor()
23
+ * // Feed AG-UI events from your agent backend
24
+ * processor.processEvent(event)
25
+ * const conversations = processor.getConversations()
26
+ *
27
+ * return <MessageList conversations={conversations} />
28
+ * }
29
+ * ```
30
+ */
31
+
32
+ /**
33
+ * AG-UI base event interface
34
+ */
35
+ interface AGUIBaseEvent {
36
+ type: string;
37
+ timestamp?: number;
38
+ rawEvent?: unknown;
39
+ }
40
+ interface AGUIRunStartedEvent extends AGUIBaseEvent {
41
+ type: 'RunStarted';
42
+ threadId: string;
43
+ runId: string;
44
+ parentRunId?: string;
45
+ input?: unknown;
46
+ }
47
+ interface AGUIRunFinishedEvent extends AGUIBaseEvent {
48
+ type: 'RunFinished';
49
+ threadId: string;
50
+ runId: string;
51
+ result?: unknown;
52
+ outcome?: 'success' | 'interrupt';
53
+ interrupt?: unknown;
54
+ }
55
+ interface AGUIRunErrorEvent extends AGUIBaseEvent {
56
+ type: 'RunError';
57
+ message: string;
58
+ code?: string;
59
+ }
60
+ interface AGUIStepStartedEvent extends AGUIBaseEvent {
61
+ type: 'StepStarted';
62
+ stepName: string;
63
+ }
64
+ interface AGUIStepFinishedEvent extends AGUIBaseEvent {
65
+ type: 'StepFinished';
66
+ stepName: string;
67
+ }
68
+ interface AGUITextMessageStartEvent extends AGUIBaseEvent {
69
+ type: 'TextMessageStart';
70
+ messageId: string;
71
+ role: 'developer' | 'system' | 'assistant' | 'user' | 'tool';
72
+ }
73
+ interface AGUITextMessageContentEvent extends AGUIBaseEvent {
74
+ type: 'TextMessageContent';
75
+ messageId: string;
76
+ delta: string;
77
+ }
78
+ interface AGUITextMessageEndEvent extends AGUIBaseEvent {
79
+ type: 'TextMessageEnd';
80
+ messageId: string;
81
+ }
82
+ interface AGUIToolCallStartEvent extends AGUIBaseEvent {
83
+ type: 'ToolCallStart';
84
+ toolCallId: string;
85
+ toolCallName: string;
86
+ parentMessageId?: string;
87
+ }
88
+ interface AGUIToolCallArgsEvent extends AGUIBaseEvent {
89
+ type: 'ToolCallArgs';
90
+ toolCallId: string;
91
+ delta: string;
92
+ }
93
+ interface AGUIToolCallEndEvent extends AGUIBaseEvent {
94
+ type: 'ToolCallEnd';
95
+ toolCallId: string;
96
+ }
97
+ interface AGUIToolCallResultEvent extends AGUIBaseEvent {
98
+ type: 'ToolCallResult';
99
+ messageId: string;
100
+ toolCallId: string;
101
+ content: unknown;
102
+ role?: 'tool';
103
+ }
104
+ interface AGUIStateSnapshotEvent extends AGUIBaseEvent {
105
+ type: 'StateSnapshot';
106
+ snapshot: Record<string, unknown>;
107
+ }
108
+ interface AGUIStateDeltaEvent extends AGUIBaseEvent {
109
+ type: 'StateDelta';
110
+ delta: Array<{
111
+ op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';
112
+ path: string;
113
+ value?: unknown;
114
+ from?: string;
115
+ }>;
116
+ }
117
+ interface AGUIMessagesSnapshotEvent extends AGUIBaseEvent {
118
+ type: 'MessagesSnapshot';
119
+ messages: unknown[];
120
+ }
121
+ interface AGUIReasoningMessageStartEvent extends AGUIBaseEvent {
122
+ type: 'ReasoningMessageStart';
123
+ messageId: string;
124
+ role: 'assistant';
125
+ }
126
+ interface AGUIReasoningMessageContentEvent extends AGUIBaseEvent {
127
+ type: 'ReasoningMessageContent';
128
+ messageId: string;
129
+ delta: string;
130
+ }
131
+ interface AGUIReasoningMessageEndEvent extends AGUIBaseEvent {
132
+ type: 'ReasoningMessageEnd';
133
+ messageId: string;
134
+ }
135
+ /**
136
+ * Union of all supported AG-UI event types
137
+ */
138
+ type AGUIEvent = AGUIRunStartedEvent | AGUIRunFinishedEvent | AGUIRunErrorEvent | AGUIStepStartedEvent | AGUIStepFinishedEvent | AGUITextMessageStartEvent | AGUITextMessageContentEvent | AGUITextMessageEndEvent | AGUIToolCallStartEvent | AGUIToolCallArgsEvent | AGUIToolCallEndEvent | AGUIToolCallResultEvent | AGUIStateSnapshotEvent | AGUIStateDeltaEvent | AGUIMessagesSnapshotEvent | AGUIReasoningMessageStartEvent | AGUIReasoningMessageContentEvent | AGUIReasoningMessageEndEvent | AGUIBaseEvent;
139
+ interface AGUIProcessorOptions {
140
+ /**
141
+ * Custom ID generator for blocks
142
+ * @default () => `block-${Date.now()}-${counter}`
143
+ */
144
+ generateBlockId?: () => string;
145
+ /**
146
+ * Callback when conversations are updated
147
+ */
148
+ onUpdate?: (conversations: LucidConversation[]) => void;
149
+ }
150
+ /**
151
+ * Stateful processor that converts AG-UI streaming events to UIX LucidConversations.
152
+ *
153
+ * AG-UI uses a streaming event model (start → content/delta → end) while UIX
154
+ * uses a snapshot model (LucidConversation[]). This processor accumulates
155
+ * events and maintains the current conversation state.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const processor = new AGUIEventProcessor({
160
+ * onUpdate: (conversations) => setConversations(conversations)
161
+ * })
162
+ *
163
+ * // Connect to AG-UI event source
164
+ * eventSource.onmessage = (event) => {
165
+ * processor.processEvent(JSON.parse(event.data))
166
+ * }
167
+ * ```
168
+ */
169
+ declare class AGUIEventProcessor {
170
+ private messages;
171
+ private messageOrder;
172
+ private generateId;
173
+ private onUpdate?;
174
+ private currentRunId;
175
+ constructor(options?: AGUIProcessorOptions);
176
+ /**
177
+ * Process a single AG-UI event and update internal state
178
+ */
179
+ processEvent(event: AGUIEvent): void;
180
+ /**
181
+ * Process multiple AG-UI events in order
182
+ */
183
+ processEvents(events: AGUIEvent[]): void;
184
+ /**
185
+ * Get the current state as UIX LucidConversations
186
+ */
187
+ getConversations(): LucidConversation[];
188
+ /**
189
+ * Reset all state
190
+ */
191
+ reset(): void;
192
+ private handleRunStarted;
193
+ private handleRunFinished;
194
+ private handleRunError;
195
+ private handleTextMessageStart;
196
+ private handleTextMessageContent;
197
+ private handleTextMessageEnd;
198
+ private handleToolCallStart;
199
+ private handleToolCallArgs;
200
+ private handleToolCallEnd;
201
+ private handleToolCallResult;
202
+ private handleReasoningStart;
203
+ private handleReasoningContent;
204
+ private handleReasoningEnd;
205
+ private findLastAssistantMessageId;
206
+ private findLastAssistantMessage;
207
+ private findToolBlock;
208
+ private buildConversation;
209
+ }
210
+ /**
211
+ * Convert a batch of AG-UI events to UIX LucidConversations (stateless)
212
+ *
213
+ * For streaming use cases, prefer AGUIEventProcessor which maintains state.
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const conversations = fromAGUIEvents(events)
218
+ * ```
219
+ */
220
+ declare function fromAGUIEvents(events: AGUIEvent[], options?: AGUIProcessorOptions): LucidConversation[];
221
+
222
+ export { type AGUIBaseEvent, type AGUIEvent, AGUIEventProcessor, type AGUIMessagesSnapshotEvent, type AGUIProcessorOptions, type AGUIReasoningMessageContentEvent, type AGUIReasoningMessageEndEvent, type AGUIReasoningMessageStartEvent, type AGUIRunErrorEvent, type AGUIRunFinishedEvent, type AGUIRunStartedEvent, type AGUIStateDeltaEvent, type AGUIStateSnapshotEvent, type AGUIStepFinishedEvent, type AGUIStepStartedEvent, type AGUITextMessageContentEvent, type AGUITextMessageEndEvent, type AGUITextMessageStartEvent, type AGUIToolCallArgsEvent, type AGUIToolCallEndEvent, type AGUIToolCallResultEvent, type AGUIToolCallStartEvent, fromAGUIEvents };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ AGUIEventProcessor,
3
+ fromAGUIEvents
4
+ } from "./chunk-MI5X6OBV.js";
5
+ export {
6
+ AGUIEventProcessor,
7
+ fromAGUIEvents
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,106 @@
1
+ import { AGUIProcessorOptions } from '../index.js';
2
+ import { LucidConversation } from '@uix-ai/core';
3
+
4
+ /**
5
+ * @uix-ai/adapter-agui/react
6
+ *
7
+ * React hooks for connecting to AG-UI protocol agent backends
8
+ * and rendering with UIX components.
9
+ *
10
+ * @example 3 lines to a full chat UI
11
+ * ```tsx
12
+ * import { AgentChat } from '@uix-ai/agent'
13
+ * import { useAGUI } from '@uix-ai/adapter-agui/react'
14
+ *
15
+ * function App() {
16
+ * const { conversations, status, send } = useAGUI({ url: '/api/agent' })
17
+ * return <AgentChat conversations={conversations} status={status} onSend={send} />
18
+ * }
19
+ * ```
20
+ */
21
+
22
+ interface UseAGUIOptions {
23
+ /**
24
+ * AG-UI agent endpoint URL.
25
+ * The hook will connect via SSE (Server-Sent Events).
26
+ */
27
+ url: string;
28
+ /**
29
+ * Thread ID for conversation continuity.
30
+ * @default auto-generated
31
+ */
32
+ threadId?: string;
33
+ /**
34
+ * Custom headers for the SSE connection.
35
+ */
36
+ headers?: Record<string, string>;
37
+ /**
38
+ * AG-UI event processor options.
39
+ */
40
+ processorOptions?: AGUIProcessorOptions;
41
+ /**
42
+ * Auto-connect on mount.
43
+ * @default false
44
+ */
45
+ autoConnect?: boolean;
46
+ /**
47
+ * Callback when an error occurs.
48
+ */
49
+ onError?: (error: Error) => void;
50
+ /**
51
+ * Callback when the run finishes.
52
+ */
53
+ onFinish?: () => void;
54
+ }
55
+ interface UseAGUIReturn {
56
+ /** UIX LucidConversation array, ready for <AgentChat> */
57
+ conversations: LucidConversation[];
58
+ /** Chat status mapped to ChatWindowStatus */
59
+ status: 'idle' | 'loading' | 'streaming' | 'error';
60
+ /** Send a user message to the agent */
61
+ send: (message: string) => void;
62
+ /** Stop the current stream */
63
+ stop: () => void;
64
+ /** Whether the agent is currently responding */
65
+ isLoading: boolean;
66
+ /** Reset the conversation */
67
+ reset: () => void;
68
+ /** Error if any */
69
+ error: Error | null;
70
+ }
71
+ /**
72
+ * Connect to an AG-UI protocol agent backend and get UIX-ready conversations.
73
+ *
74
+ * Handles SSE connection, event processing, and state management.
75
+ * Returns data directly compatible with <AgentChat>.
76
+ *
77
+ * @example Basic usage
78
+ * ```tsx
79
+ * function Chat() {
80
+ * const { conversations, status, send, stop } = useAGUI({
81
+ * url: 'https://my-agent.com/api/ag-ui',
82
+ * })
83
+ *
84
+ * return (
85
+ * <AgentChat
86
+ * conversations={conversations}
87
+ * status={status}
88
+ * onSend={send}
89
+ * onStop={stop}
90
+ * />
91
+ * )
92
+ * }
93
+ * ```
94
+ *
95
+ * @example With thread persistence
96
+ * ```tsx
97
+ * const { conversations, send } = useAGUI({
98
+ * url: '/api/agent',
99
+ * threadId: 'thread-abc-123',
100
+ * headers: { Authorization: 'Bearer ...' },
101
+ * })
102
+ * ```
103
+ */
104
+ declare function useAGUI(options: UseAGUIOptions): UseAGUIReturn;
105
+
106
+ export { type UseAGUIOptions, type UseAGUIReturn, useAGUI };
@@ -0,0 +1,130 @@
1
+ import {
2
+ AGUIEventProcessor
3
+ } from "../chunk-MI5X6OBV.js";
4
+
5
+ // src/react/index.ts
6
+ import { useState, useCallback, useRef, useEffect } from "react";
7
+ function useAGUI(options) {
8
+ const { url, threadId, headers, processorOptions, onError, onFinish } = options;
9
+ const [conversations, setConversations] = useState([]);
10
+ const [status, setStatus] = useState("idle");
11
+ const [error, setError] = useState(null);
12
+ const processorRef = useRef(
13
+ new AGUIEventProcessor({
14
+ ...processorOptions,
15
+ onUpdate: (convs) => setConversations([...convs])
16
+ })
17
+ );
18
+ const abortRef = useRef(null);
19
+ const threadIdRef = useRef(threadId ?? `thread-${Date.now()}`);
20
+ useEffect(() => {
21
+ return () => {
22
+ abortRef.current?.abort();
23
+ };
24
+ }, []);
25
+ const send = useCallback(
26
+ async (message) => {
27
+ abortRef.current?.abort();
28
+ const controller = new AbortController();
29
+ abortRef.current = controller;
30
+ setStatus("loading");
31
+ setError(null);
32
+ const userConv = {
33
+ id: `user-${Date.now()}`,
34
+ role: "user",
35
+ status: "completed",
36
+ blocks: [
37
+ {
38
+ id: `block-${Date.now()}`,
39
+ type: "text",
40
+ status: "completed",
41
+ content: { text: message }
42
+ }
43
+ ],
44
+ timestamp: Date.now()
45
+ };
46
+ setConversations((prev) => [...prev, userConv]);
47
+ try {
48
+ const requestHeaders = {
49
+ "Content-Type": "application/json",
50
+ Accept: "text/event-stream",
51
+ ...headers
52
+ };
53
+ const response = await fetch(url, {
54
+ method: "POST",
55
+ headers: requestHeaders,
56
+ body: JSON.stringify({
57
+ threadId: threadIdRef.current,
58
+ message
59
+ }),
60
+ signal: controller.signal
61
+ });
62
+ if (!response.ok) {
63
+ throw new Error(`AG-UI request failed: ${response.status} ${response.statusText}`);
64
+ }
65
+ if (!response.body) {
66
+ throw new Error("No response body for SSE stream");
67
+ }
68
+ setStatus("streaming");
69
+ const reader = response.body.getReader();
70
+ const decoder = new TextDecoder();
71
+ let buffer = "";
72
+ while (true) {
73
+ const { done, value } = await reader.read();
74
+ if (done) break;
75
+ buffer += decoder.decode(value, { stream: true });
76
+ const lines = buffer.split("\n");
77
+ buffer = lines.pop() ?? "";
78
+ for (const line of lines) {
79
+ if (line.startsWith("data: ")) {
80
+ const data = line.slice(6).trim();
81
+ if (data === "[DONE]") continue;
82
+ try {
83
+ const event = JSON.parse(data);
84
+ processorRef.current.processEvent(event);
85
+ } catch {
86
+ }
87
+ }
88
+ }
89
+ }
90
+ setStatus("idle");
91
+ onFinish?.();
92
+ } catch (err) {
93
+ if (err.name === "AbortError") {
94
+ setStatus("idle");
95
+ return;
96
+ }
97
+ const error2 = err instanceof Error ? err : new Error(String(err));
98
+ setError(error2);
99
+ setStatus("error");
100
+ onError?.(error2);
101
+ }
102
+ },
103
+ [url, headers, onError, onFinish]
104
+ );
105
+ const stop = useCallback(() => {
106
+ abortRef.current?.abort();
107
+ setStatus("idle");
108
+ }, []);
109
+ const reset = useCallback(() => {
110
+ abortRef.current?.abort();
111
+ processorRef.current.reset();
112
+ setConversations([]);
113
+ setStatus("idle");
114
+ setError(null);
115
+ threadIdRef.current = `thread-${Date.now()}`;
116
+ }, []);
117
+ return {
118
+ conversations,
119
+ status,
120
+ send,
121
+ stop,
122
+ isLoading: status === "loading" || status === "streaming",
123
+ reset,
124
+ error
125
+ };
126
+ }
127
+ export {
128
+ useAGUI
129
+ };
130
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.ts"],"sourcesContent":["/**\n * @uix-ai/adapter-agui/react\n *\n * React hooks for connecting to AG-UI protocol agent backends\n * and rendering with UIX components.\n *\n * @example 3 lines to a full chat UI\n * ```tsx\n * import { AgentChat } from '@uix-ai/agent'\n * import { useAGUI } from '@uix-ai/adapter-agui/react'\n *\n * function App() {\n * const { conversations, status, send } = useAGUI({ url: '/api/agent' })\n * return <AgentChat conversations={conversations} status={status} onSend={send} />\n * }\n * ```\n */\n\nimport { useState, useCallback, useRef, useEffect } from 'react'\nimport { AGUIEventProcessor } from '../index'\nimport type { AGUIEvent, AGUIProcessorOptions } from '../index'\nimport type { LucidConversation } from '@uix-ai/core'\n\n// ============================================================================\n// useAGUI - Connect to AG-UI agent backend\n// ============================================================================\n\nexport interface UseAGUIOptions {\n /**\n * AG-UI agent endpoint URL.\n * The hook will connect via SSE (Server-Sent Events).\n */\n url: string\n\n /**\n * Thread ID for conversation continuity.\n * @default auto-generated\n */\n threadId?: string\n\n /**\n * Custom headers for the SSE connection.\n */\n headers?: Record<string, string>\n\n /**\n * AG-UI event processor options.\n */\n processorOptions?: AGUIProcessorOptions\n\n /**\n * Auto-connect on mount.\n * @default false\n */\n autoConnect?: boolean\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void\n\n /**\n * Callback when the run finishes.\n */\n onFinish?: () => void\n}\n\nexport interface UseAGUIReturn {\n /** UIX LucidConversation array, ready for <AgentChat> */\n conversations: LucidConversation[]\n /** Chat status mapped to ChatWindowStatus */\n status: 'idle' | 'loading' | 'streaming' | 'error'\n /** Send a user message to the agent */\n send: (message: string) => void\n /** Stop the current stream */\n stop: () => void\n /** Whether the agent is currently responding */\n isLoading: boolean\n /** Reset the conversation */\n reset: () => void\n /** Error if any */\n error: Error | null\n}\n\n/**\n * Connect to an AG-UI protocol agent backend and get UIX-ready conversations.\n *\n * Handles SSE connection, event processing, and state management.\n * Returns data directly compatible with <AgentChat>.\n *\n * @example Basic usage\n * ```tsx\n * function Chat() {\n * const { conversations, status, send, stop } = useAGUI({\n * url: 'https://my-agent.com/api/ag-ui',\n * })\n *\n * return (\n * <AgentChat\n * conversations={conversations}\n * status={status}\n * onSend={send}\n * onStop={stop}\n * />\n * )\n * }\n * ```\n *\n * @example With thread persistence\n * ```tsx\n * const { conversations, send } = useAGUI({\n * url: '/api/agent',\n * threadId: 'thread-abc-123',\n * headers: { Authorization: 'Bearer ...' },\n * })\n * ```\n */\nexport function useAGUI(options: UseAGUIOptions): UseAGUIReturn {\n const { url, threadId, headers, processorOptions, onError, onFinish } = options\n\n const [conversations, setConversations] = useState<LucidConversation[]>([])\n const [status, setStatus] = useState<'idle' | 'loading' | 'streaming' | 'error'>('idle')\n const [error, setError] = useState<Error | null>(null)\n\n const processorRef = useRef<AGUIEventProcessor>(\n new AGUIEventProcessor({\n ...processorOptions,\n onUpdate: (convs) => setConversations([...convs]),\n })\n )\n const abortRef = useRef<AbortController | null>(null)\n const threadIdRef = useRef(threadId ?? `thread-${Date.now()}`)\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n abortRef.current?.abort()\n }\n }, [])\n\n const send = useCallback(\n async (message: string) => {\n // Abort any existing connection\n abortRef.current?.abort()\n\n const controller = new AbortController()\n abortRef.current = controller\n\n setStatus('loading')\n setError(null)\n\n // Add user message to conversations immediately\n const userConv: LucidConversation = {\n id: `user-${Date.now()}`,\n role: 'user',\n status: 'completed',\n blocks: [\n {\n id: `block-${Date.now()}`,\n type: 'text',\n status: 'completed',\n content: { text: message },\n },\n ],\n timestamp: Date.now(),\n }\n setConversations((prev) => [...prev, userConv])\n\n try {\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: requestHeaders,\n body: JSON.stringify({\n threadId: threadIdRef.current,\n message,\n }),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n throw new Error(`AG-UI request failed: ${response.status} ${response.statusText}`)\n }\n\n if (!response.body) {\n throw new Error('No response body for SSE stream')\n }\n\n setStatus('streaming')\n\n // Parse SSE stream\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event: AGUIEvent = JSON.parse(data)\n processorRef.current.processEvent(event)\n } catch {\n // Skip malformed events\n }\n }\n }\n }\n\n setStatus('idle')\n onFinish?.()\n } catch (err) {\n if ((err as Error).name === 'AbortError') {\n setStatus('idle')\n return\n }\n\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n setStatus('error')\n onError?.(error)\n }\n },\n [url, headers, onError, onFinish]\n )\n\n const stop = useCallback(() => {\n abortRef.current?.abort()\n setStatus('idle')\n }, [])\n\n const reset = useCallback(() => {\n abortRef.current?.abort()\n processorRef.current.reset()\n setConversations([])\n setStatus('idle')\n setError(null)\n threadIdRef.current = `thread-${Date.now()}`\n }, [])\n\n return {\n conversations,\n status,\n send,\n stop,\n isLoading: status === 'loading' || status === 'streaming',\n reset,\n error,\n }\n}\n"],"mappings":"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","names":["error"]}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@uix-ai/adapter-agui",
3
+ "version": "0.0.1",
4
+ "description": "Adapter to convert AG-UI protocol events to UIX Lucid IR format",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/react/index.d.ts",
16
+ "import": "./dist/react/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "test": "vitest run",
26
+ "clean": "rm -rf dist"
27
+ },
28
+ "dependencies": {
29
+ "@uix-ai/core": "workspace:*"
30
+ },
31
+ "peerDependencies": {
32
+ "@ag-ui/core": ">=0.0.1",
33
+ "react": "^18.0.0 || ^19.0.0"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "@ag-ui/core": {
37
+ "optional": true
38
+ },
39
+ "react": {
40
+ "optional": true
41
+ }
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^19.2.14",
45
+ "tsup": "^8.0.0",
46
+ "typescript": "^5.3.0",
47
+ "vitest": "^3.2.4"
48
+ },
49
+ "keywords": [
50
+ "uix",
51
+ "ag-ui",
52
+ "agent-ui",
53
+ "adapter",
54
+ "protocol",
55
+ "converter"
56
+ ],
57
+ "license": "MIT",
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "https://github.com/Deepractice/UIX.git",
61
+ "directory": "packages/adapter-agui"
62
+ }
63
+ }