Documentation
¶
Overview ¶
Package liveview serves a knowledge graph as a live, rotatable 3D page.
A rendered file is true for the instant it was taken. This serves a page instead — a WebGL scene on 127.0.0.1 that keeps up with the graph on its own, so a graph being written can be watched rather than re-rendered.
Two things move on the page, and they arrive by different routes:
- Structure — nodes and relations appearing or disappearing. Found by polling the graph and diffing, because it can be written by any process sharing it and there is no change feed to subscribe to. Only the difference is sent, so the layout keeps every node that did not change exactly where it had settled.
- Activity — a query running, something being saved, a relation drawn. A query changes nothing in the graph, so no amount of polling can show one. These are reported by whoever handled the call, through Server.Observe, and light up the nodes they named.
A caller supplies a Source, which is anything that can read nodes and edges. OpenSource builds one from the ambient CortexDB configuration (CORTEXDB_REMOTE for a shared brain, CORTEXDB_PATH otherwise), and LoadLocal and LoadRemote are exported for callers that know which graph they want and would rather say so than set environment variables.
The listener binds 127.0.0.1 and there is deliberately no option to widen it. The page is the whole graph with no authentication in front of it, so a listener on any other interface would be an unauthenticated read of everything it contains. An embedder that needs to expose it further should put its own authenticated proxy in front rather than ask for a wider bind.
Typical use:
src, err := liveview.OpenSource(ctx)
if err != nil {
return err
}
sv, err := liveview.Start(ctx, src, liveview.DefaultPort, liveview.DefaultInterval, false)
if err != nil {
return err
}
defer sv.Close()
fmt.Println(sv.URL())
Index ¶
- Constants
- func ClipLabel(s string) string
- func LoadLocal(ctx context.Context, sqlDB *sql.DB) ([]Node, []Edge, error)
- func LoadRemote(ctx context.Context, addr, token string, limit int, quiet bool) ([]Node, []Edge, error)
- func OpenInBrowser(url string) error
- func PortFromEnv() int
- func RemoteConfigured() (addr, token string, ok bool)
- type Delta
- type Edge
- type Event
- type Hub
- type Message
- type Node
- type Payload
- type Server
- func Current() *Server
- func CurrentFor(key string) *Server
- func Shared(ctx context.Context, activity bool) (*Server, error)
- func SharedFor(ctx context.Context, key string, activity bool, ...) (*Server, error)
- func Start(ctx context.Context, src *Source, port int, interval time.Duration, ...) (*Server, error)
- type Snapshot
- type Source
Constants ¶
const ( KindQuery = "query" KindWrite = "write" KindRelate = "relate" )
const DefaultInterval = 2 * time.Second
DefaultInterval is how often the brain is re-read for structural change. Activity does not wait for it — that arrives the moment a tool call is handled — so this only bounds how late a write from *another* machine shows up, and polling a database faster than a person can read the result is spend with nothing bought.
const DefaultPort = 37423
DefaultPort is the preferred port, chosen high and unusual so it does not collide with whatever else is being developed on this machine. When it is taken the server asks the OS for a free one instead of failing: a view is not worth an error, and the caller is told the URL either way.
Variables ¶
This section is empty.
Functions ¶
func ClipLabel ¶
ClipLabel shortens a node label for display, matching the local renderer.
Whitespace is collapsed before clipping. A node's label is often the first line of whatever text it came from, and that text has newlines in it — which survive into every view that prints the label as a string, breaking the layout of whatever panel is showing it.
func LoadLocal ¶
LoadLocal reads meaningful nodes/edges from the live GraphRAG graph (everything except chunk nodes, and the edges between them). For large graphs it keeps the most-connected core: nodes are ranked by degree and capped, so the view shows the densely-linked hub instead of an arbitrary truncation with dangling edges.
func LoadRemote ¶
func LoadRemote(ctx context.Context, addr, token string, limit int, quiet bool) ([]Node, []Edge, error)
LoadRemote pulls the whole entity graph from the shared brain.
quiet suppresses the truncation note. A one-shot render should say when it only drew part of the brain; the live view calls this every couple of seconds and would repeat the same line forever, which turns a useful notice into the only thing in the log.
func OpenInBrowser ¶
OpenInBrowser hands the URL to the desktop.
Errors are returned rather than ignored: a caller that claims to have opened something is worse than one that says it could not and gives you the URL.
func PortFromEnv ¶
func PortFromEnv() int
func RemoteConfigured ¶
RemoteConfigured reports whether this process reads a shared brain.
Types ¶
type Delta ¶
type Delta struct {
Version int64 `json:"version"`
AddedNodes []Node `json:"added_nodes"`
RemovedNodes []string `json:"removed_nodes"`
AddedEdges []Edge `json:"added_edges"`
RemovedEdges []Edge `json:"removed_edges"`
// Nodes and Edges are the totals after applying, so the page's counters
// cannot drift out of step with the brain if a delta is ever missed.
Nodes int `json:"nodes"`
Edges int `json:"edges"`
}
Delta is what changed between two snapshots.
AddedNodes carries upsert semantics rather than insert: a node whose label or type changed is re-sent here, not removed and re-added, so the view updates it in place and keeps the position the layout already settled on.
type Event ¶
type Event struct {
Seq int64 `json:"seq"`
At int64 `json:"at"` // unix milliseconds
Kind string `json:"kind"`
Tool string `json:"tool"`
// Text is the line the ticker shows.
Text string `json:"text"`
// Terms are the strings the page lights nodes up by. They are matched
// loosely against labels and ids rather than joined on node identity: a
// tool's arguments name things the way a person does ("CortexDB"), and the
// graph keys them the way a database does ("entity:CortexDB").
Terms []string `json:"terms,omitempty"`
// Links are from/to pairs to draw a pulse along, for relation writes.
Links [][2]string `json:"links,omitempty"`
Failed bool `json:"failed,omitempty"`
}
Event is one thing the brain just did.
func ClassifyToolCall ¶
ClassifyToolCall turns one MCP tool call into an event for the live view, reporting false for calls the view should ignore.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub holds the current graph and fans structure and activity out to every page watching.
Slow readers are dropped rather than waited on: a browser tab that stopped draining its stream must never be able to stall the MCP server that is feeding it, because that server is also the one answering the agent.
type Payload ¶
type Payload struct {
Version int64 `json:"version"`
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
Events []Event `json:"events"`
Source string `json:"source"`
Activity bool `json:"activity"`
Interval int64 `json:"interval_ms"`
}
Payload is the page's opening state: everything needed to draw, plus what the header reports about where it came from.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server serves one live view.
func Current ¶
func Current() *Server
Current returns the running view of the brain, or nil. Used by the middleware, which must not start a server just because a tool was called — the view exists only once someone asks to see it.
func CurrentFor ¶
CurrentFor returns the running view of one graph, or nil.
func SharedFor ¶
func SharedFor(ctx context.Context, key string, activity bool, open func(context.Context) (*Source, error)) (*Server, error)
SharedFor returns the process's view of one graph, keyed by name, starting it on first use. The empty key is the brain.
Keyed rather than single because a process can now be asked for more than one graph, and a second request for the same one means "show me", not "make me another": a view is a port and a poller, and handing out a new pair every time an agent asked twice would leave a trail of them behind.
Each view binds its own port. Only the first gets the preferred one; the rest take whatever the OS gives, which is why the URL is always returned rather than assumed.
func Start ¶
func Start(ctx context.Context, src *Source, port int, interval time.Duration, activity bool) (*Server, error)
Start reads the graph once, starts serving, and starts polling. It returns as soon as the URL is usable.
func (*Server) SourceName ¶
SourceName names the brain this view reads, for a caller that wants to say so.
func (*Server) WatchesCalls ¶
WatchesCalls reports whether tool calls reach this view. A view polling a database sees structure only; one fed by an MCP server sees the queries too, and the page says which rather than leaving a still ticker to be read as a fault.
type Snapshot ¶
type Snapshot struct {
Version int64 `json:"version"`
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
}
Snapshot is one reading of the brain's entity graph.