langchain_agentx_stream_ui 0.3.2 → 0.3.4

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.js CHANGED
@@ -1426,6 +1426,42 @@ function contentBlockFromEvent(event) {
1426
1426
  }
1427
1427
  return null;
1428
1428
  }
1429
+ function wouldAssignParentCreateCycle(containersById, containerId, parentId) {
1430
+ if (!parentId) return false;
1431
+ if (parentId === containerId) return true;
1432
+ const seen = /* @__PURE__ */ new Set();
1433
+ let current = parentId;
1434
+ while (current) {
1435
+ if (current === containerId) return true;
1436
+ if (seen.has(current)) return true;
1437
+ seen.add(current);
1438
+ current = containersById[current]?.parent_container_id ?? null;
1439
+ }
1440
+ return false;
1441
+ }
1442
+ function sanitizeContainerTreeParentLinks(containersById) {
1443
+ const next = { ...containersById };
1444
+ for (const [containerId, node] of Object.entries(next)) {
1445
+ const seen = /* @__PURE__ */ new Set([containerId]);
1446
+ let current = node.parent_container_id;
1447
+ while (current) {
1448
+ if (seen.has(current)) {
1449
+ next[containerId] = { ...node, parent_container_id: null };
1450
+ break;
1451
+ }
1452
+ seen.add(current);
1453
+ current = next[current]?.parent_container_id ?? null;
1454
+ }
1455
+ }
1456
+ return next;
1457
+ }
1458
+ function normalizeSnapshotContainerContentBlocks(containersById) {
1459
+ const next = {};
1460
+ for (const [containerId, node] of Object.entries(containersById)) {
1461
+ next[containerId] = { ...node, content_blocks: node.content_blocks ?? [] };
1462
+ }
1463
+ return next;
1464
+ }
1429
1465
  function resolveContentScopeKey(data) {
1430
1466
  for (const keyName of ["stage_key", "item_key", "branch_key", "aggregate_key", "debug_key"]) {
1431
1467
  const value = readString(data, keyName);
@@ -1503,7 +1539,11 @@ var WorkflowContainerActiveSet = class {
1503
1539
  );
1504
1540
  }
1505
1541
  }
1506
- return this.deepestActive();
1542
+ const openNonWorkflow = this.openOrder.map((cid) => this.nodes[cid]).filter((node) => node.is_open && node.scope !== "workflow");
1543
+ if (openNonWorkflow.length === 1) {
1544
+ return openNonWorkflow[0].container_id;
1545
+ }
1546
+ return null;
1507
1547
  }
1508
1548
  closeDescendantsOfPath(workflowPath, status) {
1509
1549
  const toClose = this.openOrder.filter((cid) => {
@@ -1581,7 +1621,12 @@ var WorkflowContainerStateMachine = class {
1581
1621
  const subtitle = display?.description ?? "";
1582
1622
  const pattern = display?.pattern ?? "";
1583
1623
  const status = displayStatus(data, "running");
1584
- const parentId = this.resolveParentId(workflowPath, scope);
1624
+ const existing = this.active.getNode(containerId);
1625
+ const computedParentId = this.resolveParentId(workflowPath, scope);
1626
+ let parentId = existing != null ? existing.parent_container_id : computedParentId;
1627
+ if (wouldAssignParentCreateCycle(this.active.nodesById, containerId, parentId)) {
1628
+ parentId = existing?.parent_container_id ?? null;
1629
+ }
1585
1630
  const node = {
1586
1631
  container_id: containerId,
1587
1632
  scope,
@@ -1594,7 +1639,7 @@ var WorkflowContainerStateMachine = class {
1594
1639
  pattern,
1595
1640
  parent_container_id: parentId,
1596
1641
  display,
1597
- content_blocks: [],
1642
+ content_blocks: existing?.content_blocks ?? [],
1598
1643
  is_open: true
1599
1644
  };
1600
1645
  this.active.open(node);
@@ -1672,9 +1717,7 @@ var WorkflowContainerStateMachine = class {
1672
1717
  (best, node) => this.active.compareContainerRank(node.container_id, best.container_id) > 0 ? node : best
1673
1718
  ).container_id;
1674
1719
  }
1675
- return openNodes.reduce(
1676
- (best, node) => this.active.compareContainerRank(node.container_id, best.container_id) > 0 ? node : best
1677
- ).container_id;
1720
+ return null;
1678
1721
  }
1679
1722
  };
1680
1723
  var WorkflowContainerTreeProjector = class {
@@ -2802,6 +2845,10 @@ function isAtOrBeforeProjectionCursor(projectionCursor, eventId) {
2802
2845
  }
2803
2846
  function hydrateWorkflowFromSnapshot(state, snapshot, options = {}) {
2804
2847
  const authority = options.preserveAuthority ? state.authority : null;
2848
+ const containerTree = structuredClone(snapshot.containerTree);
2849
+ containerTree.containersById = normalizeSnapshotContainerContentBlocks(
2850
+ sanitizeContainerTreeParentLinks(containerTree.containersById)
2851
+ );
2805
2852
  return {
2806
2853
  ...createEmptyWorkflowSessionState(),
2807
2854
  authority,
@@ -2809,7 +2856,7 @@ function hydrateWorkflowFromSnapshot(state, snapshot, options = {}) {
2809
2856
  ...snapshot.display,
2810
2857
  streamEnded: false
2811
2858
  },
2812
- containerTree: structuredClone(snapshot.containerTree),
2859
+ containerTree,
2813
2860
  projectionCursor: snapshot.cursor,
2814
2861
  snapshotVersion: snapshot.snapshotVersion,
2815
2862
  meta: {
@@ -4502,22 +4549,30 @@ function stageHasSubworkflowChild(stageId, containerTree) {
4502
4549
  (node) => node.scope === "subworkflow"
4503
4550
  );
4504
4551
  }
4505
- function renderContainerChildren(parentId, containerTree, loopTreesBySessionId, viewProps, depth) {
4552
+ function renderContainerChildren(parentId, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited = /* @__PURE__ */ new Set()) {
4506
4553
  const children = collectChildContainers(containerTree.containersById, parentId);
4507
4554
  const items = children.filter((node) => node.scope === "item");
4508
4555
  const rest = children.filter((node) => node.scope !== "item");
4509
4556
  return /* @__PURE__ */ jsxs10(Fragment2, { children: [
4510
4557
  renderItemSiblings(items, parentId, depth, containerTree, loopTreesBySessionId, viewProps),
4511
- rest.map((node) => renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth))
4558
+ rest.map(
4559
+ (node) => renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited)
4560
+ )
4512
4561
  ] });
4513
4562
  }
4514
- function renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth) {
4563
+ function renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited = /* @__PURE__ */ new Set()) {
4564
+ if (ancestorVisited.has(node.container_id)) {
4565
+ return null;
4566
+ }
4567
+ const pathVisited = new Set(ancestorVisited);
4568
+ pathVisited.add(node.container_id);
4515
4569
  const nested = renderContainerChildren(
4516
4570
  node.container_id,
4517
4571
  containerTree,
4518
4572
  loopTreesBySessionId,
4519
4573
  viewProps,
4520
- depth + 1
4574
+ depth + 1,
4575
+ pathVisited
4521
4576
  );
4522
4577
  const hasNested = collectChildContainers(containerTree.containersById, node.container_id).length > 0;
4523
4578
  if (node.scope === "subworkflow") {