Astrolabe / ajxpublic /astrolabe
Repository

Graph Model & Providers

reference scope internal/graph Verification failed
  • Provider
  • Node
  • Edge
  • File
  • Stats
  • Query
  • SQLiteProvider
  • FixtureProvider
Relevant source files · 3

Everything the agent knows about a repository — its files, symbols, and the relationships between them — arrives through one small package: internal/graph. The agent never touches the filesystem or a database directly for code facts; instead it asks a Provider, an interface that abstracts "a codegraph index rooted at some repository" Provider. This abstraction is what makes astrolabe testable end to end: the real pipeline runs against a SQLite index built by the external codegraph CLI, while tests and the agent's reference harness can swap in an in-memory fixture. The agent consumes the interface via its tools, as described in Agent Tools & Budget.

How it works

The data model is deliberately minimal — four value types plus a query. A Node is a single indexed symbol (function, type, route, …) carrying its identity (ID, QualifiedName), location (FilePath, StartLine/EndLine), and presentation metadata (Signature, Docstring, IsExported) Node. Edge is a directed, typed relationship between two node IDs — calls, contains, and friends — with the line where the relationship originates Edge. File and Stats are self-describing: an indexed file with its language, and a files/nodes/edges count triple File Stats. Filtering is expressed through Query, where zero-valued fields mean "no filter": constrain by node kinds and/or file path Query.

The Provider interface is the contract every backend must honor. Open guarantees an index exists and prepares the backend for reads (implementations are explicitly allowed to shell out to the codegraph CLI to build a missing index); Close releases resources; and four read methods — Files, Nodes, Edges, Stats — expose the index Provider. Notably, reading source text is not part of the interface. It is a separate SourceFunc type, so backends stay read-only with respect to the working tree while the agent wires in a simple os.ReadFile-based implementation, ReadSource, which clamps ranges and rejects inverted ones SourceFunc.

SQLiteProvider: the production backend

SQLiteProvider reads a codegraph SQLite database at <repo>/.codegraph/codegraph.db SQLiteProvider. Its configuration is three fields: the repo root, the codegraph binary name (defaulting to "codegraph" on PATH), and a Sync flag — when Sync is false, Open never invokes the CLI and fails if no index already exists, which is how tests that pre-build the index opt out of shelling out. A Logger field receives index build/sync progress.

Open does all the lifecycle work, instrumented as a codegraph.open span. If the database file is missing it either fails (no Sync) or runs codegraph init to build one; if the file exists and Sync is on, it attempts a best-effort codegraph sync — and a sync failure (say, a lock held by another process) is only a warning, since the existing on-disk index is still perfectly readable Open. Subprocess invocations go through runCodegraph, which runs the CLI under a 10-minute timeout from the repo root, records duration/exit-code/success span attributes, and wraps failures with the CLI's combined output runCodegraph. Once the index is settled, Open opens the SQLite file in read-oriented fashion — busy_timeout pragma, a pool capped at 4 connections — and pings it before handing the handle to the read methods Open.

The read methods are thin SQL projections. Files selects the ordered file list, Edges selects all edges, and Stats is a single query of three subselect counts. Nodes is the only one that translates a Query: it builds a WHERE clause from kind IN (...) and file_path = ? conditions dynamically and returns nodes ordered by file path and start line Nodes.

FixtureProvider: the test backend

FixtureProvider is an in-memory provider that serves canned nodes, edges, and files with no codegraph binary or database involved FixtureProvider. Constructed via NewFixtureProvider, its Open/Close are no-ops, and Nodes applies the same Query semantics as the SQLite backend (kind and file-path filtering) over a linear scan. It returns defensive slices.Clone copies so callers can't mutate the fixture, and it adds one convenience beyond the interface: NodeByID for direct lookup in tests Nodes. The sample repository described in Test Fixture (Sample Repo) is the source of the canned data used with this provider.

Relationships

graph TD
    subgraph "internal/graph"
        Provider["`**Provider** (interface)`"]
        SQLiteProvider["`**SQLiteProvider**`"]
        FixtureProvider["`**FixtureProvider**`"]
        Node["`Node`"]
        Edge["`Edge`"]
        File["`File`"]
        Stats["`Stats`"]
        Query["`Query`"]
        SourceFunc["`SourceFunc / ReadSource`"]
    end
    Agent["`internal/agent.Agent`"]
    Codegraph["`codegraph CLI`"]
    DB[("`.codegraph/codegraph.db`")]

    SQLiteProvider -- "implements" --> Provider
    FixtureProvider -- "implements" --> Provider
    Provider -- "returns" --> Node
    Provider -- "returns" --> Edge
    Provider -- "returns" --> File
    Provider -- "returns" --> Stats
    Provider -- "accepts" --> Query
    Edge -- "links" --> Node
    SQLiteProvider -- "invokes" --> Codegraph
    SQLiteProvider -- "reads" --> DB
    Agent -- "queries via tools" --> Provider
    Agent -- "reads source via" --> SourceFunc

Reference

Symbol Kind What it does Location
Provider interface Read contract for a codegraph index: Open/Close plus Files, Nodes, Edges, Stats. internal/graph/graph.go
Node struct One indexed symbol: identity, location, signature, docstring, export flag. internal/graph/graph.go
Edge struct Directed, typed relationship between two node IDs, with originating line. internal/graph/graph.go
File struct An indexed source file and its language. internal/graph/graph.go
Stats struct Index summary: file, node, and edge counts. internal/graph/graph.go
Query struct Node filter by kinds and file path; zero fields mean "no filter". internal/graph/graph.go
SourceFunc / ReadSource func type / func Working-tree source reads, kept out of Provider so backends stay read-only. internal/graph/graph.go
SQLiteProvider struct Production backend: manages the codegraph CLI lifecycle and reads the SQLite index. internal/graph/sqlite.go
FixtureProvider struct In-memory provider for tests serving canned data; adds NodeByID. internal/graph/fixture.go

Generated by astrolabe from commit ecc180b3 (tag 0.4.0).