@copilotkit/runtime 1.66.2 → 1.66.3
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/agent/converters/aisdk.cjs +17 -9
- package/dist/agent/converters/aisdk.cjs.map +1 -1
- package/dist/agent/converters/aisdk.d.cts +1 -1
- package/dist/agent/converters/aisdk.d.cts.map +1 -1
- package/dist/agent/converters/aisdk.d.mts +1 -1
- package/dist/agent/converters/aisdk.d.mts.map +1 -1
- package/dist/agent/converters/aisdk.mjs +17 -9
- package/dist/agent/converters/aisdk.mjs.map +1 -1
- package/dist/agent/converters/tanstack.cjs +17 -9
- package/dist/agent/converters/tanstack.cjs.map +1 -1
- package/dist/agent/converters/tanstack.d.cts +1 -1
- package/dist/agent/converters/tanstack.d.cts.map +1 -1
- package/dist/agent/converters/tanstack.d.mts +1 -1
- package/dist/agent/converters/tanstack.d.mts.map +1 -1
- package/dist/agent/converters/tanstack.mjs +17 -9
- package/dist/agent/converters/tanstack.mjs.map +1 -1
- package/dist/agent/index.cjs +6 -4
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +6 -4
- package/dist/agent/index.mjs.map +1 -1
- package/dist/agent/state-delta.cjs +322 -0
- package/dist/agent/state-delta.cjs.map +1 -0
- package/dist/agent/state-delta.mjs +321 -0
- package/dist/agent/state-delta.mjs.map +1 -0
- package/dist/package.cjs +1 -1
- package/dist/runtime/package.mjs +1 -1
- package/dist/v2/index.cjs +6 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/runtime/core/channel-manager.cjs +110 -9
- package/dist/v2/runtime/core/channel-manager.cjs.map +1 -1
- package/dist/v2/runtime/core/channel-manager.d.cts +79 -8
- package/dist/v2/runtime/core/channel-manager.d.cts.map +1 -1
- package/dist/v2/runtime/core/channel-manager.d.mts +79 -8
- package/dist/v2/runtime/core/channel-manager.d.mts.map +1 -1
- package/dist/v2/runtime/core/channel-manager.mjs +110 -9
- package/dist/v2/runtime/core/channel-manager.mjs.map +1 -1
- package/dist/v2/runtime/core/runtime.cjs.map +1 -1
- package/dist/v2/runtime/core/runtime.d.cts +1 -0
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts +1 -0
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/core/runtime.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs +2 -5
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs +2 -5
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/mcp-apps-servers.cjs +23 -0
- package/dist/v2/runtime/handlers/shared/mcp-apps-servers.cjs.map +1 -0
- package/dist/v2/runtime/handlers/shared/mcp-apps-servers.mjs +22 -0
- package/dist/v2/runtime/handlers/shared/mcp-apps-servers.mjs.map +1 -0
- package/dist/v2/runtime/index.d.cts +1 -1
- package/dist/v2/runtime/index.d.mts +1 -1
- package/dist/v2/runtime/open-generative-ui-middleware.cjs +1 -0
- package/dist/v2/runtime/open-generative-ui-middleware.cjs.map +1 -1
- package/dist/v2/runtime/open-generative-ui-middleware.mjs +1 -0
- package/dist/v2/runtime/open-generative-ui-middleware.mjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.cjs +335 -101
- package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.cts +246 -6
- package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.mts +246 -6
- package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.mjs +331 -102
- package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
- package/dist/v2/runtime/runner/index.d.cts +1 -1
- package/dist/v2/runtime/runner/index.d.mts +1 -1
- package/dist/v2/runtime/runner/index.mjs +1 -1
- package/package.json +6 -6
- package/skills/runtime/references/agent-runners-in-memory.md +49 -34
- package/skills/runtime/references/agent-runners.md +47 -21
- package/skills/runtime/references/wiring-mcp-apps-middleware.md +5 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
require("reflect-metadata");
|
|
2
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
|
+
let _ag_ui_client = require("@ag-ui/client");
|
|
4
|
+
|
|
5
|
+
//#region src/agent/state-delta.ts
|
|
6
|
+
function parseJsonPointer(pointer) {
|
|
7
|
+
if (pointer === "") return [];
|
|
8
|
+
if (!pointer.startsWith("/")) return void 0;
|
|
9
|
+
const segments = pointer.slice(1).split("/");
|
|
10
|
+
if (segments.some((segment) => /~(?![01])/.test(segment))) return;
|
|
11
|
+
return segments.map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
12
|
+
}
|
|
13
|
+
function encodeJsonPointer(segments) {
|
|
14
|
+
if (segments.length === 0) return "";
|
|
15
|
+
return `/${segments.map((segment) => segment.replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
|
|
16
|
+
}
|
|
17
|
+
function getArrayIndex(segment, length) {
|
|
18
|
+
if (segment !== "0" && !/^[1-9]\d*$/.test(segment)) return void 0;
|
|
19
|
+
const index = Number(segment);
|
|
20
|
+
return Number.isSafeInteger(index) && index < length ? index : void 0;
|
|
21
|
+
}
|
|
22
|
+
function getJsonPointerValue(root, pointer) {
|
|
23
|
+
const segments = parseJsonPointer(pointer);
|
|
24
|
+
if (segments === void 0) return { exists: false };
|
|
25
|
+
let current = root;
|
|
26
|
+
for (const segment of segments) {
|
|
27
|
+
if (current === null || typeof current !== "object") return { exists: false };
|
|
28
|
+
if (Array.isArray(current)) {
|
|
29
|
+
const index = getArrayIndex(segment, current.length);
|
|
30
|
+
if (index === void 0) return { exists: false };
|
|
31
|
+
current = current[index];
|
|
32
|
+
} else {
|
|
33
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) return { exists: false };
|
|
34
|
+
current = current[segment];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
exists: true,
|
|
39
|
+
value: current
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function getParent(root, segments) {
|
|
43
|
+
return getJsonPointerValue(root, encodeJsonPointer(segments.slice(0, -1)));
|
|
44
|
+
}
|
|
45
|
+
function cloneStateFallback(state, seen = /* @__PURE__ */ new WeakMap()) {
|
|
46
|
+
if (state === null || typeof state !== "object") return state;
|
|
47
|
+
const existing = seen.get(state);
|
|
48
|
+
if (existing !== void 0) return existing;
|
|
49
|
+
let clone;
|
|
50
|
+
try {
|
|
51
|
+
clone = Array.isArray(state) ? [] : Object.create(Object.getPrototypeOf(state));
|
|
52
|
+
} catch {
|
|
53
|
+
clone = Array.isArray(state) ? [] : {};
|
|
54
|
+
}
|
|
55
|
+
seen.set(state, clone);
|
|
56
|
+
let keys = [];
|
|
57
|
+
try {
|
|
58
|
+
keys = Reflect.ownKeys(state);
|
|
59
|
+
} catch {
|
|
60
|
+
return clone;
|
|
61
|
+
}
|
|
62
|
+
for (const key of keys) try {
|
|
63
|
+
const descriptor = Object.getOwnPropertyDescriptor(state, key);
|
|
64
|
+
if (!descriptor) continue;
|
|
65
|
+
if ("value" in descriptor) descriptor.value = cloneStateFallback(descriptor.value, seen);
|
|
66
|
+
Object.defineProperty(clone, key, descriptor);
|
|
67
|
+
} catch {}
|
|
68
|
+
return clone;
|
|
69
|
+
}
|
|
70
|
+
function cloneState(state) {
|
|
71
|
+
try {
|
|
72
|
+
return structuredClone(state);
|
|
73
|
+
} catch {
|
|
74
|
+
return cloneStateFallback(state);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function addValue(root, segments, value) {
|
|
78
|
+
if (segments.length === 0) return {
|
|
79
|
+
root: cloneState(value),
|
|
80
|
+
applied: true
|
|
81
|
+
};
|
|
82
|
+
const parent = getParent(root, segments);
|
|
83
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
84
|
+
root,
|
|
85
|
+
applied: false
|
|
86
|
+
};
|
|
87
|
+
const segment = segments[segments.length - 1];
|
|
88
|
+
if (Array.isArray(parent.value)) {
|
|
89
|
+
if (segment === "-") {
|
|
90
|
+
parent.value.push(cloneState(value));
|
|
91
|
+
return {
|
|
92
|
+
root,
|
|
93
|
+
applied: true
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const index = segment === "0" ? 0 : /^[1-9]\d*$/.test(segment) ? Number(segment) : void 0;
|
|
97
|
+
if (index === void 0 || !Number.isSafeInteger(index) || index > parent.value.length) return {
|
|
98
|
+
root,
|
|
99
|
+
applied: false
|
|
100
|
+
};
|
|
101
|
+
parent.value.splice(index, 0, cloneState(value));
|
|
102
|
+
return {
|
|
103
|
+
root,
|
|
104
|
+
applied: true
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
parent.value[segment] = cloneState(value);
|
|
108
|
+
return {
|
|
109
|
+
root,
|
|
110
|
+
applied: true
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function removeValue(root, segments) {
|
|
114
|
+
if (segments.length === 0) return {
|
|
115
|
+
root: void 0,
|
|
116
|
+
applied: true
|
|
117
|
+
};
|
|
118
|
+
const parent = getParent(root, segments);
|
|
119
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
120
|
+
root,
|
|
121
|
+
applied: false
|
|
122
|
+
};
|
|
123
|
+
const segment = segments[segments.length - 1];
|
|
124
|
+
if (Array.isArray(parent.value)) {
|
|
125
|
+
const index = getArrayIndex(segment, parent.value.length);
|
|
126
|
+
if (index === void 0) return {
|
|
127
|
+
root,
|
|
128
|
+
applied: false
|
|
129
|
+
};
|
|
130
|
+
parent.value.splice(index, 1);
|
|
131
|
+
return {
|
|
132
|
+
root,
|
|
133
|
+
applied: true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) return {
|
|
137
|
+
root,
|
|
138
|
+
applied: false
|
|
139
|
+
};
|
|
140
|
+
delete parent.value[segment];
|
|
141
|
+
return {
|
|
142
|
+
root,
|
|
143
|
+
applied: true
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function replaceValue(root, segments, value) {
|
|
147
|
+
if (segments.length === 0) return {
|
|
148
|
+
root: cloneState(value),
|
|
149
|
+
applied: true
|
|
150
|
+
};
|
|
151
|
+
const parent = getParent(root, segments);
|
|
152
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
153
|
+
root,
|
|
154
|
+
applied: false
|
|
155
|
+
};
|
|
156
|
+
const segment = segments[segments.length - 1];
|
|
157
|
+
if (Array.isArray(parent.value)) {
|
|
158
|
+
const index = getArrayIndex(segment, parent.value.length);
|
|
159
|
+
if (index === void 0) return {
|
|
160
|
+
root,
|
|
161
|
+
applied: false
|
|
162
|
+
};
|
|
163
|
+
parent.value[index] = cloneState(value);
|
|
164
|
+
return {
|
|
165
|
+
root,
|
|
166
|
+
applied: true
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) return {
|
|
170
|
+
root,
|
|
171
|
+
applied: false
|
|
172
|
+
};
|
|
173
|
+
parent.value[segment] = cloneState(value);
|
|
174
|
+
return {
|
|
175
|
+
root,
|
|
176
|
+
applied: true
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function jsonValueEqual(left, right) {
|
|
180
|
+
if (Object.is(left, right)) return true;
|
|
181
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
182
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
183
|
+
const leftKeys = Object.keys(left);
|
|
184
|
+
const rightKeys = Object.keys(right);
|
|
185
|
+
if (leftKeys.length !== rightKeys.length) return false;
|
|
186
|
+
return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && jsonValueEqual(left[key], right[key]));
|
|
187
|
+
}
|
|
188
|
+
function applyStateDeltaOperation(root, operation) {
|
|
189
|
+
if (typeof operation.path !== "string") return {
|
|
190
|
+
root,
|
|
191
|
+
applied: false
|
|
192
|
+
};
|
|
193
|
+
const path = parseJsonPointer(operation.path);
|
|
194
|
+
if (path === void 0) return {
|
|
195
|
+
root,
|
|
196
|
+
applied: false
|
|
197
|
+
};
|
|
198
|
+
switch (operation.op) {
|
|
199
|
+
case "add": return addValue(root, path, operation.value);
|
|
200
|
+
case "remove": return removeValue(root, path);
|
|
201
|
+
case "replace": return replaceValue(root, path, operation.value);
|
|
202
|
+
case "test": {
|
|
203
|
+
const actual = getJsonPointerValue(root, operation.path);
|
|
204
|
+
return {
|
|
205
|
+
root,
|
|
206
|
+
applied: actual.exists && jsonValueEqual(actual.value, operation.value)
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
case "copy": {
|
|
210
|
+
if (typeof operation.from !== "string") return {
|
|
211
|
+
root,
|
|
212
|
+
applied: false
|
|
213
|
+
};
|
|
214
|
+
const source = getJsonPointerValue(root, operation.from);
|
|
215
|
+
if (!source.exists) return {
|
|
216
|
+
root,
|
|
217
|
+
applied: false
|
|
218
|
+
};
|
|
219
|
+
return addValue(root, path, source.value);
|
|
220
|
+
}
|
|
221
|
+
case "move": {
|
|
222
|
+
if (typeof operation.from !== "string") return {
|
|
223
|
+
root,
|
|
224
|
+
applied: false
|
|
225
|
+
};
|
|
226
|
+
const from = parseJsonPointer(operation.from);
|
|
227
|
+
if (from === void 0) return {
|
|
228
|
+
root,
|
|
229
|
+
applied: false
|
|
230
|
+
};
|
|
231
|
+
const source = getJsonPointerValue(root, operation.from);
|
|
232
|
+
if (!source.exists) return {
|
|
233
|
+
root,
|
|
234
|
+
applied: false
|
|
235
|
+
};
|
|
236
|
+
if (operation.from === operation.path) return {
|
|
237
|
+
root,
|
|
238
|
+
applied: true
|
|
239
|
+
};
|
|
240
|
+
const removed = removeValue(cloneState(root), from);
|
|
241
|
+
if (!removed.applied) return {
|
|
242
|
+
root,
|
|
243
|
+
applied: false
|
|
244
|
+
};
|
|
245
|
+
const added = addValue(removed.root, path, source.value);
|
|
246
|
+
return added.applied ? added : {
|
|
247
|
+
root,
|
|
248
|
+
applied: false
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
default: return {
|
|
252
|
+
root,
|
|
253
|
+
applied: false
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function normalizeStateDelta(delta, initialState) {
|
|
258
|
+
let state = cloneState(initialState);
|
|
259
|
+
const normalized = [];
|
|
260
|
+
for (const operation of delta) {
|
|
261
|
+
const candidate = operation !== null && typeof operation === "object" ? operation : void 0;
|
|
262
|
+
if (candidate?.op === "add" && typeof candidate.path === "string" && candidate.path.endsWith("/-")) {
|
|
263
|
+
const arrayPath = candidate.path.slice(0, -2);
|
|
264
|
+
if (!getJsonPointerValue(state, arrayPath).exists) {
|
|
265
|
+
const lastSlash = arrayPath.lastIndexOf("/");
|
|
266
|
+
const parentPath = lastSlash > 0 ? arrayPath.slice(0, lastSlash) : "";
|
|
267
|
+
if (getJsonPointerValue(state, parentPath).exists) {
|
|
268
|
+
const initializer = {
|
|
269
|
+
op: "add",
|
|
270
|
+
path: arrayPath,
|
|
271
|
+
value: []
|
|
272
|
+
};
|
|
273
|
+
const applied = applyStateDeltaOperation(state, initializer);
|
|
274
|
+
if (applied.applied) {
|
|
275
|
+
normalized.push(initializer);
|
|
276
|
+
state = applied.root;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
normalized.push(operation);
|
|
282
|
+
if (candidate) {
|
|
283
|
+
const applied = applyStateDeltaOperation(state, candidate);
|
|
284
|
+
if (applied.applied) state = applied.root;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
delta: normalized,
|
|
289
|
+
state
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function createStateEventNormalizer(initialState) {
|
|
293
|
+
let state = cloneState(initialState);
|
|
294
|
+
let hasEmittedState = false;
|
|
295
|
+
return (event) => {
|
|
296
|
+
if (event.type === _ag_ui_client.EventType.STATE_SNAPSHOT) {
|
|
297
|
+
state = cloneState(event.snapshot);
|
|
298
|
+
hasEmittedState = true;
|
|
299
|
+
return [event];
|
|
300
|
+
}
|
|
301
|
+
if (event.type !== _ag_ui_client.EventType.STATE_DELTA) return [event];
|
|
302
|
+
const stateDeltaEvent = event;
|
|
303
|
+
const initialSnapshot = !hasEmittedState && initialState !== void 0 ? [{
|
|
304
|
+
type: _ag_ui_client.EventType.STATE_SNAPSHOT,
|
|
305
|
+
snapshot: cloneState(state)
|
|
306
|
+
}] : [];
|
|
307
|
+
const normalized = Array.isArray(stateDeltaEvent.delta) ? normalizeStateDelta(stateDeltaEvent.delta, state) : {
|
|
308
|
+
delta: stateDeltaEvent.delta,
|
|
309
|
+
state
|
|
310
|
+
};
|
|
311
|
+
state = normalized.state;
|
|
312
|
+
hasEmittedState = true;
|
|
313
|
+
return [...initialSnapshot, {
|
|
314
|
+
...stateDeltaEvent,
|
|
315
|
+
delta: normalized.delta
|
|
316
|
+
}];
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
//#endregion
|
|
321
|
+
exports.createStateEventNormalizer = createStateEventNormalizer;
|
|
322
|
+
//# sourceMappingURL=state-delta.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-delta.cjs","names":["EventType"],"sources":["../../src/agent/state-delta.ts"],"sourcesContent":["import type {\n BaseEvent,\n StateDeltaEvent,\n StateSnapshotEvent,\n} from \"@ag-ui/client\";\nimport { EventType } from \"@ag-ui/client\";\n\ntype StateDeltaOperation = {\n op?: string;\n path?: string;\n from?: string;\n value?: unknown;\n};\n\ntype PointerResult = {\n exists: boolean;\n value?: unknown;\n};\n\ntype OperationResult = {\n root: unknown;\n applied: boolean;\n};\n\nfunction parseJsonPointer(pointer: string): string[] | undefined {\n if (pointer === \"\") return [];\n if (!pointer.startsWith(\"/\")) return undefined;\n\n const segments = pointer.slice(1).split(\"/\");\n if (segments.some((segment) => /~(?![01])/.test(segment))) {\n return undefined;\n }\n\n return segments.map((segment) =>\n segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"),\n );\n}\n\nfunction encodeJsonPointer(segments: string[]): string {\n if (segments.length === 0) return \"\";\n return `/${segments\n .map((segment) => segment.replace(/~/g, \"~0\").replace(/\\//g, \"~1\"))\n .join(\"/\")}`;\n}\n\nfunction getArrayIndex(segment: string, length: number): number | undefined {\n if (segment !== \"0\" && !/^[1-9]\\d*$/.test(segment)) return undefined;\n const index = Number(segment);\n return Number.isSafeInteger(index) && index < length ? index : undefined;\n}\n\nfunction getJsonPointerValue(root: unknown, pointer: string): PointerResult {\n const segments = parseJsonPointer(pointer);\n if (segments === undefined) return { exists: false };\n\n let current = root;\n for (const segment of segments) {\n if (current === null || typeof current !== \"object\") {\n return { exists: false };\n }\n\n if (Array.isArray(current)) {\n const index = getArrayIndex(segment, current.length);\n if (index === undefined) return { exists: false };\n current = current[index];\n } else {\n if (!Object.prototype.hasOwnProperty.call(current, segment)) {\n return { exists: false };\n }\n current = (current as Record<string, unknown>)[segment];\n }\n }\n\n return { exists: true, value: current };\n}\n\nfunction getParent(root: unknown, segments: string[]): PointerResult {\n return getJsonPointerValue(root, encodeJsonPointer(segments.slice(0, -1)));\n}\n\nfunction cloneStateFallback(\n state: unknown,\n seen = new WeakMap<object, unknown>(),\n): unknown {\n if (state === null || typeof state !== \"object\") return state;\n\n const existing = seen.get(state);\n if (existing !== undefined) return existing;\n\n let clone: object;\n try {\n clone = Array.isArray(state)\n ? []\n : Object.create(Object.getPrototypeOf(state));\n } catch {\n clone = Array.isArray(state) ? [] : {};\n }\n seen.set(state, clone);\n\n let keys: (string | symbol)[] = [];\n try {\n keys = Reflect.ownKeys(state);\n } catch {\n return clone;\n }\n\n for (const key of keys) {\n try {\n const descriptor = Object.getOwnPropertyDescriptor(state, key);\n if (!descriptor) continue;\n if (\"value\" in descriptor) {\n descriptor.value = cloneStateFallback(descriptor.value, seen);\n }\n Object.defineProperty(clone, key, descriptor);\n } catch {\n // Keep the cloned container distinct when a property is inaccessible.\n }\n }\n\n return clone;\n}\n\nfunction cloneState(state: unknown): unknown {\n try {\n return structuredClone(state);\n } catch {\n return cloneStateFallback(state);\n }\n}\n\nfunction addValue(\n root: unknown,\n segments: string[],\n value: unknown,\n): OperationResult {\n if (segments.length === 0) {\n return { root: cloneState(value), applied: true };\n }\n\n const parent = getParent(root, segments);\n if (\n !parent.exists ||\n parent.value === null ||\n typeof parent.value !== \"object\"\n ) {\n return { root, applied: false };\n }\n\n const segment = segments[segments.length - 1];\n if (Array.isArray(parent.value)) {\n if (segment === \"-\") {\n parent.value.push(cloneState(value));\n return { root, applied: true };\n }\n\n const index =\n segment === \"0\"\n ? 0\n : /^[1-9]\\d*$/.test(segment)\n ? Number(segment)\n : undefined;\n if (\n index === undefined ||\n !Number.isSafeInteger(index) ||\n index > parent.value.length\n ) {\n return { root, applied: false };\n }\n parent.value.splice(index, 0, cloneState(value));\n return { root, applied: true };\n }\n\n (parent.value as Record<string, unknown>)[segment] = cloneState(value);\n return { root, applied: true };\n}\n\nfunction removeValue(root: unknown, segments: string[]): OperationResult {\n if (segments.length === 0) return { root: undefined, applied: true };\n\n const parent = getParent(root, segments);\n if (\n !parent.exists ||\n parent.value === null ||\n typeof parent.value !== \"object\"\n ) {\n return { root, applied: false };\n }\n\n const segment = segments[segments.length - 1];\n if (Array.isArray(parent.value)) {\n const index = getArrayIndex(segment, parent.value.length);\n if (index === undefined) return { root, applied: false };\n parent.value.splice(index, 1);\n return { root, applied: true };\n }\n\n if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) {\n return { root, applied: false };\n }\n delete (parent.value as Record<string, unknown>)[segment];\n return { root, applied: true };\n}\n\nfunction replaceValue(\n root: unknown,\n segments: string[],\n value: unknown,\n): OperationResult {\n if (segments.length === 0) {\n return { root: cloneState(value), applied: true };\n }\n\n const parent = getParent(root, segments);\n if (\n !parent.exists ||\n parent.value === null ||\n typeof parent.value !== \"object\"\n ) {\n return { root, applied: false };\n }\n\n const segment = segments[segments.length - 1];\n if (Array.isArray(parent.value)) {\n const index = getArrayIndex(segment, parent.value.length);\n if (index === undefined) return { root, applied: false };\n parent.value[index] = cloneState(value);\n return { root, applied: true };\n }\n\n if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) {\n return { root, applied: false };\n }\n (parent.value as Record<string, unknown>)[segment] = cloneState(value);\n return { root, applied: true };\n}\n\nfunction jsonValueEqual(left: unknown, right: unknown): boolean {\n if (Object.is(left, right)) return true;\n if (\n left === null ||\n right === null ||\n typeof left !== \"object\" ||\n typeof right !== \"object\"\n ) {\n return false;\n }\n if (Array.isArray(left) !== Array.isArray(right)) return false;\n\n const leftKeys = Object.keys(left as object);\n const rightKeys = Object.keys(right as object);\n if (leftKeys.length !== rightKeys.length) return false;\n\n return leftKeys.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(right, key) &&\n jsonValueEqual(\n (left as Record<string, unknown>)[key],\n (right as Record<string, unknown>)[key],\n ),\n );\n}\n\nfunction applyStateDeltaOperation(\n root: unknown,\n operation: StateDeltaOperation,\n): OperationResult {\n if (typeof operation.path !== \"string\") return { root, applied: false };\n\n const path = parseJsonPointer(operation.path);\n if (path === undefined) return { root, applied: false };\n\n switch (operation.op) {\n case \"add\":\n return addValue(root, path, operation.value);\n case \"remove\":\n return removeValue(root, path);\n case \"replace\":\n return replaceValue(root, path, operation.value);\n case \"test\": {\n const actual = getJsonPointerValue(root, operation.path);\n return {\n root,\n applied: actual.exists && jsonValueEqual(actual.value, operation.value),\n };\n }\n case \"copy\": {\n if (typeof operation.from !== \"string\") return { root, applied: false };\n const source = getJsonPointerValue(root, operation.from);\n if (!source.exists) return { root, applied: false };\n return addValue(root, path, source.value);\n }\n case \"move\": {\n if (typeof operation.from !== \"string\") return { root, applied: false };\n const from = parseJsonPointer(operation.from);\n if (from === undefined) return { root, applied: false };\n const source = getJsonPointerValue(root, operation.from);\n if (!source.exists) return { root, applied: false };\n if (operation.from === operation.path) return { root, applied: true };\n\n const nextRoot = cloneState(root);\n const removed = removeValue(nextRoot, from);\n if (!removed.applied) return { root, applied: false };\n const added = addValue(removed.root, path, source.value);\n return added.applied ? added : { root, applied: false };\n }\n default:\n return { root, applied: false };\n }\n}\n\nfunction normalizeStateDelta(\n delta: unknown[],\n initialState: unknown,\n): { delta: unknown[]; state: unknown } {\n let state = cloneState(initialState);\n const normalized: unknown[] = [];\n\n for (const operation of delta) {\n const candidate =\n operation !== null && typeof operation === \"object\"\n ? (operation as StateDeltaOperation)\n : undefined;\n if (\n candidate?.op === \"add\" &&\n typeof candidate.path === \"string\" &&\n candidate.path.endsWith(\"/-\")\n ) {\n const arrayPath = candidate.path.slice(0, -2);\n const array = getJsonPointerValue(state, arrayPath);\n if (!array.exists) {\n const lastSlash = arrayPath.lastIndexOf(\"/\");\n const parentPath = lastSlash > 0 ? arrayPath.slice(0, lastSlash) : \"\";\n if (getJsonPointerValue(state, parentPath).exists) {\n const initializer: StateDeltaOperation = {\n op: \"add\",\n path: arrayPath,\n value: [],\n };\n const applied = applyStateDeltaOperation(state, initializer);\n if (applied.applied) {\n normalized.push(initializer);\n state = applied.root;\n }\n }\n }\n }\n\n normalized.push(operation);\n if (candidate) {\n const applied = applyStateDeltaOperation(state, candidate);\n if (applied.applied) state = applied.root;\n }\n }\n\n return { delta: normalized, state };\n}\n\nexport function createStateEventNormalizer(\n initialState: unknown,\n): (event: BaseEvent) => BaseEvent[] {\n let state = cloneState(initialState);\n let hasEmittedState = false;\n\n return (event) => {\n if (event.type === EventType.STATE_SNAPSHOT) {\n state = cloneState((event as StateSnapshotEvent).snapshot);\n hasEmittedState = true;\n return [event];\n }\n\n if (event.type !== EventType.STATE_DELTA) return [event];\n\n const stateDeltaEvent = event as StateDeltaEvent;\n const initialSnapshot: StateSnapshotEvent[] =\n !hasEmittedState && initialState !== undefined\n ? [\n {\n type: EventType.STATE_SNAPSHOT,\n snapshot: cloneState(state),\n },\n ]\n : [];\n const normalized = Array.isArray(stateDeltaEvent.delta)\n ? normalizeStateDelta(stateDeltaEvent.delta, state)\n : { delta: stateDeltaEvent.delta, state };\n state = normalized.state;\n hasEmittedState = true;\n\n return [\n ...initialSnapshot,\n {\n ...stateDeltaEvent,\n delta: normalized.delta as StateDeltaEvent[\"delta\"],\n },\n ];\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { EventType } from "@ag-ui/client";
|
|
3
|
+
|
|
4
|
+
//#region src/agent/state-delta.ts
|
|
5
|
+
function parseJsonPointer(pointer) {
|
|
6
|
+
if (pointer === "") return [];
|
|
7
|
+
if (!pointer.startsWith("/")) return void 0;
|
|
8
|
+
const segments = pointer.slice(1).split("/");
|
|
9
|
+
if (segments.some((segment) => /~(?![01])/.test(segment))) return;
|
|
10
|
+
return segments.map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
11
|
+
}
|
|
12
|
+
function encodeJsonPointer(segments) {
|
|
13
|
+
if (segments.length === 0) return "";
|
|
14
|
+
return `/${segments.map((segment) => segment.replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
|
|
15
|
+
}
|
|
16
|
+
function getArrayIndex(segment, length) {
|
|
17
|
+
if (segment !== "0" && !/^[1-9]\d*$/.test(segment)) return void 0;
|
|
18
|
+
const index = Number(segment);
|
|
19
|
+
return Number.isSafeInteger(index) && index < length ? index : void 0;
|
|
20
|
+
}
|
|
21
|
+
function getJsonPointerValue(root, pointer) {
|
|
22
|
+
const segments = parseJsonPointer(pointer);
|
|
23
|
+
if (segments === void 0) return { exists: false };
|
|
24
|
+
let current = root;
|
|
25
|
+
for (const segment of segments) {
|
|
26
|
+
if (current === null || typeof current !== "object") return { exists: false };
|
|
27
|
+
if (Array.isArray(current)) {
|
|
28
|
+
const index = getArrayIndex(segment, current.length);
|
|
29
|
+
if (index === void 0) return { exists: false };
|
|
30
|
+
current = current[index];
|
|
31
|
+
} else {
|
|
32
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) return { exists: false };
|
|
33
|
+
current = current[segment];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
exists: true,
|
|
38
|
+
value: current
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function getParent(root, segments) {
|
|
42
|
+
return getJsonPointerValue(root, encodeJsonPointer(segments.slice(0, -1)));
|
|
43
|
+
}
|
|
44
|
+
function cloneStateFallback(state, seen = /* @__PURE__ */ new WeakMap()) {
|
|
45
|
+
if (state === null || typeof state !== "object") return state;
|
|
46
|
+
const existing = seen.get(state);
|
|
47
|
+
if (existing !== void 0) return existing;
|
|
48
|
+
let clone;
|
|
49
|
+
try {
|
|
50
|
+
clone = Array.isArray(state) ? [] : Object.create(Object.getPrototypeOf(state));
|
|
51
|
+
} catch {
|
|
52
|
+
clone = Array.isArray(state) ? [] : {};
|
|
53
|
+
}
|
|
54
|
+
seen.set(state, clone);
|
|
55
|
+
let keys = [];
|
|
56
|
+
try {
|
|
57
|
+
keys = Reflect.ownKeys(state);
|
|
58
|
+
} catch {
|
|
59
|
+
return clone;
|
|
60
|
+
}
|
|
61
|
+
for (const key of keys) try {
|
|
62
|
+
const descriptor = Object.getOwnPropertyDescriptor(state, key);
|
|
63
|
+
if (!descriptor) continue;
|
|
64
|
+
if ("value" in descriptor) descriptor.value = cloneStateFallback(descriptor.value, seen);
|
|
65
|
+
Object.defineProperty(clone, key, descriptor);
|
|
66
|
+
} catch {}
|
|
67
|
+
return clone;
|
|
68
|
+
}
|
|
69
|
+
function cloneState(state) {
|
|
70
|
+
try {
|
|
71
|
+
return structuredClone(state);
|
|
72
|
+
} catch {
|
|
73
|
+
return cloneStateFallback(state);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function addValue(root, segments, value) {
|
|
77
|
+
if (segments.length === 0) return {
|
|
78
|
+
root: cloneState(value),
|
|
79
|
+
applied: true
|
|
80
|
+
};
|
|
81
|
+
const parent = getParent(root, segments);
|
|
82
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
83
|
+
root,
|
|
84
|
+
applied: false
|
|
85
|
+
};
|
|
86
|
+
const segment = segments[segments.length - 1];
|
|
87
|
+
if (Array.isArray(parent.value)) {
|
|
88
|
+
if (segment === "-") {
|
|
89
|
+
parent.value.push(cloneState(value));
|
|
90
|
+
return {
|
|
91
|
+
root,
|
|
92
|
+
applied: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const index = segment === "0" ? 0 : /^[1-9]\d*$/.test(segment) ? Number(segment) : void 0;
|
|
96
|
+
if (index === void 0 || !Number.isSafeInteger(index) || index > parent.value.length) return {
|
|
97
|
+
root,
|
|
98
|
+
applied: false
|
|
99
|
+
};
|
|
100
|
+
parent.value.splice(index, 0, cloneState(value));
|
|
101
|
+
return {
|
|
102
|
+
root,
|
|
103
|
+
applied: true
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
parent.value[segment] = cloneState(value);
|
|
107
|
+
return {
|
|
108
|
+
root,
|
|
109
|
+
applied: true
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function removeValue(root, segments) {
|
|
113
|
+
if (segments.length === 0) return {
|
|
114
|
+
root: void 0,
|
|
115
|
+
applied: true
|
|
116
|
+
};
|
|
117
|
+
const parent = getParent(root, segments);
|
|
118
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
119
|
+
root,
|
|
120
|
+
applied: false
|
|
121
|
+
};
|
|
122
|
+
const segment = segments[segments.length - 1];
|
|
123
|
+
if (Array.isArray(parent.value)) {
|
|
124
|
+
const index = getArrayIndex(segment, parent.value.length);
|
|
125
|
+
if (index === void 0) return {
|
|
126
|
+
root,
|
|
127
|
+
applied: false
|
|
128
|
+
};
|
|
129
|
+
parent.value.splice(index, 1);
|
|
130
|
+
return {
|
|
131
|
+
root,
|
|
132
|
+
applied: true
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) return {
|
|
136
|
+
root,
|
|
137
|
+
applied: false
|
|
138
|
+
};
|
|
139
|
+
delete parent.value[segment];
|
|
140
|
+
return {
|
|
141
|
+
root,
|
|
142
|
+
applied: true
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function replaceValue(root, segments, value) {
|
|
146
|
+
if (segments.length === 0) return {
|
|
147
|
+
root: cloneState(value),
|
|
148
|
+
applied: true
|
|
149
|
+
};
|
|
150
|
+
const parent = getParent(root, segments);
|
|
151
|
+
if (!parent.exists || parent.value === null || typeof parent.value !== "object") return {
|
|
152
|
+
root,
|
|
153
|
+
applied: false
|
|
154
|
+
};
|
|
155
|
+
const segment = segments[segments.length - 1];
|
|
156
|
+
if (Array.isArray(parent.value)) {
|
|
157
|
+
const index = getArrayIndex(segment, parent.value.length);
|
|
158
|
+
if (index === void 0) return {
|
|
159
|
+
root,
|
|
160
|
+
applied: false
|
|
161
|
+
};
|
|
162
|
+
parent.value[index] = cloneState(value);
|
|
163
|
+
return {
|
|
164
|
+
root,
|
|
165
|
+
applied: true
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (!Object.prototype.hasOwnProperty.call(parent.value, segment)) return {
|
|
169
|
+
root,
|
|
170
|
+
applied: false
|
|
171
|
+
};
|
|
172
|
+
parent.value[segment] = cloneState(value);
|
|
173
|
+
return {
|
|
174
|
+
root,
|
|
175
|
+
applied: true
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function jsonValueEqual(left, right) {
|
|
179
|
+
if (Object.is(left, right)) return true;
|
|
180
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
181
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
182
|
+
const leftKeys = Object.keys(left);
|
|
183
|
+
const rightKeys = Object.keys(right);
|
|
184
|
+
if (leftKeys.length !== rightKeys.length) return false;
|
|
185
|
+
return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && jsonValueEqual(left[key], right[key]));
|
|
186
|
+
}
|
|
187
|
+
function applyStateDeltaOperation(root, operation) {
|
|
188
|
+
if (typeof operation.path !== "string") return {
|
|
189
|
+
root,
|
|
190
|
+
applied: false
|
|
191
|
+
};
|
|
192
|
+
const path = parseJsonPointer(operation.path);
|
|
193
|
+
if (path === void 0) return {
|
|
194
|
+
root,
|
|
195
|
+
applied: false
|
|
196
|
+
};
|
|
197
|
+
switch (operation.op) {
|
|
198
|
+
case "add": return addValue(root, path, operation.value);
|
|
199
|
+
case "remove": return removeValue(root, path);
|
|
200
|
+
case "replace": return replaceValue(root, path, operation.value);
|
|
201
|
+
case "test": {
|
|
202
|
+
const actual = getJsonPointerValue(root, operation.path);
|
|
203
|
+
return {
|
|
204
|
+
root,
|
|
205
|
+
applied: actual.exists && jsonValueEqual(actual.value, operation.value)
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
case "copy": {
|
|
209
|
+
if (typeof operation.from !== "string") return {
|
|
210
|
+
root,
|
|
211
|
+
applied: false
|
|
212
|
+
};
|
|
213
|
+
const source = getJsonPointerValue(root, operation.from);
|
|
214
|
+
if (!source.exists) return {
|
|
215
|
+
root,
|
|
216
|
+
applied: false
|
|
217
|
+
};
|
|
218
|
+
return addValue(root, path, source.value);
|
|
219
|
+
}
|
|
220
|
+
case "move": {
|
|
221
|
+
if (typeof operation.from !== "string") return {
|
|
222
|
+
root,
|
|
223
|
+
applied: false
|
|
224
|
+
};
|
|
225
|
+
const from = parseJsonPointer(operation.from);
|
|
226
|
+
if (from === void 0) return {
|
|
227
|
+
root,
|
|
228
|
+
applied: false
|
|
229
|
+
};
|
|
230
|
+
const source = getJsonPointerValue(root, operation.from);
|
|
231
|
+
if (!source.exists) return {
|
|
232
|
+
root,
|
|
233
|
+
applied: false
|
|
234
|
+
};
|
|
235
|
+
if (operation.from === operation.path) return {
|
|
236
|
+
root,
|
|
237
|
+
applied: true
|
|
238
|
+
};
|
|
239
|
+
const removed = removeValue(cloneState(root), from);
|
|
240
|
+
if (!removed.applied) return {
|
|
241
|
+
root,
|
|
242
|
+
applied: false
|
|
243
|
+
};
|
|
244
|
+
const added = addValue(removed.root, path, source.value);
|
|
245
|
+
return added.applied ? added : {
|
|
246
|
+
root,
|
|
247
|
+
applied: false
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
default: return {
|
|
251
|
+
root,
|
|
252
|
+
applied: false
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function normalizeStateDelta(delta, initialState) {
|
|
257
|
+
let state = cloneState(initialState);
|
|
258
|
+
const normalized = [];
|
|
259
|
+
for (const operation of delta) {
|
|
260
|
+
const candidate = operation !== null && typeof operation === "object" ? operation : void 0;
|
|
261
|
+
if (candidate?.op === "add" && typeof candidate.path === "string" && candidate.path.endsWith("/-")) {
|
|
262
|
+
const arrayPath = candidate.path.slice(0, -2);
|
|
263
|
+
if (!getJsonPointerValue(state, arrayPath).exists) {
|
|
264
|
+
const lastSlash = arrayPath.lastIndexOf("/");
|
|
265
|
+
const parentPath = lastSlash > 0 ? arrayPath.slice(0, lastSlash) : "";
|
|
266
|
+
if (getJsonPointerValue(state, parentPath).exists) {
|
|
267
|
+
const initializer = {
|
|
268
|
+
op: "add",
|
|
269
|
+
path: arrayPath,
|
|
270
|
+
value: []
|
|
271
|
+
};
|
|
272
|
+
const applied = applyStateDeltaOperation(state, initializer);
|
|
273
|
+
if (applied.applied) {
|
|
274
|
+
normalized.push(initializer);
|
|
275
|
+
state = applied.root;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
normalized.push(operation);
|
|
281
|
+
if (candidate) {
|
|
282
|
+
const applied = applyStateDeltaOperation(state, candidate);
|
|
283
|
+
if (applied.applied) state = applied.root;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
delta: normalized,
|
|
288
|
+
state
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function createStateEventNormalizer(initialState) {
|
|
292
|
+
let state = cloneState(initialState);
|
|
293
|
+
let hasEmittedState = false;
|
|
294
|
+
return (event) => {
|
|
295
|
+
if (event.type === EventType.STATE_SNAPSHOT) {
|
|
296
|
+
state = cloneState(event.snapshot);
|
|
297
|
+
hasEmittedState = true;
|
|
298
|
+
return [event];
|
|
299
|
+
}
|
|
300
|
+
if (event.type !== EventType.STATE_DELTA) return [event];
|
|
301
|
+
const stateDeltaEvent = event;
|
|
302
|
+
const initialSnapshot = !hasEmittedState && initialState !== void 0 ? [{
|
|
303
|
+
type: EventType.STATE_SNAPSHOT,
|
|
304
|
+
snapshot: cloneState(state)
|
|
305
|
+
}] : [];
|
|
306
|
+
const normalized = Array.isArray(stateDeltaEvent.delta) ? normalizeStateDelta(stateDeltaEvent.delta, state) : {
|
|
307
|
+
delta: stateDeltaEvent.delta,
|
|
308
|
+
state
|
|
309
|
+
};
|
|
310
|
+
state = normalized.state;
|
|
311
|
+
hasEmittedState = true;
|
|
312
|
+
return [...initialSnapshot, {
|
|
313
|
+
...stateDeltaEvent,
|
|
314
|
+
delta: normalized.delta
|
|
315
|
+
}];
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
//#endregion
|
|
320
|
+
export { createStateEventNormalizer };
|
|
321
|
+
//# sourceMappingURL=state-delta.mjs.map
|