Documentation
¶
Overview ¶
Package graph provides the core graph data structures and operations for Axon.
The graph consists of nodes and edges. Nodes represent entities (files, directories, git repos, markdown documents, etc.) and edges represent relationships between them (contains, has, links_to, etc.).
The Graph type wraps a Storage implementation and provides high-level operations like AddNode, AddEdge, Neighbors, Children, and Parents. It also handles type validation through a Registry.
Storage implementations (like SQLite) handle persistence and querying. The Storage interface is broken into smaller composable interfaces (NodeReader, NodeWriter, etc.) for flexibility.
Index ¶
- Variables
- func IDFromEdgeKey(edgeType, from, to string) string
- func IDFromURI(uri string) string
- func NewID() string
- func RegisterNodeType[T any](r *Registry, spec NodeSpec)
- type AQLQuerier
- type CountItem
- type DatabaseInfo
- type Describer
- type Direction
- type Edge
- type EdgeConnection
- type EdgeFilter
- type EdgeQuerier
- type EdgeReader
- type EdgeSpec
- type EdgeStore
- type EdgeTypeInfo
- type EdgeWriter
- type EmbeddingStore
- type Flusher
- type Graph
- func (g *Graph) AddEdge(ctx context.Context, e *Edge) error
- func (g *Graph) AddNode(ctx context.Context, n *Node) error
- func (g *Graph) Children(ctx context.Context, nodeID string) ([]*Node, error)
- func (g *Graph) CountEdges(ctx context.Context, filter EdgeFilter, opts QueryOptions) (map[string]int, error)
- func (g *Graph) CountNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) (map[string]int, error)
- func (g *Graph) DeleteEdge(ctx context.Context, id string) error
- func (g *Graph) DeleteNode(ctx context.Context, id string) error
- func (g *Graph) FindNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) ([]*Node, error)
- func (g *Graph) GetEdge(ctx context.Context, id string) (*Edge, error)
- func (g *Graph) GetEdgesFrom(ctx context.Context, nodeID string) ([]*Edge, error)
- func (g *Graph) GetEdgesTo(ctx context.Context, nodeID string) ([]*Edge, error)
- func (g *Graph) GetNode(ctx context.Context, id string) (*Node, error)
- func (g *Graph) GetNodeByURI(ctx context.Context, uri string) (*Node, error)
- func (g *Graph) Neighbors(ctx context.Context, nodeID string, dir Direction) ([]*Node, error)
- func (g *Graph) Parents(ctx context.Context, nodeID string) ([]*Node, error)
- func (g *Graph) Registry() *Registry
- func (g *Graph) Storage() Storage
- type IndexRunRecord
- type IndexRunTracker
- type Node
- func (n *Node) AddLabels(labels ...string)
- func (n *Node) Clone() *Node
- func (n *Node) HasLabel(label string) bool
- func (n *Node) WithData(data any) *Node
- func (n *Node) WithGeneration(gen string) *Node
- func (n *Node) WithKey(key string) *Node
- func (n *Node) WithLabels(labels ...string) *Node
- func (n *Node) WithName(name string) *Node
- func (n *Node) WithTTL(d time.Duration) *Node
- func (n *Node) WithURI(uri string) *Node
- type NodeFilter
- type NodeQuerier
- type NodeReader
- type NodeSpec
- type NodeStore
- type NodeTypeInfo
- type NodeWithScore
- type NodeWriter
- type QueryOptions
- type QueryPlan
- type QueryResult
- type Registry
- func (r *Registry) EdgeSpec(edgeType string) (EdgeSpec, bool)
- func (r *Registry) EdgeTypes() []string
- func (r *Registry) NodeSpec(nodeType string) (NodeSpec, bool)
- func (r *Registry) NodeTypes() []string
- func (r *Registry) RegisterEdgeType(spec EdgeSpec)
- func (r *Registry) ValidateEdge(e *Edge, fromNode, toNode *Node) error
- func (r *Registry) ValidateNode(n *Node) error
- type ResultType
- type SchemaDescription
- type StalenessManager
- type Storage
Constants ¶
This section is empty.
Variables ¶
var ErrUnknownEdgeType = errors.New("unknown edge type")
ErrUnknownEdgeType is returned when an edge type is not registered.
var ErrUnknownNodeType = errors.New("unknown node type")
ErrUnknownNodeType is returned when a node type is not registered.
Functions ¶
func IDFromEdgeKey ¶
IDFromEdgeKey generates a deterministic ID from an edge's natural key. The natural key is (type, from, to). Same key always produces the same ID.
func IDFromURI ¶
IDFromURI generates a deterministic ID from a URI. The ID is URL-safe base64 encoded (22 characters) derived from SHA256. Same URI always produces the same ID.
func RegisterNodeType ¶
RegisterNodeType registers a node type with its data schema. The generic type T specifies what type the node's Data field should hold.
Types ¶
type AQLQuerier ¶
type AQLQuerier interface {
Query(ctx context.Context, query interface{}) (*QueryResult, error)
Explain(ctx context.Context, query interface{}) (*QueryPlan, error)
}
AQLQuerier provides AQL (Axon Query Language) query execution.
type CountItem ¶ added in v0.2.0
CountItem represents a single aggregated count result (key + count). Used in QueryResult.Counts for GROUP BY queries, preserving SQLite result order.
type DatabaseInfo ¶
type DatabaseInfo interface {
GetDatabasePath() string
}
DatabaseInfo provides database metadata.
type Describer ¶ added in v0.10.0
type Describer interface {
DescribeSchema(ctx context.Context, includeFields bool) (*SchemaDescription, error)
}
Describer is an optional interface that storage implementations may satisfy to provide schema introspection. It is intentionally NOT embedded in Storage so that existing test mocks are not affected.
includeFields, when true, causes an additional per-type query to discover the JSON data field names actually stored in nodes of each type. This samples up to 500 nodes per type and may be slightly slower on large graphs.
type Edge ¶
type Edge struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Data any `json:"data,omitempty"`
Generation string `json:"generation,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"` // nil means the edge never expires (immortal)
}
Edge represents a directed relationship between two nodes.
func NewEdge ¶
NewEdge creates a new edge with the given type and endpoints. The edge ID is deterministic based on (type, from, to), ensuring the same edge always has the same ID.
func (*Edge) WithGeneration ¶
WithGeneration sets the edge's generation for staleness tracking.
type EdgeConnection ¶ added in v0.10.0
type EdgeConnection struct {
From string `json:"from"`
To string `json:"to"`
Count int `json:"count"`
}
EdgeConnection describes a from→to node-type pair for an edge type.
type EdgeFilter ¶
type EdgeFilter struct {
Type string // Filter by exact edge type (empty = any)
Types []string // Filter by multiple edge types (OR logic, empty = any)
Direction string // For traversal: "outgoing", "incoming", "both" (default: "outgoing")
From *NodeFilter // Filter by from-node properties (nil = any)
To *NodeFilter // Filter by to-node properties (nil = any)
}
EdgeFilter specifies criteria for finding/counting edges.
type EdgeQuerier ¶
type EdgeQuerier interface {
CountEdges(ctx context.Context, filter EdgeFilter, opts QueryOptions) (map[string]int, error)
}
EdgeQuerier provides edge query capabilities.
type EdgeReader ¶
type EdgeReader interface {
GetEdge(ctx context.Context, id string) (*Edge, error)
GetEdgesFrom(ctx context.Context, nodeID string) ([]*Edge, error)
GetEdgesTo(ctx context.Context, nodeID string) ([]*Edge, error)
}
EdgeReader provides read access to edges.
type EdgeSpec ¶
type EdgeSpec struct {
Type string
Description string
FromTypes []string // Allowed source node types (empty = any)
ToTypes []string // Allowed target node types (empty = any)
}
EdgeSpec describes a registered edge type.
type EdgeStore ¶
type EdgeStore interface {
EdgeReader
EdgeWriter
}
EdgeStore combines read and write access to edges.
type EdgeTypeInfo ¶ added in v0.10.0
type EdgeTypeInfo struct {
Type string `json:"type"`
Count int `json:"count"`
Connections []EdgeConnection `json:"connections"`
}
EdgeTypeInfo describes an edge type in the graph.
type EdgeWriter ¶
type EdgeWriter interface {
PutEdge(ctx context.Context, edge *Edge) error
DeleteEdge(ctx context.Context, id string) error
}
EdgeWriter provides write access to edges.
type EmbeddingStore ¶ added in v0.5.0
type EmbeddingStore interface {
PutEmbedding(ctx context.Context, nodeID string, embedding []float32) error
GetEmbedding(ctx context.Context, nodeID string) ([]float32, error)
FindSimilar(ctx context.Context, query []float32, limit int, filter *NodeFilter) ([]*NodeWithScore, error)
}
EmbeddingStore provides vector embedding storage and similarity search.
type Graph ¶
type Graph struct {
// contains filtered or unexported fields
}
Graph provides high-level operations over the storage layer.
func (*Graph) Children ¶
Children returns all nodes that this node contains or has (owns). Filters to only "contains" and "has" edges (parent→child relationships).
func (*Graph) CountEdges ¶
func (g *Graph) CountEdges(ctx context.Context, filter EdgeFilter, opts QueryOptions) (map[string]int, error)
CountEdges returns edge counts grouped by the specified field.
func (*Graph) CountNodes ¶
func (g *Graph) CountNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) (map[string]int, error)
CountNodes returns node counts grouped by the specified field.
func (*Graph) DeleteEdge ¶
DeleteEdge removes an edge from the graph.
func (*Graph) DeleteNode ¶
DeleteNode removes a node from the graph.
func (*Graph) FindNodes ¶
func (g *Graph) FindNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) ([]*Node, error)
FindNodes finds nodes matching the given filter.
func (*Graph) GetEdgesFrom ¶
GetEdgesFrom returns all edges originating from the given node.
func (*Graph) GetEdgesTo ¶
GetEdgesTo returns all edges pointing to the given node.
func (*Graph) GetNodeByURI ¶
GetNodeByURI retrieves a node by its URI.
func (*Graph) Neighbors ¶
Neighbors returns all nodes connected to the given node in the specified direction.
type IndexRunRecord ¶
type IndexRunRecord struct {
ID int64
StartedAt time.Time
FinishedAt time.Time
DurationMs int64
RootPath string
FilesIndexed int
DirsIndexed int
ReposIndexed int
StaleRemoved int
Generation string
}
IndexRunRecord represents a single indexing run for tracking history.
type IndexRunTracker ¶
type IndexRunTracker interface {
RecordIndexRun(ctx context.Context, run IndexRunRecord) error
GetLastIndexRun(ctx context.Context) (*IndexRunRecord, error)
}
IndexRunTracker tracks indexing run history.
type Node ¶
type Node struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
URI string `json:"uri,omitempty"`
Key string `json:"key,omitempty"`
Name string `json:"name,omitempty"` // Human-readable name (filename, branch name, section title)
Labels []string `json:"labels,omitempty"` // Categorical labels (e.g., "ci:config", "agent:instructions")
Data any `json:"data,omitempty"`
Generation string `json:"generation,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"` // nil means the node never expires (immortal)
}
Node represents a vertex in the graph.
func (*Node) Clone ¶
Clone returns a shallow copy of the node with a cloned Labels slice. The Data field is shared (not deep-copied) since it's typically read-only.
func (*Node) WithGeneration ¶
WithGeneration sets the node's generation for staleness tracking.
func (*Node) WithLabels ¶
WithLabels adds labels to the node and returns the node for chaining.
func (*Node) WithName ¶
WithName sets the node's human-readable name and returns the node for chaining.
type NodeFilter ¶
type NodeFilter struct {
Type string // Filter by exact node type (empty = any)
TypePattern string // Filter by node type with glob pattern (empty = any)
URIPrefix string // Filter by URI prefix (empty = any)
Name string // Filter by exact name (empty = any)
NamePattern string // Filter by name with glob pattern (empty = any)
Labels []string // Filter by labels (OR logic - node must have at least one)
Extensions []string // Filter by file extension without dot (OR logic, e.g., "go", "py")
NodeIDs []string // Filter to specific node IDs (OR logic)
Generation string // Filter by exact generation ID (empty = any). Pass indexer.Context.Generation
// to scope a query to only nodes written in the current indexing run.
Root bool // Only nodes with no incoming containment edges (top-level roots)
ExcludeTypes []string // Exclude nodes whose type matches any of these values (OR logic)
}
NodeFilter specifies criteria for finding nodes.
func (NodeFilter) Normalize ¶ added in v0.9.1
func (f NodeFilter) Normalize() NodeFilter
Normalize returns a copy of f with normalized field values. Extensions are stripped of any leading dot so that "go" and ".go" are treated identically — callers need not pre-strip the dot.
type NodeQuerier ¶
type NodeQuerier interface {
FindNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) ([]*Node, error)
CountNodes(ctx context.Context, filter NodeFilter, opts QueryOptions) (map[string]int, error)
}
NodeQuerier provides node query capabilities.
type NodeReader ¶
type NodeReader interface {
GetNode(ctx context.Context, id string) (*Node, error)
GetNodeByURI(ctx context.Context, uri string) (*Node, error)
GetNodeByKey(ctx context.Context, nodeType, key string) (*Node, error)
}
NodeReader provides read access to nodes.
type NodeSpec ¶
type NodeSpec struct {
Type string
Description string
DataType reflect.Type // The Go type for Data field
}
NodeSpec describes a registered node type.
type NodeStore ¶
type NodeStore interface {
NodeReader
NodeWriter
}
NodeStore combines read and write access to nodes.
type NodeTypeInfo ¶ added in v0.10.0
type NodeTypeInfo struct {
Type string `json:"type"`
Count int `json:"count"`
Fields []string `json:"fields,omitempty"`
}
NodeTypeInfo describes a node type in the graph.
type NodeWithScore ¶ added in v0.5.0
NodeWithScore is a node with a similarity score for semantic search results.
type NodeWriter ¶
type NodeWriter interface {
PutNode(ctx context.Context, node *Node) error
DeleteNode(ctx context.Context, id string) error
}
NodeWriter provides write access to nodes.
type QueryOptions ¶
type QueryOptions struct {
GroupBy string // "type", "label", "extension" or "" for no grouping
OrderBy string // "count", "name" for counts; "name", "updated", "type" for nodes
Desc bool // true for descending order
Limit int // 0 for no limit
}
QueryOptions specifies aggregation, ordering, and limiting for queries.
type QueryPlan ¶
type QueryPlan struct {
SQL string // Generated SQL query
Args []any // Query arguments
SQLitePlan string // Output of EXPLAIN QUERY PLAN
EstimatedMs int64 // Estimated execution time (if available)
}
QueryPlan holds the execution plan for an AQL query. Used for debugging and performance analysis.
type QueryResult ¶
type QueryResult struct {
Type ResultType
Nodes []*Node
Edges []*Edge
Counts []CountItem // For GROUP BY queries, in SQLite result order
SelectedColumns []string // Column names in SELECT order; nil means SELECT *
Rows []map[string]any // For ResultTypeRows: multi-variable pattern results
GroupingColumn string // For ResultTypeCounts GROUP BY: the grouping column name
}
QueryResult holds the results of an AQL query execution. Fields are populated based on the result type: - ResultTypeNodes: Nodes slice is populated - ResultTypeEdges: Edges slice is populated - ResultTypeCounts: Counts slice is populated - ResultTypeRows: Rows slice is populated (multi-variable pattern SELECT)
SelectedColumns is set for non-star SELECT queries, in SELECT order.
func (*QueryResult) Count ¶
func (qr *QueryResult) Count() int
Count returns the scalar count value for SELECT COUNT(*) queries. For scalar COUNT queries (no GROUP BY), looks for the "_count" sentinel item. For GROUP BY queries, returns the sum of all counts. Returns 0 if not a count query or if result is empty.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds registered node and edge type specifications.
func (*Registry) RegisterEdgeType ¶
RegisterEdgeType registers an edge type.
func (*Registry) ValidateEdge ¶
ValidateEdge validates that an edge's type is registered and that the from/to node types are allowed (if constraints are specified).
func (*Registry) ValidateNode ¶
ValidateNode validates that a node's type is registered.
type ResultType ¶
type ResultType int
ResultType indicates the type of query result.
const ( ResultTypeNodes ResultType = iota ResultTypeEdges ResultTypeCounts ResultTypeRows // Multi-variable or cross-variable field-selector pattern queries )
type SchemaDescription ¶ added in v0.10.0
type SchemaDescription struct {
NodeTypes []NodeTypeInfo `json:"node_types"`
EdgeTypes []EdgeTypeInfo `json:"edge_types"`
}
SchemaDescription is the result of schema introspection. It describes all node types and edge types currently present in the graph, along with their counts and (optionally) the data field names available on each node type.
type StalenessManager ¶
type StalenessManager interface {
FindStaleByURIPrefix(ctx context.Context, uriPrefix, currentGen string) ([]*Node, error)
DeleteStaleByURIPrefix(ctx context.Context, uriPrefix, currentGen string) (int, error)
DeleteByURIPrefix(ctx context.Context, uriPrefix string) (int, error)
DeleteStaleEdges(ctx context.Context, currentGen string) (int, error)
DeleteOrphanedEdges(ctx context.Context) (int, error)
CountOrphanedEdges(ctx context.Context) (int, error)
FindOrphanedEdges(ctx context.Context) ([]*Edge, error)
// DeleteExpired physically removes all nodes and edges whose ExpiresAt is in
// the past. Returns (nodesDeleted, edgesDeleted, error). This is called by
// "axon gc" and the background watch-mode ticker.
DeleteExpired(ctx context.Context) (int64, int64, error)
// CountExpired returns the count of expired nodes and edges without deleting
// them. Used for dry-run reporting in "axon gc --dry-run".
CountExpired(ctx context.Context) (int64, int64, error)
}
StalenessManager handles generation-based cleanup for indexers.
type Storage ¶
type Storage interface {
NodeStore
EdgeStore
NodeQuerier
EdgeQuerier
StalenessManager
IndexRunTracker
Flusher
DatabaseInfo
AQLQuerier
EmbeddingStore
}
Storage defines the complete interface for graph persistence. It composes all the smaller interfaces for full functionality.