langchain_agentx_stream_ui 0.3.2 → 0.3.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/index.js CHANGED
@@ -1426,6 +1426,35 @@ 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
+ }
1429
1458
  function resolveContentScopeKey(data) {
1430
1459
  for (const keyName of ["stage_key", "item_key", "branch_key", "aggregate_key", "debug_key"]) {
1431
1460
  const value = readString(data, keyName);
@@ -1503,7 +1532,11 @@ var WorkflowContainerActiveSet = class {
1503
1532
  );
1504
1533
  }
1505
1534
  }
1506
- return this.deepestActive();
1535
+ const openNonWorkflow = this.openOrder.map((cid) => this.nodes[cid]).filter((node) => node.is_open && node.scope !== "workflow");
1536
+ if (openNonWorkflow.length === 1) {
1537
+ return openNonWorkflow[0].container_id;
1538
+ }
1539
+ return null;
1507
1540
  }
1508
1541
  closeDescendantsOfPath(workflowPath, status) {
1509
1542
  const toClose = this.openOrder.filter((cid) => {
@@ -1581,7 +1614,12 @@ var WorkflowContainerStateMachine = class {
1581
1614
  const subtitle = display?.description ?? "";
1582
1615
  const pattern = display?.pattern ?? "";
1583
1616
  const status = displayStatus(data, "running");
1584
- const parentId = this.resolveParentId(workflowPath, scope);
1617
+ const existing = this.active.getNode(containerId);
1618
+ const computedParentId = this.resolveParentId(workflowPath, scope);
1619
+ let parentId = existing != null ? existing.parent_container_id : computedParentId;
1620
+ if (wouldAssignParentCreateCycle(this.active.nodesById, containerId, parentId)) {
1621
+ parentId = existing?.parent_container_id ?? null;
1622
+ }
1585
1623
  const node = {
1586
1624
  container_id: containerId,
1587
1625
  scope,
@@ -1594,7 +1632,7 @@ var WorkflowContainerStateMachine = class {
1594
1632
  pattern,
1595
1633
  parent_container_id: parentId,
1596
1634
  display,
1597
- content_blocks: [],
1635
+ content_blocks: existing?.content_blocks ?? [],
1598
1636
  is_open: true
1599
1637
  };
1600
1638
  this.active.open(node);
@@ -1672,9 +1710,7 @@ var WorkflowContainerStateMachine = class {
1672
1710
  (best, node) => this.active.compareContainerRank(node.container_id, best.container_id) > 0 ? node : best
1673
1711
  ).container_id;
1674
1712
  }
1675
- return openNodes.reduce(
1676
- (best, node) => this.active.compareContainerRank(node.container_id, best.container_id) > 0 ? node : best
1677
- ).container_id;
1713
+ return null;
1678
1714
  }
1679
1715
  };
1680
1716
  var WorkflowContainerTreeProjector = class {
@@ -2802,6 +2838,10 @@ function isAtOrBeforeProjectionCursor(projectionCursor, eventId) {
2802
2838
  }
2803
2839
  function hydrateWorkflowFromSnapshot(state, snapshot, options = {}) {
2804
2840
  const authority = options.preserveAuthority ? state.authority : null;
2841
+ const containerTree = structuredClone(snapshot.containerTree);
2842
+ containerTree.containersById = sanitizeContainerTreeParentLinks(
2843
+ containerTree.containersById
2844
+ );
2805
2845
  return {
2806
2846
  ...createEmptyWorkflowSessionState(),
2807
2847
  authority,
@@ -2809,7 +2849,7 @@ function hydrateWorkflowFromSnapshot(state, snapshot, options = {}) {
2809
2849
  ...snapshot.display,
2810
2850
  streamEnded: false
2811
2851
  },
2812
- containerTree: structuredClone(snapshot.containerTree),
2852
+ containerTree,
2813
2853
  projectionCursor: snapshot.cursor,
2814
2854
  snapshotVersion: snapshot.snapshotVersion,
2815
2855
  meta: {
@@ -4502,22 +4542,30 @@ function stageHasSubworkflowChild(stageId, containerTree) {
4502
4542
  (node) => node.scope === "subworkflow"
4503
4543
  );
4504
4544
  }
4505
- function renderContainerChildren(parentId, containerTree, loopTreesBySessionId, viewProps, depth) {
4545
+ function renderContainerChildren(parentId, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited = /* @__PURE__ */ new Set()) {
4506
4546
  const children = collectChildContainers(containerTree.containersById, parentId);
4507
4547
  const items = children.filter((node) => node.scope === "item");
4508
4548
  const rest = children.filter((node) => node.scope !== "item");
4509
4549
  return /* @__PURE__ */ jsxs10(Fragment2, { children: [
4510
4550
  renderItemSiblings(items, parentId, depth, containerTree, loopTreesBySessionId, viewProps),
4511
- rest.map((node) => renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth))
4551
+ rest.map(
4552
+ (node) => renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited)
4553
+ )
4512
4554
  ] });
4513
4555
  }
4514
- function renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth) {
4556
+ function renderContainerNode(node, containerTree, loopTreesBySessionId, viewProps, depth, ancestorVisited = /* @__PURE__ */ new Set()) {
4557
+ if (ancestorVisited.has(node.container_id)) {
4558
+ return null;
4559
+ }
4560
+ const pathVisited = new Set(ancestorVisited);
4561
+ pathVisited.add(node.container_id);
4515
4562
  const nested = renderContainerChildren(
4516
4563
  node.container_id,
4517
4564
  containerTree,
4518
4565
  loopTreesBySessionId,
4519
4566
  viewProps,
4520
- depth + 1
4567
+ depth + 1,
4568
+ pathVisited
4521
4569
  );
4522
4570
  const hasNested = collectChildContainers(containerTree.containersById, node.container_id).length > 0;
4523
4571
  if (node.scope === "subworkflow") {