@prometheus-ags/entity-graph-core 4.3.0 → 4.4.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/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { graphStore, useGraphStore, subscribeDevtoolsEvent, getGraphDevtoolsCompatibilityDelegate, subscribeGraphDevtoolsCompatibility, matchesFilter, matchesSearch, compareEntities, emitLegacyDevtoolsEvent, __require } from './chunk-64YZRB56.mjs';
2
- export { EMPTY_ENTITY_STATE, EMPTY_IDS, EMPTY_LIST_STATE, EMPTY_SYNC_METADATA, applyView, attachGlobalListeners, cascadeInvalidation, checkCompleteness, compareEntities, configureEngine, createGraphStore, dedupe, fetchEntity, fetchList, findInsertionIndex, getActiveSubscriberCount, getEngineOptions, getMergeStrategy, getSchema, graphStore, hasMergeStrategy, lwwStrategy, matchesFilter, matchesSearch, readRelations, registerMergeStrategy, registerSchema, registerSubscriber, serializeKey, setDefaultMergeStrategy, startGarbageCollector, stopGarbageCollector, subscribeDevtoolsEvent, subscribeSubscriberStats, unregisterSubscriber, useGraphStore } from './chunk-64YZRB56.mjs';
1
+ import { graphStore, useGraphStore, subscribeDevtoolsEvent, getGraphDevtoolsCompatibilityDelegate, subscribeGraphDevtoolsCompatibility, matchesFilter, matchesSearch, compareEntities, __require, setListIdsDraft, removeIdFromAllListsDraft, insertIdInListDraft, setEntitySyncMetadataDraft, clearPatchDraft, unpatchEntityDraft, patchEntityDraft, removeEntityDraft, replaceEntityDraft, upsertEntitiesDraft, upsertEntityDraft, emitLegacyDevtoolsEvent } from './chunk-T5WSFBXH.mjs';
2
+ export { EMPTY_ENTITY_STATE, EMPTY_IDS, EMPTY_LIST_STATE, EMPTY_SYNC_METADATA, applyView, attachGlobalListeners, cascadeInvalidation, checkCompleteness, compareEntities, configureEngine, createGraphStore, dedupe, fetchEntity, fetchList, findInsertionIndex, getActiveSubscriberCount, getEngineOptions, getMergeStrategy, getSchema, graphStore, hasMergeStrategy, lwwStrategy, matchesFilter, matchesSearch, readRelations, registerMergeStrategy, registerSchema, registerSubscriber, serializeKey, setDefaultMergeStrategy, startGarbageCollector, stopGarbageCollector, subscribeDevtoolsEvent, subscribeSubscriberStats, unregisterSubscriber, useGraphStore } from './chunk-T5WSFBXH.mjs';
3
+ import { isDraft, current } from 'immer';
3
4
  import { createStore } from 'zustand/vanilla';
4
5
 
5
6
  // src/errors.ts
@@ -494,37 +495,37 @@ function isObject(value) {
494
495
  function getValueAtPath(source, path) {
495
496
  if (!path) return source;
496
497
  const segments = path.split(".").filter(Boolean);
497
- let current = source;
498
+ let current2 = source;
498
499
  for (const segment of segments) {
499
- if (!isObject(current) && !Array.isArray(current)) return void 0;
500
- current = current[segment];
500
+ if (!isObject(current2) && !Array.isArray(current2)) return void 0;
501
+ current2 = current2[segment];
501
502
  }
502
- return current;
503
+ return current2;
503
504
  }
504
505
  function setValueAtPath(source, path, value) {
505
506
  const segments = path.split(".").filter(Boolean);
506
507
  if (segments.length === 0) return source;
507
508
  const clone2 = structuredClone(source);
508
- let current = clone2;
509
+ let current2 = clone2;
509
510
  for (let index = 0; index < segments.length - 1; index += 1) {
510
511
  const segment = segments[index];
511
- const next = current[segment];
512
- if (!isObject(next)) current[segment] = {};
513
- current = current[segment];
512
+ const next = current2[segment];
513
+ if (!isObject(next)) current2[segment] = {};
514
+ current2 = current2[segment];
514
515
  }
515
- current[segments[segments.length - 1]] = value;
516
+ current2[segments[segments.length - 1]] = value;
516
517
  return clone2;
517
518
  }
518
- function collectDirtyPaths(current, original, prefix = "", acc = /* @__PURE__ */ new Set()) {
519
- if (isObject(current) && isObject(original)) {
520
- const keys = /* @__PURE__ */ new Set([...Object.keys(current), ...Object.keys(original)]);
519
+ function collectDirtyPaths(current2, original, prefix = "", acc = /* @__PURE__ */ new Set()) {
520
+ if (isObject(current2) && isObject(original)) {
521
+ const keys = /* @__PURE__ */ new Set([...Object.keys(current2), ...Object.keys(original)]);
521
522
  for (const key of keys) {
522
523
  const nextPrefix = prefix ? `${prefix}.${key}` : key;
523
- collectDirtyPaths(current[key], original[key], nextPrefix, acc);
524
+ collectDirtyPaths(current2[key], original[key], nextPrefix, acc);
524
525
  }
525
526
  return acc;
526
527
  }
527
- if (JSON.stringify(current) !== JSON.stringify(original) && prefix) acc.add(prefix);
528
+ if (JSON.stringify(current2) !== JSON.stringify(original) && prefix) acc.add(prefix);
528
529
  return acc;
529
530
  }
530
531
 
@@ -642,18 +643,41 @@ function applySelection(row, select) {
642
643
  return picked;
643
644
  }
644
645
 
646
+ // src/devtools-gate.ts
647
+ function resolveDevtoolsEmission(env) {
648
+ if (env.buildFlag !== void 0) return env.buildFlag && env.override !== false;
649
+ if (env.override !== void 0) return env.override;
650
+ if (env.processEnv !== void 0) return env.processEnv.NODE_ENV !== "production";
651
+ return env.viteDev === true;
652
+ }
653
+ var override;
654
+ function setGraphDevtoolsEmission(enabled) {
655
+ override = enabled;
656
+ }
657
+ function isGraphDevtoolsEmissionEnabled() {
658
+ return resolveDevtoolsEmission({
659
+ buildFlag: typeof __PROMETHEUS_ENTITY_GRAPH_DEVTOOLS__ === "boolean" ? __PROMETHEUS_ENTITY_GRAPH_DEVTOOLS__ : void 0,
660
+ override,
661
+ processEnv: typeof process !== "undefined" ? process.env ?? {} : void 0,
662
+ viteDev: import.meta.env?.DEV
663
+ });
664
+ }
665
+ function emitGatedDevtoolsEvent(emit, build) {
666
+ if ((typeof __PROMETHEUS_ENTITY_GRAPH_DEVTOOLS__ !== "boolean" || __PROMETHEUS_ENTITY_GRAPH_DEVTOOLS__) && isGraphDevtoolsEmissionEnabled()) {
667
+ emit(build());
668
+ }
669
+ }
670
+
645
671
  // src/graph-actions.ts
646
672
  var graphActionListeners = /* @__PURE__ */ new Set();
647
673
  var graphActionReplayers = /* @__PURE__ */ new Map();
648
674
  function createGraphTransaction(storeApi = graphStore) {
649
- const baseline = cloneGraphData(storeApi.getState());
675
+ const baseline = captureGraphData(storeApi.getState());
650
676
  let closed = false;
651
677
  const tx = {
652
678
  upsertEntity(type, id, data) {
653
679
  storeApi.getState().upsertEntity(type, id, data);
654
- if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
655
- emitLegacyDevtoolsEvent({ kind: "upsert", type, id, data, at: (/* @__PURE__ */ new Date()).toISOString() });
656
- }
680
+ emitGatedDevtoolsEvent(emitLegacyDevtoolsEvent, () => ({ kind: "upsert", type, id, data, at: (/* @__PURE__ */ new Date()).toISOString() }));
657
681
  return tx;
658
682
  },
659
683
  replaceEntity(type, id, data) {
@@ -666,16 +690,12 @@ function createGraphTransaction(storeApi = graphStore) {
666
690
  },
667
691
  patchEntity(type, id, patch) {
668
692
  storeApi.getState().patchEntity(type, id, patch);
669
- if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
670
- emitLegacyDevtoolsEvent({ kind: "patch", type, id, patch, at: (/* @__PURE__ */ new Date()).toISOString() });
671
- }
693
+ emitGatedDevtoolsEvent(emitLegacyDevtoolsEvent, () => ({ kind: "patch", type, id, patch, at: (/* @__PURE__ */ new Date()).toISOString() }));
672
694
  return tx;
673
695
  },
674
696
  clearPatch(type, id) {
675
697
  storeApi.getState().clearPatch(type, id);
676
- if (typeof process === "undefined" || process.env.NODE_ENV !== "production") {
677
- emitLegacyDevtoolsEvent({ kind: "clearPatch", type, id, at: (/* @__PURE__ */ new Date()).toISOString() });
678
- }
698
+ emitGatedDevtoolsEvent(emitLegacyDevtoolsEvent, () => ({ kind: "clearPatch", type, id, at: (/* @__PURE__ */ new Date()).toISOString() }));
679
699
  return tx;
680
700
  },
681
701
  insertIdInList(key, id, position) {
@@ -711,7 +731,7 @@ function createGraphTransaction(storeApi = graphStore) {
711
731
  },
712
732
  rollback() {
713
733
  if (closed) return;
714
- storeApi.setState(cloneGraphData(baseline));
734
+ storeApi.setState({ ...baseline });
715
735
  closed = true;
716
736
  },
717
737
  snapshot() {
@@ -777,9 +797,224 @@ function cloneGraphData(source = graphStore.getState()) {
777
797
  lists: structuredClone(source.lists)
778
798
  };
779
799
  }
800
+ function captureGraphData(source) {
801
+ return {
802
+ entities: source.entities,
803
+ patches: source.patches,
804
+ entityStates: source.entityStates,
805
+ syncMetadata: source.syncMetadata,
806
+ lists: source.lists
807
+ };
808
+ }
780
809
  function emitGraphActionEvent(event) {
781
810
  for (const listener of graphActionListeners) listener(event);
782
811
  }
812
+ var openDrafts = /* @__PURE__ */ new WeakMap();
813
+ function createDraftBatch(draft) {
814
+ const batch = {
815
+ upsertEntity: (type, id, data) => (upsertEntityDraft(draft, type, id, data), batch),
816
+ upsertEntities: (type, entries) => (upsertEntitiesDraft(draft, type, entries), batch),
817
+ replaceEntity: (type, id, data) => (replaceEntityDraft(draft, type, id, data), batch),
818
+ removeEntity: (type, id) => (removeEntityDraft(draft, type, id), batch),
819
+ patchEntity: (type, id, patch) => (patchEntityDraft(draft, type, id, patch), batch),
820
+ unpatchEntity: (type, id, keys) => (unpatchEntityDraft(draft, type, id, keys), batch),
821
+ clearPatch: (type, id) => (clearPatchDraft(draft, type, id), batch),
822
+ setEntitySyncMetadata: (type, id, metadata) => (setEntitySyncMetadataDraft(draft, type, id, metadata), batch),
823
+ insertIdInList: (key, id, position) => (insertIdInListDraft(draft, key, id, position), batch),
824
+ removeIdFromAllLists: (type, id) => (removeIdFromAllListsDraft(draft, type, id), batch),
825
+ setListIds: (key, ids, entityType) => (setListIdsDraft(draft, key, ids, entityType), batch),
826
+ readEntity: (type, id) => {
827
+ const base = draft.entities[type]?.[id];
828
+ if (!base) return null;
829
+ const patch = draft.patches[type]?.[id];
830
+ const plain = (value) => isDraft(value) ? current(value) : value;
831
+ return patch ? { ...plain(base), ...plain(patch) } : { ...plain(base) };
832
+ }
833
+ };
834
+ return batch;
835
+ }
836
+ function batchGraphWrites(fn, store = graphStore) {
837
+ const open = openDrafts.get(store);
838
+ if (open) return fn(createDraftBatch(open));
839
+ let result;
840
+ const before = store.getState();
841
+ store.setState((draft) => {
842
+ openDrafts.set(store, draft);
843
+ try {
844
+ result = fn(createDraftBatch(draft));
845
+ } finally {
846
+ openDrafts.delete(store);
847
+ }
848
+ if (typeof result?.then === "function") {
849
+ throw new TypeError("batchGraphWrites: the callback must be synchronous; nothing was written");
850
+ }
851
+ if (store.getState() !== before) {
852
+ throw new Error(
853
+ "batchGraphWrites: the store was written outside the batch handle while the batch was open; the batch was not applied"
854
+ );
855
+ }
856
+ });
857
+ return result;
858
+ }
859
+ function applyChange(batch, change) {
860
+ switch (change.op) {
861
+ case "upsert":
862
+ batch.upsertEntity(change.type, change.id, change.data);
863
+ return;
864
+ case "replace":
865
+ batch.replaceEntity(change.type, change.id, change.data);
866
+ return;
867
+ case "remove":
868
+ batch.removeEntity(change.type, change.id);
869
+ return;
870
+ case "patch":
871
+ batch.patchEntity(change.type, change.id, change.patch);
872
+ return;
873
+ case "unpatch":
874
+ batch.unpatchEntity(change.type, change.id, change.keys);
875
+ return;
876
+ case "clearPatch":
877
+ batch.clearPatch(change.type, change.id);
878
+ return;
879
+ case "syncMetadata":
880
+ batch.setEntitySyncMetadata(change.type, change.id, change.metadata);
881
+ return;
882
+ case "insertId":
883
+ batch.insertIdInList(change.key, change.id, change.position);
884
+ return;
885
+ case "removeIdFromAllLists":
886
+ batch.removeIdFromAllLists(change.type, change.id);
887
+ return;
888
+ case "setListIds":
889
+ batch.setListIds(change.key, change.ids, change.entityType);
890
+ return;
891
+ default:
892
+ throw new Error(`Unknown graph change op: ${change.op}`);
893
+ }
894
+ }
895
+ function applyGraphChanges(changes, store = graphStore) {
896
+ batchGraphWrites((batch) => {
897
+ for (const change of changes) applyChange(batch, change);
898
+ }, store);
899
+ }
900
+
901
+ // src/live-layer.ts
902
+ function liveKey(type, id) {
903
+ return `${type}:${id}`;
904
+ }
905
+ function without(values, fields) {
906
+ const rest = { ...values };
907
+ for (const field of fields) delete rest[field];
908
+ return Object.keys(rest).length > 0 ? rest : void 0;
909
+ }
910
+ function pick(values, fields) {
911
+ if (!fields) return values;
912
+ const picked = {};
913
+ for (const field of fields) if (Object.hasOwn(values, field)) picked[field] = values[field];
914
+ return picked;
915
+ }
916
+ function createLiveLayer(options = {}) {
917
+ const store = options.store ?? graphStore;
918
+ const values = /* @__PURE__ */ new Map();
919
+ const listeners = /* @__PURE__ */ new Map();
920
+ const mergedCache = /* @__PURE__ */ new Map();
921
+ const muted = /* @__PURE__ */ new Set();
922
+ const notify = (key) => {
923
+ const set = listeners.get(key);
924
+ if (!set) return;
925
+ for (const listener of [...set]) listener();
926
+ };
927
+ const putLive = (type, id, fields) => {
928
+ const key = liveKey(type, id);
929
+ if (fields) values.set(key, { type, id, fields });
930
+ else values.delete(key);
931
+ };
932
+ const durable = (state, type, id) => state.readEntity(type, id);
933
+ const layer = {
934
+ set(type, id, next) {
935
+ const current2 = values.get(liveKey(type, id))?.fields;
936
+ putLive(type, id, { ...current2, ...next });
937
+ notify(liveKey(type, id));
938
+ },
939
+ append(type, id, field, chunk) {
940
+ const current2 = values.get(liveKey(type, id))?.fields;
941
+ let prior = current2 && Object.hasOwn(current2, field) ? current2[field] : void 0;
942
+ if (prior === void 0) prior = durable(store.getState(), type, id)?.[field];
943
+ layer.set(type, id, { [field]: (typeof prior === "string" ? prior : "") + chunk });
944
+ },
945
+ get(type, id) {
946
+ return values.get(liveKey(type, id))?.fields;
947
+ },
948
+ read(type, id) {
949
+ const key = liveKey(type, id);
950
+ const base = durable(store.getState(), type, id);
951
+ const live = values.get(key)?.fields;
952
+ const cached = mergedCache.get(key);
953
+ if (cached && cached.base === base && cached.live === live) return cached.merged;
954
+ const merged = live ? { ...base ?? {}, ...live } : base;
955
+ if (merged === null) mergedCache.delete(key);
956
+ else mergedCache.set(key, { base, live, merged });
957
+ return merged;
958
+ },
959
+ subscribe(type, id, listener) {
960
+ const key = liveKey(type, id);
961
+ let set = listeners.get(key);
962
+ if (!set) listeners.set(key, set = /* @__PURE__ */ new Set());
963
+ set.add(listener);
964
+ const unsubscribeGraph = store.subscribe(
965
+ (state) => [state.entities[type]?.[id], state.patches[type]?.[id]],
966
+ () => {
967
+ if (!muted.has(key)) listener();
968
+ },
969
+ { equalityFn: (a, b) => a[0] === b[0] && a[1] === b[1] }
970
+ );
971
+ let active = true;
972
+ return () => {
973
+ if (!active) return;
974
+ active = false;
975
+ unsubscribeGraph();
976
+ set.delete(listener);
977
+ if (set.size === 0 && listeners.get(key) === set) listeners.delete(key);
978
+ };
979
+ },
980
+ commit(type, id, commitOptions = {}) {
981
+ const key = liveKey(type, id);
982
+ const live = values.get(key)?.fields;
983
+ if (!live) return;
984
+ const data = pick(live, commitOptions.fields);
985
+ muted.add(key);
986
+ try {
987
+ if (Object.keys(data).length > 0) store.getState().upsertEntity(type, id, data);
988
+ } finally {
989
+ muted.delete(key);
990
+ }
991
+ putLive(type, id, commitOptions.fields ? without(live, commitOptions.fields) : void 0);
992
+ notify(key);
993
+ },
994
+ commitAll() {
995
+ const entries = [...values.entries()];
996
+ if (entries.length === 0) return;
997
+ for (const [key] of entries) muted.add(key);
998
+ try {
999
+ batchGraphWrites((batch) => {
1000
+ for (const [, entry] of entries) batch.upsertEntity(entry.type, entry.id, entry.fields);
1001
+ }, store);
1002
+ } finally {
1003
+ for (const [key] of entries) muted.delete(key);
1004
+ }
1005
+ for (const [key] of entries) values.delete(key);
1006
+ for (const [key] of entries) notify(key);
1007
+ },
1008
+ discard(type, id, fields) {
1009
+ const key = liveKey(type, id);
1010
+ const live = values.get(key)?.fields;
1011
+ if (!live) return;
1012
+ putLive(type, id, fields ? without(live, fields) : void 0);
1013
+ notify(key);
1014
+ }
1015
+ };
1016
+ return layer;
1017
+ }
783
1018
 
784
1019
  // src/graph-effects.ts
785
1020
  function createGraphEffect(opts) {
@@ -1626,34 +1861,34 @@ function removeAt(doc, segs) {
1626
1861
  return root;
1627
1862
  }
1628
1863
  function applyJsonPatch(doc, ops) {
1629
- let current = doc;
1864
+ let current2 = doc;
1630
1865
  for (const op of ops) {
1631
1866
  const segs = parsePointer(op.path);
1632
1867
  switch (op.op) {
1633
1868
  case "add":
1634
- current = setAt(current, segs, op.value, "add");
1869
+ current2 = setAt(current2, segs, clone(op.value), "add");
1635
1870
  break;
1636
1871
  case "replace":
1637
- current = setAt(current, segs, op.value, "replace");
1872
+ current2 = setAt(current2, segs, clone(op.value), "replace");
1638
1873
  break;
1639
1874
  case "remove":
1640
- current = removeAt(current, segs);
1875
+ current2 = removeAt(current2, segs);
1641
1876
  break;
1642
1877
  case "move": {
1643
1878
  const fromSegs = parsePointer(op.from ?? "");
1644
- const moved = getAt(current, fromSegs);
1645
- current = removeAt(current, fromSegs);
1646
- current = setAt(current, segs, moved, "add");
1879
+ const moved = getAt(current2, fromSegs);
1880
+ current2 = removeAt(current2, fromSegs);
1881
+ current2 = setAt(current2, segs, moved, "add");
1647
1882
  break;
1648
1883
  }
1649
1884
  case "copy": {
1650
1885
  const fromSegs = parsePointer(op.from ?? "");
1651
- const copied = clone(getAt(current, fromSegs));
1652
- current = setAt(current, segs, copied, "add");
1886
+ const copied = clone(getAt(current2, fromSegs));
1887
+ current2 = setAt(current2, segs, copied, "add");
1653
1888
  break;
1654
1889
  }
1655
1890
  case "test": {
1656
- const actual = getAt(current, segs);
1891
+ const actual = getAt(current2, segs);
1657
1892
  if (JSON.stringify(actual) !== JSON.stringify(op.value)) {
1658
1893
  throw new Error(`JSON Patch test failed at "${op.path}"`);
1659
1894
  }
@@ -1663,83 +1898,148 @@ function applyJsonPatch(doc, ops) {
1663
1898
  throw new Error(`Unsupported JSON Patch op: ${op.op}`);
1664
1899
  }
1665
1900
  }
1666
- return current;
1901
+ return current2;
1667
1902
  }
1668
1903
 
1669
1904
  // src/agent/ag-ui-bridge.ts
1905
+ var AGUI_STATE_ENTITY_TYPE = "AgUiState";
1906
+ var DEFAULT_STATE_ID = "default";
1670
1907
  function isObject3(v) {
1671
1908
  return typeof v === "object" && v !== null && !Array.isArray(v);
1672
1909
  }
1910
+ function parsePointer2(pointer) {
1911
+ if (pointer === "" || pointer === "/") return [];
1912
+ return pointer.slice(1).split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
1913
+ }
1673
1914
  function getAtPointer(state, pointer) {
1674
- if (pointer === "" || pointer === "/") return state;
1675
- const segs = pointer.slice(1).split("/").map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
1676
1915
  let cur = state;
1677
- for (const s of segs) {
1916
+ for (const s of parsePointer2(pointer)) {
1678
1917
  if (Array.isArray(cur)) cur = cur[Number(s)];
1679
1918
  else if (isObject3(cur)) cur = cur[s];
1680
1919
  else return void 0;
1681
1920
  }
1682
1921
  return cur;
1683
1922
  }
1684
- function writeEntity(mapping, id, obj) {
1685
- const store = useGraphStore.getState();
1686
- if ((mapping.write ?? "upsert") === "replace") {
1687
- store.replaceEntity(mapping.entityType, id, obj);
1688
- } else {
1689
- store.upsertEntity(mapping.entityType, id, obj);
1923
+ function agUiListKey(mapping, stateId = DEFAULT_STATE_ID) {
1924
+ return mapping.listKey ?? `agui:${stateId}:${mapping.entityType}:${mapping.pointer}`;
1925
+ }
1926
+ function mappedItems(state, mapping) {
1927
+ const slice = getAtPointer(state, mapping.pointer);
1928
+ if (slice === void 0) return [];
1929
+ if (mapping.kind === "single") {
1930
+ if (!isObject3(slice)) return [];
1931
+ const id = mapping.constantId ?? String(slice[mapping.idField ?? "id"] ?? "");
1932
+ return id ? [[id, slice]] : [];
1933
+ }
1934
+ const items = [];
1935
+ if (Array.isArray(slice)) {
1936
+ for (const item of slice) {
1937
+ if (isObject3(item)) {
1938
+ const id = String(item[mapping.idField ?? "id"] ?? "");
1939
+ if (id) items.push([id, item]);
1940
+ }
1941
+ }
1942
+ } else if (isObject3(slice)) {
1943
+ for (const [key, item] of Object.entries(slice)) {
1944
+ if (isObject3(item)) items.push([String(item[mapping.idField ?? "id"] ?? key), item]);
1945
+ }
1690
1946
  }
1947
+ return items;
1691
1948
  }
1692
- function projectState(state, mappings) {
1693
- for (const mapping of mappings) {
1694
- const slice = getAtPointer(state, mapping.pointer);
1695
- if (slice === void 0) continue;
1696
- if (mapping.kind === "single") {
1697
- if (!isObject3(slice)) continue;
1698
- const id = mapping.constantId ?? String(slice[mapping.idField ?? "id"] ?? "");
1699
- if (!id) continue;
1700
- writeEntity(mapping, id, slice);
1701
- } else {
1702
- const items = [];
1703
- if (Array.isArray(slice)) {
1704
- for (const item of slice) {
1705
- if (isObject3(item)) {
1706
- const id = String(item[mapping.idField ?? "id"] ?? "");
1707
- if (id) items.push([id, item]);
1708
- }
1709
- }
1710
- } else if (isObject3(slice)) {
1711
- for (const [key, item] of Object.entries(slice)) {
1712
- if (isObject3(item)) {
1713
- const id = String(item[mapping.idField ?? "id"] ?? key);
1714
- items.push([id, item]);
1715
- }
1716
- }
1949
+ function projectState(batch, prev, next, mappings, stateId) {
1950
+ const itemsByMapping = mappings.map((mapping) => mappedItems(next, mapping));
1951
+ if (prev) {
1952
+ const held = /* @__PURE__ */ new Map();
1953
+ mappings.forEach((mapping, i) => {
1954
+ let ids = held.get(mapping.entityType);
1955
+ if (!ids) held.set(mapping.entityType, ids = /* @__PURE__ */ new Set());
1956
+ for (const [id] of itemsByMapping[i]) ids.add(id);
1957
+ });
1958
+ const removed = /* @__PURE__ */ new Set();
1959
+ for (const mapping of mappings) {
1960
+ for (const [id] of mappedItems(prev, mapping)) {
1961
+ const key = `${mapping.entityType}:${id}`;
1962
+ if (held.get(mapping.entityType)?.has(id) || removed.has(key)) continue;
1963
+ removed.add(key);
1964
+ batch.removeEntity(mapping.entityType, id);
1965
+ batch.removeIdFromAllLists(mapping.entityType, id);
1717
1966
  }
1718
- for (const [id, obj] of items) writeEntity(mapping, id, obj);
1719
1967
  }
1720
1968
  }
1969
+ mappings.forEach((mapping, i) => {
1970
+ const items = itemsByMapping[i];
1971
+ const nextIds = new Set(items.map(([id]) => id));
1972
+ for (const [id, obj] of items) {
1973
+ if ((mapping.write ?? "upsert") === "replace") batch.replaceEntity(mapping.entityType, id, obj);
1974
+ else batch.upsertEntity(mapping.entityType, id, obj);
1975
+ }
1976
+ if (mapping.kind === "collection") {
1977
+ batch.setListIds(agUiListKey(mapping, stateId), [...nextIds], mapping.entityType);
1978
+ }
1979
+ });
1980
+ }
1981
+ function readRecord(store, stateId) {
1982
+ const record = store.getState().entities[AGUI_STATE_ENTITY_TYPE]?.[stateId];
1983
+ return record;
1984
+ }
1985
+ function readAgUiState(stateId = DEFAULT_STATE_ID, store = graphStore) {
1986
+ return readRecord(store, stateId)?.state ?? null;
1987
+ }
1988
+ function applyState(options, nextOf) {
1989
+ const store = options.store ?? graphStore;
1990
+ const stateId = options.stateId ?? DEFAULT_STATE_ID;
1991
+ const record = readRecord(store, stateId);
1992
+ if (options.eventId !== void 0 && record?.appliedEventIds.includes(options.eventId)) {
1993
+ return { applied: false, state: record.state };
1994
+ }
1995
+ const { prev, next } = nextOf(record);
1996
+ if (!isObject3(next)) return { applied: false, state: record?.state ?? null };
1997
+ const appliedEventIds = options.eventId === void 0 ? record?.appliedEventIds ?? [] : [...record?.appliedEventIds ?? [], options.eventId].slice(-256);
1998
+ batchGraphWrites((batch) => {
1999
+ projectState(batch, prev, next, options.mappings, stateId);
2000
+ batch.replaceEntity(AGUI_STATE_ENTITY_TYPE, stateId, { id: stateId, state: next, appliedEventIds });
2001
+ }, store);
2002
+ return { applied: true, state: readAgUiState(stateId, store) };
1721
2003
  }
1722
2004
  function applyAgUiSnapshot(event, options) {
1723
- if (!isObject3(event.snapshot)) return;
1724
- projectState(event.snapshot, options.mappings);
2005
+ if (!isObject3(event.snapshot)) return { applied: false, state: null };
2006
+ return applyState(options, (record) => ({ prev: record?.state, next: structuredClone(event.snapshot) }));
1725
2007
  }
1726
2008
  function applyAgUiDelta(event, options, currentState) {
1727
- const base = currentState ?? reconstructState(options.mappings);
1728
- const next = applyJsonPatch(base, event.delta);
1729
- if (isObject3(next)) projectState(next, options.mappings);
2009
+ const store = options.store ?? graphStore;
2010
+ const stateId = options.stateId ?? DEFAULT_STATE_ID;
2011
+ return applyState(options, (record) => {
2012
+ const base = currentState !== void 0 ? structuredClone(currentState) : record?.state;
2013
+ if (base) return { prev: base, next: applyJsonPatch(base, event.delta) };
2014
+ const reconstructed = reconstructState(options.mappings, store, stateId);
2015
+ return { prev: void 0, next: applyJsonPatch(reconstructed, event.delta) };
2016
+ });
1730
2017
  }
1731
- function reconstructState(mappings) {
1732
- const store = useGraphStore.getState();
1733
- const state = {};
2018
+ function setAtPointer(target, pointer, value) {
2019
+ const segs = parsePointer2(pointer);
2020
+ if (segs.length === 0) return isObject3(value) ? { ...value } : target;
2021
+ const root = { ...target };
2022
+ let cur = root;
2023
+ for (const seg of segs.slice(0, -1)) {
2024
+ const child = isObject3(cur[seg]) ? { ...cur[seg] } : {};
2025
+ cur[seg] = child;
2026
+ cur = child;
2027
+ }
2028
+ cur[segs[segs.length - 1]] = value;
2029
+ return root;
2030
+ }
2031
+ function reconstructState(mappings, store, stateId) {
2032
+ const s = store.getState();
2033
+ let state = {};
1734
2034
  for (const mapping of mappings) {
1735
- const key = mapping.pointer.replace(/^\//, "").split("/")[0];
1736
- if (!key) continue;
1737
- const bucket = store.entities[mapping.entityType] ?? {};
2035
+ const bucket = s.entities[mapping.entityType] ?? {};
1738
2036
  if (mapping.kind === "single") {
1739
2037
  const id = mapping.constantId;
1740
- if (id && bucket[id]) state[key] = bucket[id];
2038
+ if (id && bucket[id]) state = setAtPointer(state, mapping.pointer, bucket[id]);
1741
2039
  } else {
1742
- state[key] = Object.values(bucket);
2040
+ const order = s.lists[agUiListKey(mapping, stateId)]?.ids;
2041
+ const items = order ? order.map((id) => bucket[id]).filter(Boolean) : Object.values(bucket);
2042
+ state = setAtPointer(state, mapping.pointer, items);
1743
2043
  }
1744
2044
  }
1745
2045
  return state;
@@ -2838,18 +3138,18 @@ function parseCreateTable(sql) {
2838
3138
  function splitTopLevelCommas(body) {
2839
3139
  const parts = [];
2840
3140
  let depth = 0;
2841
- let current = "";
3141
+ let current2 = "";
2842
3142
  for (const ch of body) {
2843
3143
  if (ch === "(") depth++;
2844
3144
  else if (ch === ")") depth--;
2845
3145
  if (ch === "," && depth === 0) {
2846
- parts.push(current);
2847
- current = "";
3146
+ parts.push(current2);
3147
+ current2 = "";
2848
3148
  } else {
2849
- current += ch;
3149
+ current2 += ch;
2850
3150
  }
2851
3151
  }
2852
- if (current.trim()) parts.push(current);
3152
+ if (current2.trim()) parts.push(current2);
2853
3153
  return parts;
2854
3154
  }
2855
3155
  function sqlTypeToJsonSchema(sqlType) {
@@ -2883,9 +3183,9 @@ function sqlTypeToJsonSchema(sqlType) {
2883
3183
  warning: `sql type "${sqlType}" not explicitly mapped; defaulting to string`
2884
3184
  };
2885
3185
  }
2886
- function deepMergeUnknown(base, override) {
3186
+ function deepMergeUnknown(base, override2) {
2887
3187
  const out = { ...base };
2888
- for (const [key, value] of Object.entries(override)) {
3188
+ for (const [key, value] of Object.entries(override2)) {
2889
3189
  const baseValue = base[key];
2890
3190
  if (value !== null && typeof value === "object" && !Array.isArray(value) && baseValue !== null && typeof baseValue === "object" && !Array.isArray(baseValue)) {
2891
3191
  out[key] = deepMergeUnknown(
@@ -3289,6 +3589,6 @@ function getFacetedRowModel(preFilteredRowModel, columnId, allFilteredRowModel)
3289
3589
  return preFilteredRowModel;
3290
3590
  }
3291
3591
 
3292
- export { IncrementalView, RealtimeManager, TerminalError, TransientError, __resetActiveGraphStore, __resetEntityTransports, __resetStoreRegistry, applyAgUiDelta, applyAgUiSnapshot, applyJsonPatch, buildTenantWhere, collectDirtyPaths, configureTimeTravel, createConvexAdapter, createDevtoolsEventBus, createElectricAdapter, createFlintAdapter, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphSyncStatusStore, createGraphTool, createGraphTransaction, createLoroMergeStrategy, createPGlitePersistenceAdapter, createRow, createRuntimeScope, createSchemaGraphTool, createSupabaseRealtimeAdapter, createSurrealLiveAdapter, createTauriSqlPersistenceAdapter, createTenantScopedElectricAdapter, createWebSocketAdapter, escapeHtml, evaluateResume, exportGraphSnapshot, exportGraphSnapshotWithSchemas, flattenClauses, getCoreRowModel, getRealtimeManager as getElectricRealtimeManager, getEntityJsonSchema, getEntityTransport, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGraphSyncStatus, getGroupedRowModel, getPaginatedRowModel, getRealtimeManager, getRegisteredEntityTypes, getRegisteredStores, getSelectedRowModel, getSortedRowModel, getTimeTravelState, getValueAtPath, graphSyncStatusStore, hasCustomPredicates, humanizeFieldName, hydrateGraphFromStorage, inferSchemaFieldType, makeRestTransport, parseCreateTable, persistGraphToStorage, prepareGraphStoreScope, publishFlintMutation, queryOnce, recordGraphSnapshot, registerEntityFromSql, registerEntityJsonSchema, registerEntityTransport, registerRuntimeSchema, registerStore, registryKey, renderMarkdownToHtml, replayActionWithRetry, resetRealtimeManager, resolveActiveGraphStore, restoreGraphSnapshot, restoreGraphSnapshotBySeq, runWithGraphStore, selectGraph, setActiveGraphStore, setValueAtPath, sqlTypeToJsonSchema, startLocalFirstGraph, stepTimeTravel, subscribeTimeTravel, toEntityError, toGraphQLVariables, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses };
3592
+ export { AGUI_STATE_ENTITY_TYPE, IncrementalView, RealtimeManager, TerminalError, TransientError, __resetActiveGraphStore, __resetEntityTransports, __resetStoreRegistry, agUiListKey, applyAgUiDelta, applyAgUiSnapshot, applyGraphChanges, applyJsonPatch, batchGraphWrites, buildTenantWhere, collectDirtyPaths, configureTimeTravel, createConvexAdapter, createDevtoolsEventBus, createElectricAdapter, createFlintAdapter, createGraphAction, createGraphEffect, createGraphQLSubscriptionAdapter, createGraphSyncStatusStore, createGraphTool, createGraphTransaction, createLiveLayer, createLoroMergeStrategy, createPGlitePersistenceAdapter, createRow, createRuntimeScope, createSchemaGraphTool, createSupabaseRealtimeAdapter, createSurrealLiveAdapter, createTauriSqlPersistenceAdapter, createTenantScopedElectricAdapter, createWebSocketAdapter, escapeHtml, evaluateResume, exportGraphSnapshot, exportGraphSnapshotWithSchemas, flattenClauses, getCoreRowModel, getRealtimeManager as getElectricRealtimeManager, getEntityJsonSchema, getEntityTransport, getExpandedRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getGraphSyncStatus, getGroupedRowModel, getPaginatedRowModel, getRealtimeManager, getRegisteredEntityTypes, getRegisteredStores, getSelectedRowModel, getSortedRowModel, getTimeTravelState, getValueAtPath, graphSyncStatusStore, hasCustomPredicates, humanizeFieldName, hydrateGraphFromStorage, inferSchemaFieldType, isGraphDevtoolsEmissionEnabled, makeRestTransport, parseCreateTable, persistGraphToStorage, prepareGraphStoreScope, publishFlintMutation, queryOnce, readAgUiState, recordGraphSnapshot, registerEntityFromSql, registerEntityJsonSchema, registerEntityTransport, registerRuntimeSchema, registerStore, registryKey, renderMarkdownToHtml, replayActionWithRetry, resetRealtimeManager, resolveActiveGraphStore, restoreGraphSnapshot, restoreGraphSnapshotBySeq, runWithGraphStore, selectGraph, setActiveGraphStore, setGraphDevtoolsEmission, setValueAtPath, sqlTypeToJsonSchema, startLocalFirstGraph, stepTimeTravel, subscribeTimeTravel, toEntityError, toGraphQLVariables, toPrismaOrderBy, toPrismaWhere, toRestParams, toSQLClauses };
3293
3593
  //# sourceMappingURL=index.mjs.map
3294
3594
  //# sourceMappingURL=index.mjs.map