@olane/o-lane 0.7.12-alpha.74 → 0.7.12-alpha.76
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/dist/src/ag-ui/ag-ui-constants.d.ts +90 -0
- package/dist/src/ag-ui/ag-ui-constants.d.ts.map +1 -0
- package/dist/src/ag-ui/ag-ui-constants.js +113 -0
- package/dist/src/ag-ui/ag-ui-event-mapper.d.ts +88 -0
- package/dist/src/ag-ui/ag-ui-event-mapper.d.ts.map +1 -0
- package/dist/src/ag-ui/ag-ui-event-mapper.js +487 -0
- package/dist/src/ag-ui/ag-ui-olane.tool.d.ts +45 -0
- package/dist/src/ag-ui/ag-ui-olane.tool.d.ts.map +1 -0
- package/dist/src/ag-ui/ag-ui-olane.tool.js +257 -0
- package/dist/src/ag-ui/ag-ui-stream-manager.d.ts +99 -0
- package/dist/src/ag-ui/ag-ui-stream-manager.d.ts.map +1 -0
- package/dist/src/ag-ui/ag-ui-stream-manager.js +160 -0
- package/dist/src/ag-ui/ag-ui-utils.d.ts +50 -0
- package/dist/src/ag-ui/ag-ui-utils.d.ts.map +1 -0
- package/dist/src/ag-ui/ag-ui-utils.js +287 -0
- package/dist/src/ag-ui/index.d.ts +17 -0
- package/dist/src/ag-ui/index.d.ts.map +1 -0
- package/dist/src/ag-ui/index.js +21 -0
- package/dist/src/ag-ui/transports/ag-ui-transport.interface.d.ts +44 -0
- package/dist/src/ag-ui/transports/ag-ui-transport.interface.d.ts.map +1 -0
- package/dist/src/ag-ui/transports/ag-ui-transport.interface.js +26 -0
- package/dist/src/ag-ui/transports/callback-transport.d.ts +13 -0
- package/dist/src/ag-ui/transports/callback-transport.d.ts.map +1 -0
- package/dist/src/ag-ui/transports/callback-transport.js +26 -0
- package/dist/src/ag-ui/transports/console-transport.d.ts +14 -0
- package/dist/src/ag-ui/transports/console-transport.d.ts.map +1 -0
- package/dist/src/ag-ui/transports/console-transport.js +63 -0
- package/dist/src/ag-ui/transports/index.d.ts +5 -0
- package/dist/src/ag-ui/transports/index.d.ts.map +1 -0
- package/dist/src/ag-ui/transports/index.js +4 -0
- package/dist/src/ag-ui/transports/onode-transport.d.ts +34 -0
- package/dist/src/ag-ui/transports/onode-transport.d.ts.map +1 -0
- package/dist/src/ag-ui/transports/onode-transport.js +83 -0
- package/dist/src/ag-ui/types/ag-ui-config.interface.d.ts +105 -0
- package/dist/src/ag-ui/types/ag-ui-config.interface.d.ts.map +1 -0
- package/dist/src/ag-ui/types/ag-ui-config.interface.js +1 -0
- package/dist/src/ag-ui/types/ag-ui-event.types.d.ts +266 -0
- package/dist/src/ag-ui/types/ag-ui-event.types.d.ts.map +1 -0
- package/dist/src/ag-ui/types/ag-ui-event.types.js +6 -0
- package/dist/src/ag-ui/types/index.d.ts +3 -0
- package/dist/src/ag-ui/types/index.d.ts.map +1 -0
- package/dist/src/ag-ui/types/index.js +2 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/package.json +7 -7
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { oLaneTool } from '../o-lane.tool.js';
|
|
2
|
+
import { AGUIEventMapper } from './ag-ui-event-mapper.js';
|
|
3
|
+
import { AGUIStreamManager } from './ag-ui-stream-manager.js';
|
|
4
|
+
import { ONodeAGUITransport } from './transports/onode-transport.js';
|
|
5
|
+
import { ConsoleAGUITransport } from './transports/console-transport.js';
|
|
6
|
+
import { oIntent } from '../intent/o-intent.js';
|
|
7
|
+
import { oLaneContext } from '../o-lane.context.js';
|
|
8
|
+
import { oCapabilityType } from '../capabilities/enums/o-capability.type-enum.js';
|
|
9
|
+
import { oAddress } from '@olane/o-core';
|
|
10
|
+
import { generateRunId, generateThreadId, generateTimestamp, } from './ag-ui-utils.js';
|
|
11
|
+
import { AG_UI_DEFAULTS } from './ag-ui-constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* AG-UI compatible oLane Tool
|
|
14
|
+
* Extends oLaneTool with AG-UI event streaming capabilities
|
|
15
|
+
*/
|
|
16
|
+
export class AGUIoLaneTool extends oLaneTool {
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super(config);
|
|
19
|
+
this.agUIConfig = {
|
|
20
|
+
...config,
|
|
21
|
+
enableAGUI: config.enableAGUI ?? AG_UI_DEFAULTS.AGUI_ENABLED,
|
|
22
|
+
debugAGUI: config.debugAGUI ?? AG_UI_DEFAULTS.DEBUG_ENABLED,
|
|
23
|
+
stateSnapshotInterval: config.stateSnapshotInterval ?? AG_UI_DEFAULTS.STATE_SNAPSHOT_INTERVAL,
|
|
24
|
+
maxDeltaHistory: config.maxDeltaHistory ?? AG_UI_DEFAULTS.MAX_DELTA_HISTORY,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* AG-UI compatible intent method with full event streaming
|
|
29
|
+
* This is the main entry point for AG-UI enabled intent resolution
|
|
30
|
+
*/
|
|
31
|
+
async _tool_ag_ui_intent(request) {
|
|
32
|
+
const { intent, context, threadId: providedThreadId, _isStreaming = false, } = request.params;
|
|
33
|
+
this.logger.debug('AG-UI intent received:', request.params);
|
|
34
|
+
// Generate IDs
|
|
35
|
+
const runId = generateRunId();
|
|
36
|
+
const threadId = providedThreadId || generateThreadId(context);
|
|
37
|
+
// Create AG-UI event context
|
|
38
|
+
const eventContext = {
|
|
39
|
+
threadId,
|
|
40
|
+
runId,
|
|
41
|
+
parentRunId: undefined,
|
|
42
|
+
cycleToMessageId: new Map(),
|
|
43
|
+
taskToToolCallId: new Map(),
|
|
44
|
+
};
|
|
45
|
+
// Create event mapper
|
|
46
|
+
const eventMapper = new AGUIEventMapper(eventContext, {
|
|
47
|
+
emitActivityEvents: this.agUIConfig.debugAGUI,
|
|
48
|
+
emitReasoningEvents: true,
|
|
49
|
+
textChunkSize: AG_UI_DEFAULTS.TEXT_CHUNK_SIZE,
|
|
50
|
+
});
|
|
51
|
+
// Create transport
|
|
52
|
+
const transport = this.agUIConfig.agUITransport || this.createDefaultTransport(request);
|
|
53
|
+
// Create stream manager
|
|
54
|
+
const streamManager = new AGUIStreamManager({
|
|
55
|
+
transport,
|
|
56
|
+
debug: this.agUIConfig.debugAGUI,
|
|
57
|
+
eventFilter: this.agUIConfig.eventFilter,
|
|
58
|
+
validateEvents: true,
|
|
59
|
+
});
|
|
60
|
+
try {
|
|
61
|
+
// Emit RunStarted
|
|
62
|
+
await streamManager.emit(eventMapper.mapLaneStartToRunStarted(new oIntent({ intent: intent }), { intent, context }));
|
|
63
|
+
// Emit preflight step
|
|
64
|
+
await streamManager.emit(eventMapper.mapCapabilityStartToStepStarted(oCapabilityType.UNKNOWN));
|
|
65
|
+
// Create lane with AG-UI event emission hooks
|
|
66
|
+
let previousSequence = [];
|
|
67
|
+
let cycleNumber = 0;
|
|
68
|
+
const lane = await this.manager.createLane({
|
|
69
|
+
intent: new oIntent({ intent: intent }),
|
|
70
|
+
currentNode: this,
|
|
71
|
+
caller: this.address,
|
|
72
|
+
useStream: _isStreaming,
|
|
73
|
+
requestId: request.id,
|
|
74
|
+
onChunk: async (chunk) => {
|
|
75
|
+
console.log('Chunk received:', chunk);
|
|
76
|
+
// Emit chunk as activity event for real-time progress
|
|
77
|
+
// Note: This fires AFTER addSequence has emitted full capability events,
|
|
78
|
+
// so ActivitySnapshot provides a complementary progress update
|
|
79
|
+
try {
|
|
80
|
+
const activityEvent = eventMapper.mapChunkToActivity(chunk, cycleNumber);
|
|
81
|
+
console.log('Activity event:', activityEvent);
|
|
82
|
+
await streamManager.emit(activityEvent);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
this.logger.error('Error mapping chunk to activity:', error);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
context: context
|
|
89
|
+
? new oLaneContext([
|
|
90
|
+
`[Chat History Context Begin]\n${context}\n[Chat History Context End]`,
|
|
91
|
+
])
|
|
92
|
+
: undefined,
|
|
93
|
+
});
|
|
94
|
+
// Emit preflight complete
|
|
95
|
+
await streamManager.emit(eventMapper.mapCapabilityEndToStepFinished(oCapabilityType.UNKNOWN));
|
|
96
|
+
// Override lane's addSequence to emit events as capabilities execute
|
|
97
|
+
const originalAddSequence = lane.addSequence.bind(lane);
|
|
98
|
+
lane.addSequence = (result) => {
|
|
99
|
+
// Call original method
|
|
100
|
+
originalAddSequence(result);
|
|
101
|
+
// Emit AG-UI events asynchronously
|
|
102
|
+
(async () => {
|
|
103
|
+
try {
|
|
104
|
+
cycleNumber++;
|
|
105
|
+
// Emit step started
|
|
106
|
+
await streamManager.emit(eventMapper.mapCapabilityStartToStepStarted(result.type));
|
|
107
|
+
// Map capability to events
|
|
108
|
+
const events = eventMapper.mapCapabilityToEvents(result, cycleNumber);
|
|
109
|
+
await streamManager.emitBatch(events);
|
|
110
|
+
// Emit state updates
|
|
111
|
+
if (this.agUIConfig.stateSnapshotInterval &&
|
|
112
|
+
cycleNumber % this.agUIConfig.stateSnapshotInterval === 0) {
|
|
113
|
+
// Emit full snapshot
|
|
114
|
+
await streamManager.emit(eventMapper.mapSequenceToStateSnapshot(lane.sequence));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Emit delta
|
|
118
|
+
const delta = eventMapper.mapSequenceToStateDelta(previousSequence, lane.sequence);
|
|
119
|
+
if (delta) {
|
|
120
|
+
await streamManager.emit(delta);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
previousSequence = [...lane.sequence];
|
|
124
|
+
// Emit step finished
|
|
125
|
+
await streamManager.emit(eventMapper.mapCapabilityEndToStepFinished(result.type));
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
this.logger.error('Error emitting AG-UI events:', error);
|
|
129
|
+
}
|
|
130
|
+
})();
|
|
131
|
+
};
|
|
132
|
+
// Execute the lane
|
|
133
|
+
let result;
|
|
134
|
+
let error;
|
|
135
|
+
try {
|
|
136
|
+
result = await lane.execute();
|
|
137
|
+
// Emit final state snapshot
|
|
138
|
+
await streamManager.emit(eventMapper.mapSequenceToStateSnapshot(lane.sequence));
|
|
139
|
+
// Emit RunFinished
|
|
140
|
+
if (result) {
|
|
141
|
+
await streamManager.emit(eventMapper.mapLaneCompleteToRunFinished(result));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
error = err;
|
|
146
|
+
this.logger.error('Lane execution error:', error);
|
|
147
|
+
// Emit RunError
|
|
148
|
+
await streamManager.emit(eventMapper.mapLaneErrorToRunError(error));
|
|
149
|
+
}
|
|
150
|
+
// Flush any remaining events
|
|
151
|
+
await streamManager.flushQueue();
|
|
152
|
+
// Return standard response
|
|
153
|
+
const completeResponse = {
|
|
154
|
+
result: result?.result,
|
|
155
|
+
humanResult: result?.humanResult,
|
|
156
|
+
summary: result?.config?.params?.summary,
|
|
157
|
+
error: error?.message || result?.error,
|
|
158
|
+
cycles: lane.sequence.length,
|
|
159
|
+
cid: lane.cid?.toString(),
|
|
160
|
+
threadId,
|
|
161
|
+
runId,
|
|
162
|
+
sequence: lane.sequence.map((s) => s.result),
|
|
163
|
+
};
|
|
164
|
+
return completeResponse;
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
// Close stream manager
|
|
168
|
+
await streamManager.close();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Standard intent method - optionally enable AG-UI if configured
|
|
173
|
+
* Overrides the base _tool_intent to add AG-UI support
|
|
174
|
+
*/
|
|
175
|
+
async _tool_intent(request) {
|
|
176
|
+
// If AG-UI is enabled, use AG-UI intent method
|
|
177
|
+
if (this.agUIConfig.enableAGUI) {
|
|
178
|
+
return this._tool_ag_ui_intent(request);
|
|
179
|
+
}
|
|
180
|
+
// Otherwise, call the parent implementation
|
|
181
|
+
// Use the standard lane execution from withLane mixin
|
|
182
|
+
const { intent, context, streamTo, _isStreaming = false } = request.params;
|
|
183
|
+
const lane = await this.manager.createLane({
|
|
184
|
+
intent: new oIntent({ intent: intent }),
|
|
185
|
+
currentNode: this,
|
|
186
|
+
caller: this.address,
|
|
187
|
+
streamTo: streamTo ? new oAddress(streamTo) : undefined,
|
|
188
|
+
useStream: _isStreaming,
|
|
189
|
+
requestId: request.id,
|
|
190
|
+
context: context
|
|
191
|
+
? new oLaneContext([
|
|
192
|
+
`[Chat History Context Begin]\n${context}\n[Chat History Context End]`,
|
|
193
|
+
])
|
|
194
|
+
: undefined,
|
|
195
|
+
});
|
|
196
|
+
const response = await lane.execute();
|
|
197
|
+
return {
|
|
198
|
+
result: response?.result,
|
|
199
|
+
humanResult: response?.humanResult,
|
|
200
|
+
summary: response?.config?.params?.summary,
|
|
201
|
+
error: response?.error,
|
|
202
|
+
cycles: lane.sequence.length,
|
|
203
|
+
cid: lane.cid?.toString(),
|
|
204
|
+
sequence: lane.sequence.map((s) => s.result),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Receive AG-UI event from remote sources
|
|
209
|
+
* Allows other tools to send events to this tool
|
|
210
|
+
*/
|
|
211
|
+
async _tool_receive_ag_ui_event(request) {
|
|
212
|
+
const { event } = request.params;
|
|
213
|
+
this.logger.debug('Received AG-UI event:', event);
|
|
214
|
+
// Handle the event (can be extended for custom logic)
|
|
215
|
+
return {
|
|
216
|
+
received: true,
|
|
217
|
+
eventType: event.type,
|
|
218
|
+
timestamp: generateTimestamp(),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Create default transport based on request configuration
|
|
223
|
+
*/
|
|
224
|
+
createDefaultTransport(request) {
|
|
225
|
+
// If streaming is enabled and we have a stream, use ONode transport
|
|
226
|
+
if (request.params._isStreaming && request.stream) {
|
|
227
|
+
return new ONodeAGUITransport({
|
|
228
|
+
stream: request.stream,
|
|
229
|
+
node: this,
|
|
230
|
+
requestId: request.id,
|
|
231
|
+
streamTo: request.params.streamTo
|
|
232
|
+
? new oAddress(request.params.streamTo)
|
|
233
|
+
: undefined,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// Otherwise, use console transport for debugging
|
|
237
|
+
return new ConsoleAGUITransport(this.agUIConfig.debugAGUI);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Enable or disable AG-UI at runtime
|
|
241
|
+
*/
|
|
242
|
+
setAGUIEnabled(enabled) {
|
|
243
|
+
this.agUIConfig.enableAGUI = enabled;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Check if AG-UI is enabled
|
|
247
|
+
*/
|
|
248
|
+
isAGUIEnabled() {
|
|
249
|
+
return this.agUIConfig.enableAGUI || false;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Get AG-UI configuration
|
|
253
|
+
*/
|
|
254
|
+
getAGUIConfig() {
|
|
255
|
+
return { ...this.agUIConfig };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AGUIEvent } from './types/ag-ui-event.types.js';
|
|
2
|
+
import { AGUITransport } from './transports/ag-ui-transport.interface.js';
|
|
3
|
+
import { oObject } from '@olane/o-core';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for stream manager
|
|
6
|
+
*/
|
|
7
|
+
export interface AGUIStreamManagerConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Event transport mechanism
|
|
10
|
+
*/
|
|
11
|
+
transport: AGUITransport;
|
|
12
|
+
/**
|
|
13
|
+
* Enable debug logging
|
|
14
|
+
*/
|
|
15
|
+
debug?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Filter events by type (if undefined, all events are emitted)
|
|
18
|
+
*/
|
|
19
|
+
eventFilter?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Maximum queue size before forcing emission
|
|
22
|
+
*/
|
|
23
|
+
maxQueueSize?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Enable event validation
|
|
26
|
+
*/
|
|
27
|
+
validateEvents?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Manages AG-UI event emission with proper ordering and formatting
|
|
31
|
+
*/
|
|
32
|
+
export declare class AGUIStreamManager extends oObject {
|
|
33
|
+
private transport;
|
|
34
|
+
private debug;
|
|
35
|
+
private eventFilter?;
|
|
36
|
+
private maxQueueSize;
|
|
37
|
+
private validateEvents;
|
|
38
|
+
private eventQueue;
|
|
39
|
+
private emitting;
|
|
40
|
+
constructor(config: AGUIStreamManagerConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Emit a single event
|
|
43
|
+
*/
|
|
44
|
+
emit(event: AGUIEvent): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Emit multiple events in sequence
|
|
47
|
+
*/
|
|
48
|
+
emitBatch(events: AGUIEvent[]): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Queue an event for later emission
|
|
51
|
+
* Useful for buffering events during processing
|
|
52
|
+
*/
|
|
53
|
+
queueEvent(event: AGUIEvent): void;
|
|
54
|
+
/**
|
|
55
|
+
* Queue multiple events
|
|
56
|
+
*/
|
|
57
|
+
queueBatch(events: AGUIEvent[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Flush all queued events
|
|
60
|
+
*/
|
|
61
|
+
flushQueue(): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Get the number of queued events
|
|
64
|
+
*/
|
|
65
|
+
getQueueSize(): number;
|
|
66
|
+
/**
|
|
67
|
+
* Clear the event queue without emitting
|
|
68
|
+
*/
|
|
69
|
+
clearQueue(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Check if transport is active
|
|
72
|
+
*/
|
|
73
|
+
isActive(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Close the stream manager and transport
|
|
76
|
+
*/
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Update the transport
|
|
80
|
+
*/
|
|
81
|
+
setTransport(transport: AGUITransport): void;
|
|
82
|
+
/**
|
|
83
|
+
* Get transport type
|
|
84
|
+
*/
|
|
85
|
+
getTransportType(): string;
|
|
86
|
+
/**
|
|
87
|
+
* Enable/disable debug mode
|
|
88
|
+
*/
|
|
89
|
+
setDebug(debug: boolean): void;
|
|
90
|
+
/**
|
|
91
|
+
* Update event filter
|
|
92
|
+
*/
|
|
93
|
+
setEventFilter(filter: string[] | undefined): void;
|
|
94
|
+
/**
|
|
95
|
+
* Get current event filter
|
|
96
|
+
*/
|
|
97
|
+
getEventFilter(): string[] | undefined;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=ag-ui-stream-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ag-ui-stream-manager.d.ts","sourceRoot":"","sources":["../../../src/ag-ui/ag-ui-stream-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,SAAS,EAAE,aAAa,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,OAAO;IAC5C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,uBAAuB;IAW3C;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B3C;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAclC;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI;IAMrC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI;IAI5C;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9B;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI;IAIlD;;OAEG;IACH,cAAc,IAAI,MAAM,EAAE,GAAG,SAAS;CAGvC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { validateEvent } from './ag-ui-utils.js';
|
|
2
|
+
import { oObject } from '@olane/o-core';
|
|
3
|
+
/**
|
|
4
|
+
* Manages AG-UI event emission with proper ordering and formatting
|
|
5
|
+
*/
|
|
6
|
+
export class AGUIStreamManager extends oObject {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super('ag-ui-stream-manager');
|
|
9
|
+
this.eventQueue = [];
|
|
10
|
+
this.emitting = false;
|
|
11
|
+
this.transport = config.transport;
|
|
12
|
+
this.debug = config.debug || false;
|
|
13
|
+
this.eventFilter = config.eventFilter
|
|
14
|
+
? new Set(config.eventFilter)
|
|
15
|
+
: undefined;
|
|
16
|
+
this.maxQueueSize = config.maxQueueSize || 100;
|
|
17
|
+
this.validateEvents = config.validateEvents !== false;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Emit a single event
|
|
21
|
+
*/
|
|
22
|
+
async emit(event) {
|
|
23
|
+
// Filter events if configured
|
|
24
|
+
if (this.eventFilter && !this.eventFilter.has(event.type)) {
|
|
25
|
+
if (this.debug) {
|
|
26
|
+
this.logger.debug(`Filtered event: ${event.type}`);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Validate event if configured
|
|
31
|
+
if (this.validateEvents && !validateEvent(event)) {
|
|
32
|
+
this.logger.warn(`Invalid event structure: ${event.type}`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (this.debug) {
|
|
36
|
+
this.logger.debug(`Emitting event: ${event.type}`, event);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
await this.transport.send(event);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.logger.error(`Error emitting event ${event.type}:`, error);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Emit multiple events in sequence
|
|
48
|
+
*/
|
|
49
|
+
async emitBatch(events) {
|
|
50
|
+
for (const event of events) {
|
|
51
|
+
await this.emit(event);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Queue an event for later emission
|
|
56
|
+
* Useful for buffering events during processing
|
|
57
|
+
*/
|
|
58
|
+
queueEvent(event) {
|
|
59
|
+
this.eventQueue.push(event);
|
|
60
|
+
// Auto-flush if queue is too large
|
|
61
|
+
if (this.eventQueue.length >= this.maxQueueSize) {
|
|
62
|
+
this.logger.warn(`Event queue reached max size (${this.maxQueueSize}), flushing...`);
|
|
63
|
+
this.flushQueue().catch((error) => {
|
|
64
|
+
this.logger.error('Error flushing queue:', error);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Queue multiple events
|
|
70
|
+
*/
|
|
71
|
+
queueBatch(events) {
|
|
72
|
+
for (const event of events) {
|
|
73
|
+
this.queueEvent(event);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Flush all queued events
|
|
78
|
+
*/
|
|
79
|
+
async flushQueue() {
|
|
80
|
+
if (this.emitting) {
|
|
81
|
+
this.logger.debug('Already emitting, skipping flush');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (this.eventQueue.length === 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.emitting = true;
|
|
88
|
+
try {
|
|
89
|
+
const events = [...this.eventQueue];
|
|
90
|
+
this.eventQueue = [];
|
|
91
|
+
if (this.debug) {
|
|
92
|
+
this.logger.debug(`Flushing ${events.length} queued events`);
|
|
93
|
+
}
|
|
94
|
+
await this.emitBatch(events);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
this.emitting = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the number of queued events
|
|
102
|
+
*/
|
|
103
|
+
getQueueSize() {
|
|
104
|
+
return this.eventQueue.length;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Clear the event queue without emitting
|
|
108
|
+
*/
|
|
109
|
+
clearQueue() {
|
|
110
|
+
this.eventQueue = [];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if transport is active
|
|
114
|
+
*/
|
|
115
|
+
isActive() {
|
|
116
|
+
return this.transport.isActive();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Close the stream manager and transport
|
|
120
|
+
*/
|
|
121
|
+
async close() {
|
|
122
|
+
// Flush any remaining events
|
|
123
|
+
await this.flushQueue();
|
|
124
|
+
// Close transport
|
|
125
|
+
await this.transport.close();
|
|
126
|
+
if (this.debug) {
|
|
127
|
+
this.logger.debug('Stream manager closed');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Update the transport
|
|
132
|
+
*/
|
|
133
|
+
setTransport(transport) {
|
|
134
|
+
this.transport = transport;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get transport type
|
|
138
|
+
*/
|
|
139
|
+
getTransportType() {
|
|
140
|
+
return this.transport.getType();
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Enable/disable debug mode
|
|
144
|
+
*/
|
|
145
|
+
setDebug(debug) {
|
|
146
|
+
this.debug = debug;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Update event filter
|
|
150
|
+
*/
|
|
151
|
+
setEventFilter(filter) {
|
|
152
|
+
this.eventFilter = filter ? new Set(filter) : undefined;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get current event filter
|
|
156
|
+
*/
|
|
157
|
+
getEventFilter() {
|
|
158
|
+
return this.eventFilter ? Array.from(this.eventFilter) : undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { JSONPatchOperation } from './types/ag-ui-event.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for AG-UI event handling
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate a unique run ID
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateRunId(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a unique message ID
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateMessageId(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Generate a unique tool call ID
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateToolCallId(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Generate a thread ID from context or create a new one
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateThreadId(context?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Generate ISO 8601 timestamp for events
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateTimestamp(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate JSON Patch operations (RFC 6902) for state deltas
|
|
27
|
+
* Compares old and new state to create minimal patch
|
|
28
|
+
*/
|
|
29
|
+
export declare function generateJSONPatch(oldState: any, newState: any, basePath?: string): JSONPatchOperation[];
|
|
30
|
+
/**
|
|
31
|
+
* Apply JSON Patch operations to an object
|
|
32
|
+
*/
|
|
33
|
+
export declare function applyJSONPatch(obj: any, patches: JSONPatchOperation[]): any;
|
|
34
|
+
/**
|
|
35
|
+
* Chunk a string into smaller pieces for streaming
|
|
36
|
+
*/
|
|
37
|
+
export declare function chunkString(str: string, chunkSize: number): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Validate an AG-UI event has required fields
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateEvent(event: any): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Extract capability type from step name
|
|
44
|
+
*/
|
|
45
|
+
export declare function capabilityTypeToStepName(capabilityType: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Create a safe JSON string from any value
|
|
48
|
+
*/
|
|
49
|
+
export declare function safeJSONStringify(value: any): string;
|
|
50
|
+
//# sourceMappingURL=ag-ui-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ag-ui-utils.d.ts","sourceRoot":"","sources":["../../../src/ag-ui/ag-ui-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE;;GAEG;AAEH;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAOzD;AAeD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,GAAG,EACb,QAAQ,GAAE,MAAW,GACpB,kBAAkB,EAAE,CA+EtB;AAyDD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,GAAG,CAoB3E;AA2DD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAWjD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAMpD"}
|