# All files / src/components/streams SessionNode.tsx

100% Statements 5/5
100% Branches 6/6
100% Functions 1/1
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    76x
    76x
    76x
    76x

    76x

     import { Handle, Position } from "@xyflow/react";
    import type { NodeProps } from "@xyflow/react";
    import type { JSX } from "react";
    import { sessionStatusStyle } from "../../utils/sessionStatus.js";
    import type { SessionNodeData } from "./useCoordinationLayout.js";
    import styles from "./CoordinationGraph.module.scss";

    /**
     * Custom React Flow node rendering an agent session as a status-colored card.
     * Used by {@link CoordinationGraph}; handles flow left (target) to right (source)
     * to match the bipartite LR layout.
     */
    export function SessionNode({ data }: NodeProps): JSX.Element {
      const { session, streamCount, external } = data as SessionNodeData;
      const status = sessionStatusStyle(session.status, external);
      const color = `var(${status.varName})`;
      const className = external ? `${styles.sessionNode} ${styles.external}` : styles.sessionNode;

      return (
        <div className={className} data-testid={`coordination-node-session-${session.id}`}>
          <Handle
            type="target"
            position={Position.Left}
            isConnectable={false}
            className={styles.handle}
          />
          <div className={styles.sessionAccent} style={{ backgroundColor: color }} />
          <div className={styles.nodeContent}>
            <div className={styles.nodeHeader}>
              <span className={styles.nodeTitle}>{external ? session.id : session.runtime}</span>
            </div>
            <div className={styles.nodeMeta}>
              <span className={styles.nodeSubtle} style={{ color }}>
                {status.label}
              </span>
              {streamCount > 0 && <span className={styles.countBadge}>{streamCount}</span>}
            </div>
          </div>
          <Handle
            type="source"
            position={Position.Right}
            isConnectable={false}
            className={styles.handle}
          />
        </div>
      );
    }