Skip to content

model

code_context_agent.tools.graph.model

Core data structures for code graph analysis.

This module defines the fundamental types for representing code as a graph: - NodeType/EdgeType enums for classification - CodeNode/CodeEdge Pydantic models for graph elements - CodeGraph class wrapping NetworkX MultiDiGraph

NodeType

Bases: Enum

Types of nodes in the code graph.

EdgeType

Bases: Enum

Types of relationships between code elements.

CodeNode

Bases: FrozenModel

A node in the code graph representing a code element.

Attributes:

Name Type Description
id str

Unique identifier (typically "file_path:symbol_name" or "file_path:line")

name str

Human-readable display name

node_type NodeType

Classification of the code element

file_path str

Absolute path to the source file

line_start int

Starting line number (0-indexed)

line_end int

Ending line number (0-indexed)

metadata dict[str, Any]

Additional properties (docstring, visibility, rule_id, etc.)

to_dict

to_dict()

Convert to dictionary for serialization.

Source code in src/code_context_agent/tools/graph/model.py
def to_dict(self) -> dict[str, Any]:
    """Convert to dictionary for serialization."""
    result = self.model_dump()
    result["node_type"] = self.node_type.value
    return result

CodeEdge

Bases: FrozenModel

An edge in the code graph representing a relationship.

Attributes:

Name Type Description
source str

Source node ID

target str

Target node ID

edge_type EdgeType

Classification of the relationship

weight float

Edge weight for algorithms (default 1.0)

metadata dict[str, Any]

Additional properties (line where relationship occurs, etc.)

to_dict

to_dict()

Convert to dictionary for serialization.

Source code in src/code_context_agent/tools/graph/model.py
def to_dict(self) -> dict[str, Any]:
    """Convert to dictionary for serialization."""
    result = self.model_dump()
    result["edge_type"] = self.edge_type.value
    return result

CodeGraph

CodeGraph()

Multi-layer code graph supporting multiple relationship types.

Wraps a NetworkX MultiDiGraph to support: - Multiple edge types between the same node pair - Node/edge attributes for metadata - Filtered views for specific relationship types

Initialize an empty code graph.

Source code in src/code_context_agent/tools/graph/model.py
def __init__(self) -> None:
    """Initialize an empty code graph."""
    self._graph: nx.MultiDiGraph = nx.MultiDiGraph()

node_count property

node_count

Return the number of nodes.

edge_count property

edge_count

Return the number of edges.

add_node

add_node(node)

Add a node to the graph.

Parameters:

Name Type Description Default
node CodeNode

The CodeNode to add

required
Source code in src/code_context_agent/tools/graph/model.py
def add_node(self, node: CodeNode) -> None:
    """Add a node to the graph.

    Args:
        node: The CodeNode to add
    """
    self._graph.add_node(
        node.id,
        name=node.name,
        node_type=node.node_type.value,
        file_path=node.file_path,
        line_start=node.line_start,
        line_end=node.line_end,
        **node.metadata,
    )

add_edge

add_edge(edge)

Add an edge to the graph.

Parameters:

Name Type Description Default
edge CodeEdge

The CodeEdge to add

required
Source code in src/code_context_agent/tools/graph/model.py
def add_edge(self, edge: CodeEdge) -> None:
    """Add an edge to the graph.

    Args:
        edge: The CodeEdge to add
    """
    self._graph.add_edge(
        edge.source,
        edge.target,
        key=edge.edge_type.value,
        edge_type=edge.edge_type.value,
        weight=edge.weight,
        **edge.metadata,
    )

has_node

has_node(node_id)

Check if a node exists in the graph.

Source code in src/code_context_agent/tools/graph/model.py
def has_node(self, node_id: str) -> bool:
    """Check if a node exists in the graph."""
    return self._graph.has_node(node_id)

has_edge

has_edge(source, target, edge_type=None)

Check if an edge exists in the graph.

Parameters:

Name Type Description Default
source str

Source node ID

required
target str

Target node ID

required
edge_type EdgeType | None

Optional edge type to check for specifically

None
Source code in src/code_context_agent/tools/graph/model.py
def has_edge(self, source: str, target: str, edge_type: EdgeType | None = None) -> bool:
    """Check if an edge exists in the graph.

    Args:
        source: Source node ID
        target: Target node ID
        edge_type: Optional edge type to check for specifically
    """
    if edge_type is None:
        return self._graph.has_edge(source, target)
    return self._graph.has_edge(source, target, key=edge_type.value)

get_node_data

get_node_data(node_id)

Get the data associated with a node.

Parameters:

Name Type Description Default
node_id str

The node ID to look up

required

Returns:

Type Description
dict[str, Any] | None

Dictionary of node attributes or None if not found

Source code in src/code_context_agent/tools/graph/model.py
def get_node_data(self, node_id: str) -> dict[str, Any] | None:
    """Get the data associated with a node.

    Args:
        node_id: The node ID to look up

    Returns:
        Dictionary of node attributes or None if not found
    """
    if not self._graph.has_node(node_id):
        return None
    return dict(self._graph.nodes[node_id])

get_nodes_by_type

get_nodes_by_type(node_type)

Get all node IDs of a specific type.

Parameters:

Name Type Description Default
node_type NodeType

The type to filter by

required

Returns:

Type Description
list[str]

List of node IDs matching the type

Source code in src/code_context_agent/tools/graph/model.py
def get_nodes_by_type(self, node_type: NodeType) -> list[str]:
    """Get all node IDs of a specific type.

    Args:
        node_type: The type to filter by

    Returns:
        List of node IDs matching the type
    """
    return [n for n, d in self._graph.nodes(data=True) if d.get("node_type") == node_type.value]

get_edges_by_type

get_edges_by_type(edge_type)

Get all edges of a specific type.

Parameters:

Name Type Description Default
edge_type EdgeType

The type to filter by

required

Returns:

Type Description
list[tuple[str, str, dict[str, Any]]]

List of (source, target, data) tuples

Source code in src/code_context_agent/tools/graph/model.py
def get_edges_by_type(self, edge_type: EdgeType) -> list[tuple[str, str, dict[str, Any]]]:
    """Get all edges of a specific type.

    Args:
        edge_type: The type to filter by

    Returns:
        List of (source, target, data) tuples
    """
    return [(u, v, d) for u, v, k, d in self._graph.edges(keys=True, data=True) if k == edge_type.value]

get_view

get_view(edge_types=None)

Get a filtered view of the graph for analysis algorithms.

Creates a simple DiGraph (not Multi) with only the specified edge types. Multiple edges between the same nodes are aggregated by summing weights.

Parameters:

Name Type Description Default
edge_types list[EdgeType] | None

List of edge types to include (None = all types)

None

Returns:

Type Description
DiGraph

A NetworkX DiGraph suitable for analysis algorithms

Source code in src/code_context_agent/tools/graph/model.py
def get_view(self, edge_types: list[EdgeType] | None = None) -> nx.DiGraph:
    """Get a filtered view of the graph for analysis algorithms.

    Creates a simple DiGraph (not Multi) with only the specified edge types.
    Multiple edges between the same nodes are aggregated by summing weights.

    Args:
        edge_types: List of edge types to include (None = all types)

    Returns:
        A NetworkX DiGraph suitable for analysis algorithms
    """
    view = nx.DiGraph()

    # Copy all nodes with their attributes
    view.add_nodes_from(self._graph.nodes(data=True))

    # Filter and aggregate edges
    for u, v, k, d in self._graph.edges(keys=True, data=True):
        if edge_types is None or EdgeType(k) in edge_types:
            if view.has_edge(u, v):
                # Aggregate weights
                view[u][v]["weight"] += d.get("weight", 1.0)
            else:
                view.add_edge(u, v, weight=d.get("weight", 1.0), types=[k])

    return view

nodes

nodes(data=False)

Return nodes, optionally with data.

Parameters:

Name Type Description Default
data bool

If True, return (node_id, data) tuples

False

Returns:

Type Description
Any

Node view from underlying NetworkX graph

Source code in src/code_context_agent/tools/graph/model.py
def nodes(self, data: bool = False) -> Any:
    """Return nodes, optionally with data.

    Args:
        data: If True, return (node_id, data) tuples

    Returns:
        Node view from underlying NetworkX graph
    """
    return self._graph.nodes(data=data)

edges

edges(data=False)

Return edges, optionally with data.

Parameters:

Name Type Description Default
data bool

If True, return (source, target, data) tuples

False

Returns:

Type Description
Any

Edge view from underlying NetworkX graph

Source code in src/code_context_agent/tools/graph/model.py
def edges(self, data: bool = False) -> Any:
    """Return edges, optionally with data.

    Args:
        data: If True, return (source, target, data) tuples

    Returns:
        Edge view from underlying NetworkX graph
    """
    return self._graph.edges(data=data)
to_node_link_data()

Export graph as node-link JSON format.

Returns:

Type Description
dict[str, Any]

Dictionary suitable for JSON serialization

Source code in src/code_context_agent/tools/graph/model.py
def to_node_link_data(self) -> dict[str, Any]:
    """Export graph as node-link JSON format.

    Returns:
        Dictionary suitable for JSON serialization
    """
    return nx.node_link_data(self._graph)
from_node_link_data(data)

Create a CodeGraph from node-link JSON format.

Handles both old NetworkX format ("links" key) and new 3.6+ format ("edges" key) for backward compatibility with saved graphs.

Parameters:

Name Type Description Default
data dict[str, Any]

Dictionary from node_link_data or JSON

required

Returns:

Type Description
CodeGraph

New CodeGraph instance

Source code in src/code_context_agent/tools/graph/model.py
@classmethod
def from_node_link_data(cls, data: dict[str, Any]) -> "CodeGraph":
    """Create a CodeGraph from node-link JSON format.

    Handles both old NetworkX format ("links" key) and new 3.6+
    format ("edges" key) for backward compatibility with saved graphs.

    Args:
        data: Dictionary from node_link_data or JSON

    Returns:
        New CodeGraph instance
    """
    graph = cls()
    # Handle both old ("links") and new ("edges") format
    if "links" in data and "edges" not in data:
        graph._graph = nx.node_link_graph(data, edges="links")
    else:
        graph._graph = nx.node_link_graph(data)
    return graph

describe

describe()

Get a quick summary of the graph.

Returns:

Type Description
dict[str, Any]

Dictionary with node count, edge count, type distributions, and density.

Source code in src/code_context_agent/tools/graph/model.py
def describe(self) -> dict[str, Any]:
    """Get a quick summary of the graph.

    Returns:
        Dictionary with node count, edge count, type distributions, and density.
    """
    node_types: dict[str, int] = {}
    for _, data in self._graph.nodes(data=True):
        nt = data.get("node_type", "unknown")
        node_types[nt] = node_types.get(nt, 0) + 1

    edge_types: dict[str, int] = {}
    for _, _, k, _ in self._graph.edges(keys=True, data=True):
        edge_types[k] = edge_types.get(k, 0) + 1

    return {
        "node_count": self.node_count,
        "edge_count": self.edge_count,
        "node_types": node_types,
        "edge_types": edge_types,
        "density": nx.density(self._graph),
    }

lsp_kind_to_node_type

lsp_kind_to_node_type(kind)

Convert LSP SymbolKind to NodeType.

Source code in src/code_context_agent/tools/graph/model.py
def lsp_kind_to_node_type(kind: int) -> NodeType:
    """Convert LSP SymbolKind to NodeType."""
    return LSP_SYMBOL_KIND_MAP.get(kind, NodeType.VARIABLE)