react-websocket 4.0.0 → 4.18.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/README.md +27 -3
- package/dist/ag-ui.cjs +421 -0
- package/dist/ag-ui.cjs.map +1 -0
- package/dist/ag-ui.d.cts +493 -0
- package/dist/ag-ui.d.ts +171 -0
- package/dist/ag-ui.js +418 -0
- package/dist/ag-ui.js.map +1 -0
- package/dist/core.cjs +689 -153
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +459 -53
- package/dist/core.d.ts +459 -53
- package/dist/core.js +686 -154
- package/dist/core.js.map +1 -1
- package/dist/devtools.cjs +186 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.cts +32 -0
- package/dist/devtools.d.ts +32 -0
- package/dist/devtools.js +185 -0
- package/dist/devtools.js.map +1 -0
- package/dist/index.cjs +182 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +663 -48
- package/dist/index.d.ts +393 -22
- package/dist/index.js +178 -24
- package/dist/index.js.map +1 -1
- package/dist/outbox.cjs +222 -0
- package/dist/outbox.cjs.map +1 -0
- package/dist/outbox.d.cts +127 -0
- package/dist/outbox.d.ts +127 -0
- package/dist/outbox.js +219 -0
- package/dist/outbox.js.map +1 -0
- package/dist/replay.cjs +324 -0
- package/dist/replay.cjs.map +1 -0
- package/dist/replay.d.cts +124 -0
- package/dist/replay.d.ts +124 -0
- package/dist/replay.js +322 -0
- package/dist/replay.js.map +1 -0
- package/dist/tabs.cjs +336 -0
- package/dist/tabs.cjs.map +1 -0
- package/dist/tabs.d.cts +81 -0
- package/dist/tabs.d.ts +81 -0
- package/dist/tabs.js +335 -0
- package/dist/tabs.js.map +1 -0
- package/dist/timeline.d.cts +1 -216
- package/dist/types-BEecFqIB.d.cts +268 -0
- package/dist/webtransport.cjs +243 -0
- package/dist/webtransport.cjs.map +1 -0
- package/dist/webtransport.d.cts +67 -0
- package/dist/webtransport.d.ts +67 -0
- package/dist/webtransport.js +242 -0
- package/dist/webtransport.js.map +1 -0
- package/package.json +139 -3
package/dist/ag-ui.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { createWebSocketRuns } from "./core.js";
|
|
2
|
+
//#region src/ag-ui.ts
|
|
3
|
+
function unescape(token) {
|
|
4
|
+
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
5
|
+
}
|
|
6
|
+
function equal(a, b) {
|
|
7
|
+
if (a === b) return true;
|
|
8
|
+
if (typeof a !== "object" || typeof b !== "object" || !a || !b) return false;
|
|
9
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
10
|
+
const keys = Object.keys(a);
|
|
11
|
+
return keys.length === Object.keys(b).length && keys.every((key) => equal(a[key], b[key]));
|
|
12
|
+
}
|
|
13
|
+
function fail(operation) {
|
|
14
|
+
throw new Error(`JSON Patch failed: ${operation.op} ${operation.path}`);
|
|
15
|
+
}
|
|
16
|
+
const INDEX = /^(0|[1-9]\d*)$/;
|
|
17
|
+
/** A JSON Pointer's tokens. It's empty, for the whole document, or starts with `/`. */
|
|
18
|
+
function tokens(pointer, operation) {
|
|
19
|
+
if (pointer !== "" && pointer[0] !== "/") fail(operation);
|
|
20
|
+
return pointer.split("/").slice(1).map(unescape);
|
|
21
|
+
}
|
|
22
|
+
/** Whether `node` has `token`: an index in range for an array, not `length`; an own key otherwise. */
|
|
23
|
+
function has(node, token) {
|
|
24
|
+
return Array.isArray(node) ? INDEX.test(token) && +token < node.length : Object.hasOwn(node, token);
|
|
25
|
+
}
|
|
26
|
+
/** Set an own property, even `__proto__`, as JSON.parse would. */
|
|
27
|
+
function put(object, key, value) {
|
|
28
|
+
Object.defineProperty(object, key, {
|
|
29
|
+
value,
|
|
30
|
+
writable: true,
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Apply a JSON Patch (RFC 6902) without changing `document`: what changes is copied, the rest is
|
|
37
|
+
* shared. Throws, leaving `document` as it was, if an operation can't be applied: a missing path,
|
|
38
|
+
* an index out of range, a pointer that doesn't start with `/`, or a failed `test`.
|
|
39
|
+
*/
|
|
40
|
+
function applyPatch(document, operations) {
|
|
41
|
+
let root = document;
|
|
42
|
+
function get(path, operation) {
|
|
43
|
+
let node = root;
|
|
44
|
+
for (const token of tokens(path, operation)) {
|
|
45
|
+
if (typeof node !== "object" || node === null || !has(node, token)) fail(operation);
|
|
46
|
+
node = node[token];
|
|
47
|
+
}
|
|
48
|
+
return node;
|
|
49
|
+
}
|
|
50
|
+
function edit(path, operation, change) {
|
|
51
|
+
const keys = tokens(path, operation);
|
|
52
|
+
if (!keys.length) fail(operation);
|
|
53
|
+
const walk = (node, depth) => {
|
|
54
|
+
if (typeof node !== "object" || node === null) fail(operation);
|
|
55
|
+
const copy = Array.isArray(node) ? [...node] : { ...node };
|
|
56
|
+
const key = keys[depth];
|
|
57
|
+
if (depth === keys.length - 1) change(copy, key);
|
|
58
|
+
else if (!has(node, key)) fail(operation);
|
|
59
|
+
else copy[key] = walk(node[key], depth + 1);
|
|
60
|
+
return copy;
|
|
61
|
+
};
|
|
62
|
+
root = walk(root, 0);
|
|
63
|
+
}
|
|
64
|
+
function index(parent, key, operation, adding) {
|
|
65
|
+
const i = key === "-" ? adding ? parent.length : -1 : INDEX.test(key) ? +key : -1;
|
|
66
|
+
if (i < 0 || i > parent.length - (adding ? 0 : 1)) fail(operation);
|
|
67
|
+
return i;
|
|
68
|
+
}
|
|
69
|
+
function add(path, value, operation) {
|
|
70
|
+
if (path === "") return void (root = value);
|
|
71
|
+
edit(path, operation, (parent, key) => {
|
|
72
|
+
if (Array.isArray(parent)) parent.splice(index(parent, key, operation, true), 0, value);
|
|
73
|
+
else put(parent, key, value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function remove(path, operation) {
|
|
77
|
+
edit(path, operation, (parent, key) => {
|
|
78
|
+
if (Array.isArray(parent)) parent.splice(index(parent, key, operation, false), 1);
|
|
79
|
+
else if (Object.hasOwn(parent, key)) delete parent[key];
|
|
80
|
+
else fail(operation);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
for (const operation of operations) {
|
|
84
|
+
const { op, path, from, value } = operation;
|
|
85
|
+
if (op === "add") add(path, value, operation);
|
|
86
|
+
else if (op === "remove") remove(path, operation);
|
|
87
|
+
else if (op === "replace") {
|
|
88
|
+
get(path, operation);
|
|
89
|
+
if (path === "") root = value;
|
|
90
|
+
else edit(path, operation, (parent, key) => {
|
|
91
|
+
if (Array.isArray(parent)) parent[key] = value;
|
|
92
|
+
else put(parent, key, value);
|
|
93
|
+
});
|
|
94
|
+
} else if (op === "move" || op === "copy") {
|
|
95
|
+
const moved = get(from ?? fail(operation), operation);
|
|
96
|
+
if (op === "move") remove(from, operation);
|
|
97
|
+
add(path, op === "copy" ? structuredClone(moved) : moved, operation);
|
|
98
|
+
} else if (op === "test") {
|
|
99
|
+
if (!equal(get(path, operation), value)) fail(operation);
|
|
100
|
+
} else fail(operation);
|
|
101
|
+
}
|
|
102
|
+
return root;
|
|
103
|
+
}
|
|
104
|
+
function updateMessage(thread, id, change) {
|
|
105
|
+
return thread.messages.map((message) => message.id === id ? change(message) : message);
|
|
106
|
+
}
|
|
107
|
+
function appendText(message, delta) {
|
|
108
|
+
return {
|
|
109
|
+
...message,
|
|
110
|
+
content: `${message.content ?? ""}${delta ?? ""}`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function updateToolCall(thread, id, change) {
|
|
114
|
+
return thread.messages.map((message) => message.toolCalls?.some((call) => call.id === id) ? {
|
|
115
|
+
...message,
|
|
116
|
+
toolCalls: message.toolCalls.map((call) => call.id === id ? change(call) : call)
|
|
117
|
+
} : message);
|
|
118
|
+
}
|
|
119
|
+
/** The last message with a tool call, for chunks that leave out `toolCallId`. */
|
|
120
|
+
function lastToolCallId(thread) {
|
|
121
|
+
for (let i = thread.messages.length - 1; i >= 0; i--) {
|
|
122
|
+
const calls = thread.messages[i].toolCalls;
|
|
123
|
+
if (calls?.length) return calls.at(-1).id;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Fold one AG-UI event into a thread, without changing it. Handles the run lifecycle, steps,
|
|
128
|
+
* text, tool calls and their results, reasoning, activity, and message and state snapshots and
|
|
129
|
+
* deltas. A `STATE_DELTA` that can't be applied marks the thread `stale` instead of throwing.
|
|
130
|
+
* Other events, such as `CUSTOM` and `RAW`, return the thread unchanged.
|
|
131
|
+
*
|
|
132
|
+
* Use it as a `reduce` function, or wrap it to handle events of your own.
|
|
133
|
+
*/
|
|
134
|
+
function applyAgUiEvent(thread, event) {
|
|
135
|
+
const e = event;
|
|
136
|
+
const message = (role, extra) => ({
|
|
137
|
+
...thread,
|
|
138
|
+
messages: [...thread.messages, {
|
|
139
|
+
id: e.messageId,
|
|
140
|
+
role,
|
|
141
|
+
content: "",
|
|
142
|
+
...extra
|
|
143
|
+
}]
|
|
144
|
+
});
|
|
145
|
+
const known = (id) => thread.messages.some((m) => m.id === id);
|
|
146
|
+
switch (e.type) {
|
|
147
|
+
case "RUN_STARTED": return {
|
|
148
|
+
...thread,
|
|
149
|
+
status: "running",
|
|
150
|
+
error: void 0,
|
|
151
|
+
result: void 0
|
|
152
|
+
};
|
|
153
|
+
case "RUN_FINISHED": return {
|
|
154
|
+
...thread,
|
|
155
|
+
status: "finished",
|
|
156
|
+
step: void 0,
|
|
157
|
+
result: e.result
|
|
158
|
+
};
|
|
159
|
+
case "RUN_ERROR": return {
|
|
160
|
+
...thread,
|
|
161
|
+
status: "error",
|
|
162
|
+
step: void 0,
|
|
163
|
+
error: {
|
|
164
|
+
message: e.message,
|
|
165
|
+
code: e.code
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
case "STEP_STARTED": return {
|
|
169
|
+
...thread,
|
|
170
|
+
step: e.stepName
|
|
171
|
+
};
|
|
172
|
+
case "STEP_FINISHED": return {
|
|
173
|
+
...thread,
|
|
174
|
+
step: void 0
|
|
175
|
+
};
|
|
176
|
+
case "TEXT_MESSAGE_START": return message(e.role ?? "assistant");
|
|
177
|
+
case "REASONING_MESSAGE_START": return message("reasoning");
|
|
178
|
+
case "TEXT_MESSAGE_CONTENT":
|
|
179
|
+
case "REASONING_MESSAGE_CONTENT": return {
|
|
180
|
+
...thread,
|
|
181
|
+
messages: updateMessage(thread, e.messageId, (m) => appendText(m, e.delta))
|
|
182
|
+
};
|
|
183
|
+
case "TEXT_MESSAGE_CHUNK":
|
|
184
|
+
case "REASONING_MESSAGE_CHUNK": {
|
|
185
|
+
const id = e.messageId ?? thread.messages.at(-1)?.id;
|
|
186
|
+
const role = e.type === "TEXT_MESSAGE_CHUNK" ? e.role ?? "assistant" : "reasoning";
|
|
187
|
+
const next = known(id) ? thread : message(role);
|
|
188
|
+
return {
|
|
189
|
+
...next,
|
|
190
|
+
messages: updateMessage(next, id, (m) => appendText(m, e.delta))
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
case "TOOL_CALL_START":
|
|
194
|
+
case "TOOL_CALL_CHUNK": {
|
|
195
|
+
const id = e.toolCallId ?? lastToolCallId(thread);
|
|
196
|
+
let next = thread;
|
|
197
|
+
if (e.type === "TOOL_CALL_START" || !thread.messages.some((m) => m.toolCalls?.some((c) => c.id === id))) {
|
|
198
|
+
const call = {
|
|
199
|
+
id,
|
|
200
|
+
type: "function",
|
|
201
|
+
function: {
|
|
202
|
+
name: e.toolCallName,
|
|
203
|
+
arguments: ""
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const parent = e.parentMessageId ?? id;
|
|
207
|
+
next = known(parent) ? thread : {
|
|
208
|
+
...thread,
|
|
209
|
+
messages: [...thread.messages, {
|
|
210
|
+
id: parent,
|
|
211
|
+
role: "assistant"
|
|
212
|
+
}]
|
|
213
|
+
};
|
|
214
|
+
next = {
|
|
215
|
+
...next,
|
|
216
|
+
messages: updateMessage(next, parent, (m) => ({
|
|
217
|
+
...m,
|
|
218
|
+
toolCalls: [...m.toolCalls ?? [], call]
|
|
219
|
+
}))
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (e.type === "TOOL_CALL_START") return next;
|
|
223
|
+
return toolArgs(next, id, e.delta);
|
|
224
|
+
}
|
|
225
|
+
case "TOOL_CALL_ARGS": return toolArgs(thread, e.toolCallId, e.delta);
|
|
226
|
+
case "TOOL_CALL_RESULT": return message(e.role ?? "tool", {
|
|
227
|
+
toolCallId: e.toolCallId,
|
|
228
|
+
content: e.content
|
|
229
|
+
});
|
|
230
|
+
case "STATE_SNAPSHOT": return {
|
|
231
|
+
...thread,
|
|
232
|
+
state: e.snapshot,
|
|
233
|
+
stale: false
|
|
234
|
+
};
|
|
235
|
+
case "STATE_DELTA":
|
|
236
|
+
if (thread.stale) return thread;
|
|
237
|
+
try {
|
|
238
|
+
return {
|
|
239
|
+
...thread,
|
|
240
|
+
state: applyPatch(thread.state, e.delta)
|
|
241
|
+
};
|
|
242
|
+
} catch {
|
|
243
|
+
return {
|
|
244
|
+
...thread,
|
|
245
|
+
stale: true
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
case "MESSAGES_SNAPSHOT": return {
|
|
249
|
+
...thread,
|
|
250
|
+
messages: e.messages
|
|
251
|
+
};
|
|
252
|
+
case "ACTIVITY_SNAPSHOT": {
|
|
253
|
+
if (known(e.messageId) && e.replace === false) return thread;
|
|
254
|
+
const next = known(e.messageId) ? thread : message("activity");
|
|
255
|
+
return {
|
|
256
|
+
...next,
|
|
257
|
+
messages: updateMessage(next, e.messageId, (m) => ({
|
|
258
|
+
...m,
|
|
259
|
+
activityType: e.activityType,
|
|
260
|
+
content: e.content
|
|
261
|
+
}))
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
case "ACTIVITY_DELTA": try {
|
|
265
|
+
return {
|
|
266
|
+
...thread,
|
|
267
|
+
messages: updateMessage(thread, e.messageId, (m) => ({
|
|
268
|
+
...m,
|
|
269
|
+
content: applyPatch(m.content, e.patch)
|
|
270
|
+
}))
|
|
271
|
+
};
|
|
272
|
+
} catch {
|
|
273
|
+
return thread;
|
|
274
|
+
}
|
|
275
|
+
default: return thread;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function toolArgs(thread, id, delta) {
|
|
279
|
+
return {
|
|
280
|
+
...thread,
|
|
281
|
+
messages: updateToolCall(thread, id, (call) => ({
|
|
282
|
+
...call,
|
|
283
|
+
function: {
|
|
284
|
+
...call.function,
|
|
285
|
+
arguments: call.function.arguments + (delta ?? "")
|
|
286
|
+
}
|
|
287
|
+
}))
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function randomId() {
|
|
291
|
+
return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
292
|
+
}
|
|
293
|
+
const isEnvelope = (message) => typeof message?.runId === "string" && typeof message.offset === "number" && typeof message.event?.type === "string" ? message : void 0;
|
|
294
|
+
const ENDS = /* @__PURE__ */ new Set(["RUN_FINISHED", "RUN_ERROR"]);
|
|
295
|
+
/**
|
|
296
|
+
* Run an [AG-UI](https://docs.ag-ui.com) agent over a WebSocket. Each run streams AG-UI events,
|
|
297
|
+
* which are folded into the thread's messages and shared state with {@link applyAgUiEvent}.
|
|
298
|
+
* Runs come from `createWebSocketRuns`, so they resume after a reconnect or a reload, and a
|
|
299
|
+
* state delta that can't be applied asks for a snapshot (`resync`).
|
|
300
|
+
*
|
|
301
|
+
* AG-UI doesn't define messages for WebSockets, so the defaults are small: the client sends
|
|
302
|
+
* `{ type: 'run', runId, input }`, `{ type: 'resume', runId, after }` and
|
|
303
|
+
* `{ type: 'cancel', runId }`, and the server sends `{ runId, offset, event }`, with `offset`
|
|
304
|
+
* counting each run's events from 1. Each option replaces one of them.
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```ts
|
|
308
|
+
* import { createAgUiAgent } from 'react-websocket/ag-ui';
|
|
309
|
+
*
|
|
310
|
+
* export const agent = createAgUiAgent(createWebSocket(url, { json: true }));
|
|
311
|
+
*
|
|
312
|
+
* agent.run({ messages: [{ id: crypto.randomUUID(), role: 'user', content: 'Plan my week' }] });
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
function createAgUiAgent(client, options = {}) {
|
|
316
|
+
const threadId = options.threadId ?? randomId();
|
|
317
|
+
const empty = {
|
|
318
|
+
messages: [],
|
|
319
|
+
state: options.state,
|
|
320
|
+
status: "idle",
|
|
321
|
+
stale: false
|
|
322
|
+
};
|
|
323
|
+
let base = empty;
|
|
324
|
+
let snapshot = empty;
|
|
325
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
326
|
+
const resynced = /* @__PURE__ */ new Set();
|
|
327
|
+
const event = options.event ?? isEnvelope;
|
|
328
|
+
const send = (message) => client.socket?.readyState === 1 && client.send(message);
|
|
329
|
+
const runs = createWebSocketRuns(client, {
|
|
330
|
+
name: options.name ?? "ag-ui",
|
|
331
|
+
start: options.run ?? ((input, runId) => ({
|
|
332
|
+
type: "run",
|
|
333
|
+
runId,
|
|
334
|
+
input
|
|
335
|
+
})),
|
|
336
|
+
resume: options.resume ?? ((runId, after) => ({
|
|
337
|
+
type: "resume",
|
|
338
|
+
runId,
|
|
339
|
+
after
|
|
340
|
+
})),
|
|
341
|
+
cancel: options.cancel ?? ((runId) => ({
|
|
342
|
+
type: "cancel",
|
|
343
|
+
runId
|
|
344
|
+
})),
|
|
345
|
+
event: (message) => event(message),
|
|
346
|
+
done: (message) => ENDS.has(event(message).event.type),
|
|
347
|
+
initial: empty,
|
|
348
|
+
reduce: (thread, message) => applyAgUiEvent(thread, event(message).event),
|
|
349
|
+
policy: options.policy,
|
|
350
|
+
storage: options.storage
|
|
351
|
+
});
|
|
352
|
+
function update() {
|
|
353
|
+
const latest = runs.list().at(-1);
|
|
354
|
+
let next = latest ? latest.value : base;
|
|
355
|
+
if (latest?.status === "aborted" && next.status === "running") next = {
|
|
356
|
+
...next,
|
|
357
|
+
status: "aborted"
|
|
358
|
+
};
|
|
359
|
+
if (latest && !latest.value.stale) resynced.delete(latest.runId);
|
|
360
|
+
else if (latest && options.resync && !resynced.has(latest.runId)) {
|
|
361
|
+
if (send(options.resync(latest.runId))) resynced.add(latest.runId);
|
|
362
|
+
}
|
|
363
|
+
if (next === snapshot) return;
|
|
364
|
+
snapshot = next;
|
|
365
|
+
for (const listener of [...listeners]) listener();
|
|
366
|
+
}
|
|
367
|
+
const off = runs.subscribe(update);
|
|
368
|
+
update();
|
|
369
|
+
function abort() {
|
|
370
|
+
for (const run of runs.list()) runs.abort(run.runId);
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
client,
|
|
374
|
+
runs,
|
|
375
|
+
run(input = {}, runOptions) {
|
|
376
|
+
abort();
|
|
377
|
+
const runId = randomId();
|
|
378
|
+
base = {
|
|
379
|
+
...snapshot,
|
|
380
|
+
stale: false,
|
|
381
|
+
messages: [...snapshot.messages, ...input.messages ?? []]
|
|
382
|
+
};
|
|
383
|
+
runs.start({
|
|
384
|
+
threadId,
|
|
385
|
+
runId,
|
|
386
|
+
state: base.state,
|
|
387
|
+
messages: base.messages,
|
|
388
|
+
tools: input.tools ?? [],
|
|
389
|
+
context: input.context ?? [],
|
|
390
|
+
forwardedProps: input.forwardedProps ?? {}
|
|
391
|
+
}, {
|
|
392
|
+
runId,
|
|
393
|
+
initial: {
|
|
394
|
+
...base,
|
|
395
|
+
status: "running"
|
|
396
|
+
},
|
|
397
|
+
policy: runOptions?.policy
|
|
398
|
+
});
|
|
399
|
+
return runId;
|
|
400
|
+
},
|
|
401
|
+
abort,
|
|
402
|
+
getSnapshot: () => snapshot,
|
|
403
|
+
subscribe(listener) {
|
|
404
|
+
listeners.add(listener);
|
|
405
|
+
return () => {
|
|
406
|
+
listeners.delete(listener);
|
|
407
|
+
};
|
|
408
|
+
},
|
|
409
|
+
dispose() {
|
|
410
|
+
off();
|
|
411
|
+
runs.dispose();
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
416
|
+
export { applyAgUiEvent, applyPatch, createAgUiAgent };
|
|
417
|
+
|
|
418
|
+
//# sourceMappingURL=ag-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ag-ui.js","names":[],"sources":["../src/ag-ui.ts"],"sourcesContent":["// The build keeps `./core` external, so this entry shares the client with the others.\nimport {\n createWebSocketRuns,\n type RunPolicy,\n type RunStorage,\n type WebSocketClient,\n type WebSocketRuns\n} from './core';\n\n/** A JSON Patch (RFC 6902) operation, as in AG-UI's `STATE_DELTA` and `ACTIVITY_DELTA`. */\nexport interface JsonPatchOperation {\n readonly op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';\n /** A JSON Pointer (RFC 6901), such as `/items/0/name`. */\n readonly path: string;\n /** The source of `move` and `copy`. */\n readonly from?: string;\n /** The value to `add`, `replace` with or `test` for. */\n readonly value?: unknown;\n}\n\n/** An AG-UI event: `type` is `'RUN_STARTED'`, `'TEXT_MESSAGE_CONTENT'`, `'STATE_DELTA'`, … */\nexport interface AgUiEvent {\n readonly type: string;\n readonly [field: string]: any;\n}\n\n/** A tool call on an assistant message, as in AG-UI. */\nexport interface AgUiToolCall {\n readonly id: string;\n readonly type: 'function';\n readonly function: { readonly name: string; readonly arguments: string };\n}\n\n/** A message in an AG-UI thread. */\nexport interface AgUiMessage {\n readonly id: string;\n readonly role: 'developer' | 'system' | 'assistant' | 'user' | 'tool' | 'reasoning' | 'activity';\n readonly content?: unknown;\n readonly toolCalls?: readonly AgUiToolCall[];\n /** For a `tool` message, the call it answers. */\n readonly toolCallId?: string;\n /** For an `activity` message. */\n readonly activityType?: string;\n readonly [field: string]: unknown;\n}\n\n/** AG-UI's `RunAgentInput`: what a run starts from. */\nexport interface RunAgentInput {\n readonly threadId: string;\n readonly runId: string;\n readonly parentRunId?: string;\n readonly state?: unknown;\n readonly messages: readonly AgUiMessage[];\n readonly tools: readonly unknown[];\n readonly context: readonly unknown[];\n readonly forwardedProps: unknown;\n}\n\n/** A thread's messages and shared state, reduced from AG-UI events. */\nexport interface AgUiThread<S = unknown> {\n readonly messages: readonly AgUiMessage[];\n /** The shared state, from `STATE_SNAPSHOT` and `STATE_DELTA`. */\n readonly state: S;\n /**\n * `'running'` from `RUN_STARTED`, `'finished'` after `RUN_FINISHED`, `'error'` after\n * `RUN_ERROR`, `'aborted'` when the run was stopped from this side.\n */\n readonly status: 'idle' | 'running' | 'finished' | 'error' | 'aborted';\n /** The step in progress, between `STEP_STARTED` and `STEP_FINISHED`. */\n readonly step?: string;\n /** From `RUN_ERROR`. */\n readonly error?: { readonly message: string; readonly code?: string };\n /** From `RUN_FINISHED`. */\n readonly result?: unknown;\n /**\n * A `STATE_DELTA` couldn't be applied. `state` is the last good one, and later deltas are\n * skipped until a `STATE_SNAPSHOT` arrives.\n */\n readonly stale: boolean;\n}\n\ntype Json = any;\n\nfunction unescape(token: string) {\n return token.replace(/~1/g, '/').replace(/~0/g, '~');\n}\n\nfunction equal(a: Json, b: Json): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || !a || !b) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n const keys = Object.keys(a);\n return keys.length === Object.keys(b).length && keys.every(key => equal(a[key], b[key]));\n}\n\nfunction fail(operation: JsonPatchOperation): never {\n throw new Error(`JSON Patch failed: ${operation.op} ${operation.path}`);\n}\n\nconst INDEX = /^(0|[1-9]\\d*)$/;\n\n/** A JSON Pointer's tokens. It's empty, for the whole document, or starts with `/`. */\nfunction tokens(pointer: string, operation: JsonPatchOperation) {\n if (pointer !== '' && pointer[0] !== '/') fail(operation);\n return pointer.split('/').slice(1).map(unescape);\n}\n\n/** Whether `node` has `token`: an index in range for an array, not `length`; an own key otherwise. */\nfunction has(node: Json, token: string) {\n return Array.isArray(node)\n ? INDEX.test(token) && +token < node.length\n : Object.hasOwn(node, token);\n}\n\n/** Set an own property, even `__proto__`, as JSON.parse would. */\nfunction put(object: Json, key: string, value: Json) {\n Object.defineProperty(object, key, {\n value,\n writable: true,\n enumerable: true,\n configurable: true\n });\n}\n\n/**\n * Apply a JSON Patch (RFC 6902) without changing `document`: what changes is copied, the rest is\n * shared. Throws, leaving `document` as it was, if an operation can't be applied: a missing path,\n * an index out of range, a pointer that doesn't start with `/`, or a failed `test`.\n */\nexport function applyPatch<T>(document: T, operations: readonly JsonPatchOperation[]): T {\n let root: Json = document;\n\n function get(path: string, operation: JsonPatchOperation): Json {\n let node = root;\n for (const token of tokens(path, operation)) {\n if (typeof node !== 'object' || node === null || !has(node, token)) fail(operation);\n node = node[token];\n }\n return node;\n }\n\n // Replace the parent of `path` with a copy, change it with `change`, and copy its ancestors.\n function edit(\n path: string,\n operation: JsonPatchOperation,\n change: (parent: Json, key: string) => void\n ) {\n const keys = tokens(path, operation);\n if (!keys.length) fail(operation);\n const walk = (node: Json, depth: number): Json => {\n if (typeof node !== 'object' || node === null) fail(operation);\n const copy = Array.isArray(node) ? [...node] : { ...node };\n const key = keys[depth]!;\n if (depth === keys.length - 1) change(copy, key);\n else if (!has(node, key)) fail(operation);\n else copy[key] = walk(node[key], depth + 1);\n return copy;\n };\n root = walk(root, 0);\n }\n\n function index(parent: Json[], key: string, operation: JsonPatchOperation, adding: boolean) {\n // `-` is the end of the array, which only `add` can use.\n const i = key === '-' ? (adding ? parent.length : -1) : INDEX.test(key) ? +key : -1;\n if (i < 0 || i > parent.length - (adding ? 0 : 1)) fail(operation);\n return i;\n }\n\n function add(path: string, value: Json, operation: JsonPatchOperation) {\n if (path === '') return void (root = value);\n edit(path, operation, (parent, key) => {\n if (Array.isArray(parent)) parent.splice(index(parent, key, operation, true), 0, value);\n else put(parent, key, value);\n });\n }\n\n function remove(path: string, operation: JsonPatchOperation) {\n edit(path, operation, (parent, key) => {\n if (Array.isArray(parent)) parent.splice(index(parent, key, operation, false), 1);\n else if (Object.hasOwn(parent, key)) delete parent[key];\n else fail(operation);\n });\n }\n\n for (const operation of operations) {\n const { op, path, from, value } = operation;\n if (op === 'add') add(path, value, operation);\n else if (op === 'remove') remove(path, operation);\n else if (op === 'replace') {\n get(path, operation);\n if (path === '') root = value;\n else\n edit(path, operation, (parent, key) => {\n if (Array.isArray(parent)) parent[key as unknown as number] = value;\n else put(parent, key, value);\n });\n } else if (op === 'move' || op === 'copy') {\n const moved = get(from ?? fail(operation), operation);\n if (op === 'move') remove(from!, operation);\n add(path, op === 'copy' ? structuredClone(moved) : moved, operation);\n } else if (op === 'test') {\n if (!equal(get(path, operation), value)) fail(operation);\n } else fail(operation);\n }\n return root;\n}\n\nfunction updateMessage(\n thread: AgUiThread<any>,\n id: string | undefined,\n change: (message: AgUiMessage) => AgUiMessage\n) {\n return thread.messages.map(message => (message.id === id ? change(message) : message));\n}\n\nfunction appendText(message: AgUiMessage, delta: string | undefined) {\n return { ...message, content: `${(message.content as string | undefined) ?? ''}${delta ?? ''}` };\n}\n\nfunction updateToolCall(\n thread: AgUiThread<any>,\n id: string | undefined,\n change: (call: AgUiToolCall) => AgUiToolCall\n) {\n return thread.messages.map(message =>\n message.toolCalls?.some(call => call.id === id)\n ? {\n ...message,\n toolCalls: message.toolCalls.map(call => (call.id === id ? change(call) : call))\n }\n : message\n );\n}\n\n/** The last message with a tool call, for chunks that leave out `toolCallId`. */\nfunction lastToolCallId(thread: AgUiThread<any>) {\n for (let i = thread.messages.length - 1; i >= 0; i--) {\n const calls = thread.messages[i]!.toolCalls;\n if (calls?.length) return calls.at(-1)!.id;\n }\n}\n\n/**\n * Fold one AG-UI event into a thread, without changing it. Handles the run lifecycle, steps,\n * text, tool calls and their results, reasoning, activity, and message and state snapshots and\n * deltas. A `STATE_DELTA` that can't be applied marks the thread `stale` instead of throwing.\n * Other events, such as `CUSTOM` and `RAW`, return the thread unchanged.\n *\n * Use it as a `reduce` function, or wrap it to handle events of your own.\n */\nexport function applyAgUiEvent<S>(thread: AgUiThread<S>, event: AgUiEvent): AgUiThread<S> {\n const e = event;\n const message = (role: AgUiMessage['role'], extra?: object): AgUiThread<S> => ({\n ...thread,\n messages: [...thread.messages, { id: e.messageId, role, content: '', ...extra }]\n });\n const known = (id: string | undefined) => thread.messages.some(m => m.id === id);\n switch (e.type) {\n case 'RUN_STARTED':\n return { ...thread, status: 'running', error: undefined, result: undefined };\n case 'RUN_FINISHED':\n return { ...thread, status: 'finished', step: undefined, result: e.result };\n case 'RUN_ERROR':\n return {\n ...thread,\n status: 'error',\n step: undefined,\n error: { message: e.message, code: e.code }\n };\n case 'STEP_STARTED':\n return { ...thread, step: e.stepName };\n case 'STEP_FINISHED':\n return { ...thread, step: undefined };\n case 'TEXT_MESSAGE_START':\n return message(e.role ?? 'assistant');\n case 'REASONING_MESSAGE_START':\n return message('reasoning');\n case 'TEXT_MESSAGE_CONTENT':\n case 'REASONING_MESSAGE_CONTENT':\n return {\n ...thread,\n messages: updateMessage(thread, e.messageId, m => appendText(m, e.delta))\n };\n case 'TEXT_MESSAGE_CHUNK':\n case 'REASONING_MESSAGE_CHUNK': {\n // Only the first chunk of a message must carry its id.\n const id = e.messageId ?? thread.messages.at(-1)?.id;\n const role = e.type === 'TEXT_MESSAGE_CHUNK' ? (e.role ?? 'assistant') : 'reasoning';\n const next = known(id) ? thread : message(role);\n return { ...next, messages: updateMessage(next, id, m => appendText(m, e.delta)) };\n }\n case 'TOOL_CALL_START':\n case 'TOOL_CALL_CHUNK': {\n const id = e.toolCallId ?? lastToolCallId(thread);\n let next = thread;\n if (\n e.type === 'TOOL_CALL_START' ||\n !thread.messages.some(m => m.toolCalls?.some(c => c.id === id))\n ) {\n const call: AgUiToolCall = {\n id,\n type: 'function',\n function: { name: e.toolCallName, arguments: '' }\n };\n const parent = e.parentMessageId ?? id;\n next = known(parent)\n ? thread\n : { ...thread, messages: [...thread.messages, { id: parent, role: 'assistant' }] };\n next = {\n ...next,\n messages: updateMessage(next, parent, m => ({\n ...m,\n toolCalls: [...(m.toolCalls ?? []), call]\n }))\n };\n }\n if (e.type === 'TOOL_CALL_START') return next;\n return toolArgs(next, id, e.delta);\n }\n case 'TOOL_CALL_ARGS':\n return toolArgs(thread, e.toolCallId, e.delta);\n case 'TOOL_CALL_RESULT':\n return message(e.role ?? 'tool', { toolCallId: e.toolCallId, content: e.content });\n case 'STATE_SNAPSHOT':\n return { ...thread, state: e.snapshot, stale: false };\n case 'STATE_DELTA':\n if (thread.stale) return thread;\n try {\n return { ...thread, state: applyPatch(thread.state, e.delta) };\n } catch {\n return { ...thread, stale: true };\n }\n case 'MESSAGES_SNAPSHOT':\n return { ...thread, messages: e.messages };\n case 'ACTIVITY_SNAPSHOT': {\n if (known(e.messageId) && e.replace === false) return thread;\n const next = known(e.messageId) ? thread : message('activity');\n return {\n ...next,\n messages: updateMessage(next, e.messageId, m => ({\n ...m,\n activityType: e.activityType,\n content: e.content\n }))\n };\n }\n case 'ACTIVITY_DELTA':\n try {\n return {\n ...thread,\n messages: updateMessage(thread, e.messageId, m => ({\n ...m,\n content: applyPatch(m.content, e.patch)\n }))\n };\n } catch {\n return thread;\n }\n default:\n return thread;\n }\n}\n\nfunction toolArgs<S>(thread: AgUiThread<S>, id: string | undefined, delta: string | undefined) {\n return {\n ...thread,\n messages: updateToolCall(thread, id, call => ({\n ...call,\n function: { ...call.function, arguments: call.function.arguments + (delta ?? '') }\n }))\n };\n}\n\n/** What the server sends for each event of a run: its run, its offset (from 1), and the event. */\nexport interface AgUiEnvelope {\n readonly runId: string;\n readonly offset: number;\n readonly event: AgUiEvent;\n}\n\n/** Options for {@link createAgUiAgent}. The message formats have defaults; see the guide. */\nexport interface AgUiAgentOptions<S, In, Out> {\n /** The thread's id, sent in every `RunAgentInput`. A new random one by default. */\n threadId?: string;\n /** The shared state before the first `STATE_SNAPSHOT`, sent with the first run. */\n state?: S;\n /** Names where streaming runs are remembered across reloads. @default 'ag-ui' */\n name?: string;\n /** @default `{ type: 'run', runId, input }` */\n run?: (input: RunAgentInput, runId: string) => Out;\n /** @default `{ type: 'resume', runId, after }` */\n resume?: (runId: string, after: number | undefined) => Out;\n /** @default `{ type: 'cancel', runId }` */\n cancel?: (runId: string) => Out;\n /**\n * The message that asks the server for a `STATE_SNAPSHOT`, sent when a `STATE_DELTA` can't\n * be applied. Without it, the state stays `stale` until the server sends one by itself.\n */\n resync?: (runId: string) => Out;\n /** Recognize a run's event. @default messages shaped like {@link AgUiEnvelope} */\n event?: (message: In) => AgUiEnvelope | null | undefined;\n /** What happens to a run when its connection drops. @default 'keep' */\n policy?: RunPolicy;\n /** Where streaming runs are remembered. @default sessionStorage */\n storage?: RunStorage | null;\n}\n\n/** An AG-UI agent over a WebSocket. Create with {@link createAgUiAgent}. */\nexport interface AgUiAgent<S> {\n /** The client the runs stream on. */\n readonly client: WebSocketClient<any, any>;\n /** The runs underneath, from `createWebSocketRuns`. */\n readonly runs: WebSocketRuns<RunAgentInput, AgUiThread<S>>;\n /**\n * Start a run with the thread so far plus `input.messages`, which show up in the thread right\n * away. A run that's still streaming is aborted first. Returns the run's id.\n */\n run(\n input?: {\n messages?: readonly AgUiMessage[];\n tools?: readonly unknown[];\n context?: readonly unknown[];\n forwardedProps?: unknown;\n },\n options?: { policy?: RunPolicy }\n ): string;\n /** Stop the run that's streaming, if any. */\n abort(): void;\n /** The thread as of the latest run. The same object until it changes. */\n getSnapshot(): AgUiThread<S>;\n /** Get notified when the thread changes. Compatible with `useSyncExternalStore`. */\n subscribe(listener: () => void): () => void;\n /** Stop following runs, and release the connection. */\n dispose(): void;\n}\n\nfunction randomId() {\n return (\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`\n );\n}\n\nconst isEnvelope = (message: any): AgUiEnvelope | undefined =>\n typeof message?.runId === 'string' &&\n typeof message.offset === 'number' &&\n typeof message.event?.type === 'string'\n ? message\n : undefined;\n\nconst ENDS = new Set(['RUN_FINISHED', 'RUN_ERROR']);\n\n/**\n * Run an [AG-UI](https://docs.ag-ui.com) agent over a WebSocket. Each run streams AG-UI events,\n * which are folded into the thread's messages and shared state with {@link applyAgUiEvent}.\n * Runs come from `createWebSocketRuns`, so they resume after a reconnect or a reload, and a\n * state delta that can't be applied asks for a snapshot (`resync`).\n *\n * AG-UI doesn't define messages for WebSockets, so the defaults are small: the client sends\n * `{ type: 'run', runId, input }`, `{ type: 'resume', runId, after }` and\n * `{ type: 'cancel', runId }`, and the server sends `{ runId, offset, event }`, with `offset`\n * counting each run's events from 1. Each option replaces one of them.\n *\n * @example\n * ```ts\n * import { createAgUiAgent } from 'react-websocket/ag-ui';\n *\n * export const agent = createAgUiAgent(createWebSocket(url, { json: true }));\n *\n * agent.run({ messages: [{ id: crypto.randomUUID(), role: 'user', content: 'Plan my week' }] });\n * ```\n */\nexport function createAgUiAgent<S = unknown, In = any, Out = any>(\n client: WebSocketClient<In, Out>,\n options: AgUiAgentOptions<S, NoInfer<In>, NoInfer<Out>> = {}\n): AgUiAgent<S> {\n const threadId = options.threadId ?? randomId();\n const empty: AgUiThread<S> = {\n messages: [],\n state: options.state as S,\n status: 'idle',\n stale: false\n };\n let base = empty;\n let snapshot = empty;\n const listeners = new Set<() => void>();\n // Runs that asked for a snapshot after a failed delta, until one arrives.\n const resynced = new Set<string>();\n const event = options.event ?? isEnvelope;\n // Now or never: not queued, and not `volatile`, which can be a datagram that never arrives.\n const send = (message: unknown) => client.socket?.readyState === 1 && client.send(message as Out);\n\n const runs = createWebSocketRuns<RunAgentInput, AgUiThread<S>, In, Out>(client, {\n name: options.name ?? 'ag-ui',\n start: options.run ?? ((input, runId) => ({ type: 'run', runId, input }) as Out),\n resume: options.resume ?? ((runId, after) => ({ type: 'resume', runId, after }) as Out),\n cancel: options.cancel ?? (runId => ({ type: 'cancel', runId }) as Out),\n event: message => event(message),\n done: message => ENDS.has(event(message)!.event.type),\n initial: empty,\n reduce: (thread, message) => applyAgUiEvent(thread, event(message)!.event),\n policy: options.policy,\n storage: options.storage\n });\n\n function update() {\n const latest = runs.list().at(-1);\n let next = latest ? latest.value : base;\n if (latest?.status === 'aborted' && next.status === 'running')\n next = { ...next, status: 'aborted' };\n // Once each time the state goes stale, or on a later event if the socket wasn't open.\n if (latest && !latest.value.stale) resynced.delete(latest.runId);\n else if (latest && options.resync && !resynced.has(latest.runId)) {\n if (send(options.resync(latest.runId))) resynced.add(latest.runId);\n }\n if (next === snapshot) return;\n snapshot = next;\n for (const listener of [...listeners]) listener();\n }\n const off = runs.subscribe(update);\n update();\n\n function abort() {\n for (const run of runs.list()) runs.abort(run.runId);\n }\n\n return {\n client,\n runs,\n run(input = {}, runOptions) {\n abort();\n const runId = randomId();\n // The run starts from the state sent with it, the last good one: its deltas apply to it.\n base = {\n ...snapshot,\n stale: false,\n messages: [...snapshot.messages, ...(input.messages ?? [])]\n };\n runs.start(\n {\n threadId,\n runId,\n state: base.state,\n messages: base.messages,\n tools: input.tools ?? [],\n context: input.context ?? [],\n forwardedProps: input.forwardedProps ?? {}\n },\n { runId, initial: { ...base, status: 'running' }, policy: runOptions?.policy }\n );\n return runId;\n },\n abort,\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n dispose() {\n off();\n runs.dispose();\n }\n };\n}\n"],"mappings":"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"}
|