Help us shape the future of Go! Take the 2026 Go Developer Survey

importdocs

package
v0.10.18 Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2026 License: MIT Imports: 59 Imported by: 0

Documentation

Overview

Package importdocs copies a folder of markdown docs, or one web page, into a vault as notes, and keeps the copies in step on every re-run.

The doc is the source of truth; its note is a projection. Each note carries the doc as `paths:` (so reading the doc brings the note) and as `source:` plus `source_hash:` (so a re-run knows what changed). Copying rather than mounting keeps every write inside the vault's confinement — see docs/specs in the research repo, plan item 6.

Index

Constants

View Source
const ImportedDir = vault.ImportFolder

ImportedDir is the vault folder imported notes live under. The string lives on vault so propose can reuse it without importing this package (Principle 7).

View Source
const MinWatchInterval = 100 * time.Millisecond

MinWatchInterval is the shortest pause WatchLoop takes between polls; a shorter Interval is raised to it.

View Source
const NoteType = vault.ImportNoteType

NoteType is the type an imported note is filed as.

Variables

View Source
var ErrNoMarkdown = errors.New("no markdown files or readable PDF, Office, HTML, CSV, EPUB, archived or image documents")

ErrNoMarkdown reports a source folder with nothing to import.

View Source
var UserAgentVersion = "dev"

UserAgentVersion is the version in the User-Agent. The command sets it from the binary's version string. Empty means "dev".

Functions

func Fingerprint added in v0.10.3

func Fingerprint(src Source, vaultRoot string) (string, error)

Fingerprint is a digest of every file the import of src would read: its path, size and modification time. It changes when one of those files is added, edited or removed, and only then: the walk is the import's own (walkImportable), so hidden, dependency and gitignored files never count. Nothing is read but the files' metadata.

func WatchLoop added in v0.10.3

func WatchLoop(ctx context.Context, c WatchConfig)

WatchLoop keeps a vault in step with its source until ctx is done. A change is acted on once the fingerprint has held still for one interval: an editor's write-then-rename, or a checkout of many files, is one re-sync, not one per file.

Types

type Action

type Action string

Action is what an import did, or would do, with one doc or note.

const (
	Added     Action = "added"
	Updated   Action = "updated"
	Unchanged Action = "unchanged"
	// Orphaned is a note whose doc is gone. It stays until --prune.
	Orphaned Action = "orphaned"
	Pruned   Action = "pruned"
	// Conflict is a note edited by hand whose doc also changed. It is kept;
	// --force overwrites it.
	Conflict Action = "conflict"
	// Skipped is a doc or note the import will not touch: a symlink, a file
	// it did not write, or an id another doc already took.
	Skipped Action = "skipped"
)

The actions an import reports.

type CrawlOptions added in v0.10.3

type CrawlOptions struct {
	// MaxPages caps the page requests. Discovery reads (robots.txt,
	// llms.txt, sitemaps) are not pages.
	MaxPages int
	// Depth caps link hops from the start: 0 is the start page alone.
	// Pages listed in llms.txt or a sitemap are one hop away.
	Depth int
	// Include and Exclude are `paths:` globs on the URL path. A link must
	// match an Include (when there are any) and no Exclude. The start page
	// is always fetched.
	Include, Exclude []string
	// RespectRobots obeys robots.txt: its Disallow rules and a Crawl-delay
	// above Delay. Off by default; robots.txt is still read for sitemaps.
	RespectRobots bool
	// Delay is the pause between requests.
	Delay time.Duration
}

CrawlOptions bound a crawl. See Crawl.

type Entry

type Entry struct {
	Action Action `json:"action"`
	// Note is the note's vault-relative path. A Skipped entry names what was
	// skipped instead: a source path, or, for what git ignores, a count such
	// as "32 path(s)" (one entry for the lot, with the first paths in Reason).
	Note string `json:"note"`
	// Source is the doc as `<repo>:<path>`, empty for a skipped note.
	Source string `json:"source,omitempty"`
	Reason string `json:"reason,omitempty"`
}

Entry is one line of the report.

type Fetcher added in v0.10.2

type Fetcher func(ctx context.Context, rawURL string) (Page, error)

Fetcher retrieves one page. ImportURL takes one so a test can answer without the network; the command passes HTTPFetcher.

func HTTPFetcher added in v0.10.2

func HTTPFetcher(startURL string) Fetcher

HTTPFetcher fetches pages with net/http for a run that starts at startURL. No cookies are stored. Redirects stop at five and must stay on http or https. A body over 5 MiB, a non-2xx status, or a media type that is not text is an error and nothing is written. Only public addresses are reached, unless startURL itself names a private one (see guard.go).

func PublicFetcher added in v0.10.3

func PublicFetcher() Fetcher

PublicFetcher is HTTPFetcher that reaches only public addresses, even when the URL names a private one: for a caller that did not choose the URL itself, such as an MCP client a page it read can prompt.

type Options

type Options struct {
	DryRun bool
	Prune  bool
	Force  bool
	// Excludes is the vault's exclude list: a note it would hide from the
	// index is not written.
	Excludes []string
	// Vision describes images with a model, opt-in. Empty, no image leaves
	// the machine.
	Vision Vision
}

Options change what an import writes.

type Page added in v0.10.2

type Page struct {
	FinalURL    string
	ContentType string
	Body        []byte
}

Page is one fetched page. Body is UTF-8. FinalURL is where redirects landed; the note's address is the URL the operator named, not this one.

type Result

type Result struct {
	Entries []Entry `json:"entries"`
	DryRun  bool    `json:"dry_run"`
}

Result is the whole report.

func Crawl added in v0.10.3

func Crawl(ctx context.Context, startURL, vaultRoot string, opts Options, co CrawlOptions, fetch Fetcher) (*Result, error)

Crawl imports startURL and the pages it leads to as notes, one per page, each the note a single-page import of that URL would write. Pages come from llms.txt, the sitemaps, then links, breadth first, within the start URL's host and folder. A page that fails is skipped and the crawl goes on; the start page failing is an error and nothing is written.

func Import

func Import(src Source, vaultRoot string, opts Options) (*Result, error)

Import brings the docs under src into vaultRoot and reports what it did.

func ImportFile added in v0.10.2

func ImportFile(src Source, rel, vaultRoot string, opts Options) (*Result, error)

ImportFile imports one markdown, PDF or Office file, rel under src.Dir, with the repository and prefix of that folder. There is no orphan pass: this import has one doc, and the folder's other notes are not its to report or prune. A file that cannot become a note is an error here, not a skip — it is the one thing the operator asked for.

func ImportURL added in v0.10.2

func ImportURL(ctx context.Context, rawURL, vaultRoot string, opts Options, fetch Fetcher) (*Result, error)

ImportURL imports the page at rawURL as one note. fetch retrieves it; HTTPFetcher is what the command passes, and a test passes its own. The note is planned and written by the same syncer as a folder import, so hash re-sync, conflicts, excludes, and unowned files behave the same. Orphans are not considered: this import has one page, and notes from other pages are not its to remove.

func (*Result) Changed

func (r *Result) Changed() []string

Changed returns the vault-relative paths written or removed, which the caller re-indexes.

func (*Result) Count

func (r *Result) Count(a Action) int

Count returns how many entries took action a.

type Source

type Source struct {
	Dir string
	// Repo is the repository name `paths:` entries use.
	Repo string
	// Prefix is Dir relative to the repository root, "" at the root.
	Prefix string
	// contains filtered or unexported fields
}

Source names the docs to import. The command layer resolves Repo and Prefix from the repository around Dir, as `paths:` does.

type StatusError added in v0.10.3

type StatusError struct {
	Code   int
	Status string
}

StatusError is a response whose status is not 2xx. A crawl tells a page that is gone (404, 410) from one that failed, and reads robots.txt's status as RFC 9309 says.

func (*StatusError) Error added in v0.10.3

func (e *StatusError) Error() string

type Vision added in v0.10.3

type Vision struct {
	Endpoint string
	Model    string
	APIKey   string
}

Vision is the opt-in model that describes images: an OpenAI-compatible endpoint (Ollama's is http://localhost:11434/v1, LM Studio and OpenAI work too), the model, and the key when the endpoint needs one. With no endpoint, no image leaves the machine.

type WatchConfig added in v0.10.3

type WatchConfig struct {
	Interval    time.Duration
	Fingerprint func() (string, error)
	Run         func() error
	Wait        func(ctx context.Context, d time.Duration) error
	OnError     func(error)
}

WatchConfig drives WatchLoop. Fingerprint, when set, is polled every Interval and Run called once a change has settled; without it Run is called every Interval (a URL, which has no cheap fingerprint). Wait pauses for an interval, or until the context is done; OnError hears every failure, which never ends the loop. A test injects Wait to take no time.

Jump to

Keyboard shortcuts

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