docs

package
v0.37.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package docs implements the `volcano docs` subsystem: fetching Volcano documentation from a configurable GitHub source into a local cache and searching it with a small, dependency-free BM25 index. It is designed primarily for AI agents that need to look up or validate facts against the official docs, with machine-readable (JSON) output as a first-class concern.

Index

Constants

View Source
const (
	EnvRepo = "VOLCANO_DOCS_REPO"
	EnvRef  = "VOLCANO_DOCS_REF"
	EnvPath = "VOLCANO_DOCS_PATH"
)

Environment overrides for the documentation source.

View Source
const ManifestSchemaVersion = 1

ManifestSchemaVersion versions the on-disk manifest format.

View Source
const Provider = "github"

Provider identifies the backing documentation host. Only GitHub is supported today; the field keeps the cache key and JSON envelope forward compatible if another provider is ever added.

View Source
const StaleAfter = 7 * 24 * time.Hour

StaleAfter is how long a cache is served before it is reported stale. Reads never refresh automatically; staleness is informational only.

Variables

View Source
var (
	// ErrCacheMissing indicates no cache snapshot exists yet (and, for reads,
	// --offline prevented a bootstrap sync).
	ErrCacheMissing = errors.New("docs cache is empty; run `volcano docs sync`")
	// ErrSourceUnavailable indicates the GitHub source could not be reached or
	// returned an error while syncing.
	ErrSourceUnavailable = errors.New("docs source unavailable")
	// ErrInvalidSource indicates a malformed repo/ref/path.
	ErrInvalidSource = errors.New("invalid docs source")
	// ErrDocNotFound indicates a requested document/section does not exist.
	ErrDocNotFound = errors.New("doc not found")
	// ErrInvalidID indicates a malformed document id/path.
	ErrInvalidID = errors.New("invalid doc id")
	// ErrSyncIncomplete indicates a sync failed partway and left the previous
	// cache untouched.
	ErrSyncIncomplete = errors.New("docs sync incomplete")
	// ErrOfflineConflict indicates a network-requiring operation (e.g. `sync`)
	// was invoked with --offline, which is an invalid flag combination rather
	// than a source failure.
	ErrOfflineConflict = errors.New("operation requires network access but --offline was set")
)

Sentinel errors carry stable machine codes for the JSON envelope. Each maps to a DOCS_* code in the command layer.

Functions

func CacheDir

func CacheDir(override string, src SourceRef) (string, error)

CacheDir returns the per-source cache directory: <base>/docs/<version>/<source-key>.

func Code

func Code(err error) string

Code returns the DOCS_* machine code for a docs error, or empty string.

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache manages snapshot directories and the current pointer for one source.

func NewCache

func NewCache(dir string) *Cache

NewCache returns a Cache rooted at the per-source directory.

func (*Cache) Exists

func (c *Cache) Exists() bool

Exists reports whether a published snapshot is available.

func (*Cache) Load

func (c *Cache) Load() (*Manifest, error)

Load reads the live manifest. Returns ErrCacheMissing when no snapshot exists.

func (*Cache) ReadFile

func (c *Cache) ReadFile(relPath string) ([]byte, error)

ReadFile returns the raw bytes of a cached document by its relative path.

type CacheState

type CacheState struct {
	Key       string     `json:"key"`
	SyncedAt  *time.Time `json:"synced_at"`
	CheckedAt *time.Time `json:"checked_at"`
	Stale     bool       `json:"stale"`
	Offline   bool       `json:"offline"`
}

CacheState reports the current cache metadata for the JSON envelope.

type FileEntry

type FileEntry struct {
	Path string `json:"path"`
	SHA  string `json:"sha"`
	Size int64  `json:"size"`
}

FileEntry records one cached document and its GitHub blob SHA so a later sync can reuse unchanged files without re-downloading them.

type GetResult

type GetResult struct {
	ID          string   `json:"id"`
	Path        string   `json:"path"`
	Topic       string   `json:"topic"`
	Title       string   `json:"title"`
	Anchor      string   `json:"anchor,omitempty"`
	HeadingPath []string `json:"heading_path,omitempty"`
	LineStart   int      `json:"line_start,omitempty"`
	LineEnd     int      `json:"line_end,omitempty"`
	Content     string   `json:"content"`
}

GetResult is the payload for `docs get`.

type HTTPDoer

type HTTPDoer interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPDoer is the minimal HTTP contract used by sync, satisfied by *http.Client and the runtime's injected client.

type Index

type Index struct {
	// contains filtered or unexported fields
}

Index is an in-memory BM25 index built per invocation. No index is persisted; the corpus is small enough to rebuild on each search.

func NewIndex

func NewIndex(sections []Section) *Index

NewIndex builds a BM25 index over the given sections.

func (*Index) Search

func (idx *Index) Search(query, topic string, limit int) []Result

Search returns up to limit ranked results, filtered to topic when non-empty.

type ListItem

type ListItem struct {
	Path  string `json:"path"`
	Topic string `json:"topic"`
	Title string `json:"title"`
}

ListItem is one document entry for `docs list`.

type Manifest

type Manifest struct {
	SchemaVersion  int         `json:"schema_version"`
	Provider       string      `json:"provider"`
	Source         SourceRef   `json:"source"`
	ResolvedCommit string      `json:"resolved_commit"`
	Files          []FileEntry `json:"files"`
	SyncedAt       time.Time   `json:"synced_at"`
	CheckedAt      time.Time   `json:"checked_at"`
}

Manifest describes a published cache snapshot.

func (*Manifest) Stale

func (m *Manifest) Stale(now time.Time) bool

Stale reports whether the snapshot is older than StaleAfter relative to now.

type Options

type Options struct {
	Overrides    Overrides
	Config       *config.Config
	HTTPClient   HTTPDoer
	CacheDir     string
	GitHubAPIURL string
	RawBaseURL   string
	Token        string
	Now          func() time.Time
	Env          func(string) (string, bool)
}

Options configures a Service. The command layer builds this from cliruntime.Deps, the loaded config, and --repo/--ref/--path flags.

type Overrides

type Overrides struct {
	Repo string
	Ref  string
	Path string
}

Overrides carries explicit per-invocation source overrides, typically from --repo/--ref/--path flags. Empty fields are treated as "not set".

type Result

type Result struct {
	ID           string   `json:"id"`
	Rank         int      `json:"rank"`
	Score        float64  `json:"score"`
	Path         string   `json:"path"`
	Topic        string   `json:"topic"`
	Title        string   `json:"title"`
	HeadingPath  []string `json:"heading_path"`
	Anchor       string   `json:"anchor"`
	LineStart    int      `json:"line_start"`
	LineEnd      int      `json:"line_end"`
	Snippet      string   `json:"snippet"`
	MatchedTerms []string `json:"matched_terms"`
}

Result is one ranked search hit, deduplicated to the section level.

type Section

type Section struct {
	DocPath     string   `json:"path"`
	Topic       string   `json:"topic"`
	Title       string   `json:"title"`
	Heading     string   `json:"heading"`
	HeadingPath []string `json:"heading_path"`
	Anchor      string   `json:"anchor"`
	Level       int      `json:"-"`
	LineStart   int      `json:"line_start"`
	LineEnd     int      `json:"line_end"`
	Body        string   `json:"-"`
}

Section is a heading-delimited slice of a document. Sections are the unit of search and retrieval: each has a stable id (docPath#anchor), a heading breadcrumb for context, and source line bounds.

func ParseDoc

func ParseDoc(docPath string, content []byte) []Section

ParseDoc splits raw markdown into sections. It is fence-aware so ATX-style "#" lines inside code blocks are never treated as headings. The document title is the first level-1 heading, falling back to a prettified file name.

func (Section) ID

func (s Section) ID() string

ID returns the stable section identifier docPath#anchor. A section with no anchor (document preamble) is identified by its bare doc path.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the entry point for docs operations, bundling a resolved source, its cache, and a syncer.

func NewService

func NewService(opts Options) (*Service, error)

NewService resolves the documentation source and prepares the cache/syncer.

func (*Service) CacheState

func (s *Service) CacheState(offline bool) CacheState

CacheState builds cache metadata; manifest may be nil when no cache exists.

func (*Service) Get

func (s *Service) Get(ctx context.Context, id string, offline bool) (*GetResult, error)

Get retrieves a document by path, or a single section when the id carries a #anchor. A bare path returns the complete raw markdown document.

func (*Service) List

func (s *Service) List(ctx context.Context, topic string, offline bool) ([]ListItem, error)

List returns the cached documents, optionally filtered by topic.

func (*Service) ResolvedCommit

func (s *Service) ResolvedCommit() string

ResolvedCommit returns the live cache's pinned commit, or "".

func (*Service) Search

func (s *Service) Search(ctx context.Context, query, topic string, limit int, offline bool) ([]Result, error)

Search bootstraps if needed then runs a BM25 query.

func (*Service) Source

func (s *Service) Source() SourceRef

Source returns the resolved documentation source.

func (*Service) Sync

func (s *Service) Sync(ctx context.Context, force bool) (*SyncResult, error)

Sync fetches/refreshes the cache from the source.

type SourceRef

type SourceRef struct {
	Repo string `json:"repository"`
	Ref  string `json:"ref"`
	Path string `json:"path"`
}

SourceRef locates a documentation corpus: a GitHub owner/name repository, a ref (branch, tag, or commit), and the subdirectory the docs live under.

func DefaultSource

func DefaultSource() SourceRef

DefaultSource returns the compiled-in default documentation source.

func ResolveSource

func ResolveSource(ov Overrides, cfg *config.Config, lookup envLookup) SourceRef

ResolveSource applies the precedence flags > env (VOLCANO_DOCS_*) > config.DocsSource > compiled defaults, field by field. A missing value at one layer falls through to the next, so a user can override only the ref while inheriting the default repo and path.

func (SourceRef) CacheKey

func (s SourceRef) CacheKey() string

CacheKey derives a stable, filesystem-safe identifier for a source so that distinct repo/ref/path combinations never share a cache namespace.

func (SourceRef) Validate

func (s SourceRef) Validate() error

Validate enforces the narrow GitHub owner/name + ref + path shape. Rejecting anything else keeps configurable sources from becoming a path-traversal or SSRF vector: we only ever talk to api.github.com / raw.githubusercontent.com for a well-formed repository.

type SyncResult

type SyncResult struct {
	ResolvedCommit string `json:"resolved_commit"`
	Added          int    `json:"added"`
	Updated        int    `json:"updated"`
	Removed        int    `json:"removed"`
	Unchanged      int    `json:"unchanged"`
	Changed        bool   `json:"changed"`
}

SyncResult summarizes a completed synchronization.

type Syncer

type Syncer struct {
	// contains filtered or unexported fields
}

Syncer fetches a documentation corpus from GitHub into a Cache.

func (*Syncer) Sync

func (s *Syncer) Sync(ctx context.Context, force bool) (*SyncResult, error)

Sync resolves the source ref to a commit, enumerates markdown docs, reuses unchanged blobs from the prior snapshot, downloads changed ones, and atomically publishes a new snapshot. A no-change sync only refreshes checked_at. Any failure leaves the previous cache untouched.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL