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
- Variables
- func Fingerprint(src Source, vaultRoot string) (string, error)
- func WatchLoop(ctx context.Context, c WatchConfig)
- type Action
- type CrawlOptions
- type Entry
- type Fetcher
- type Options
- type Page
- type Result
- func Crawl(ctx context.Context, startURL, vaultRoot string, opts Options, co CrawlOptions, ...) (*Result, error)
- func Import(src Source, vaultRoot string, opts Options) (*Result, error)
- func ImportFile(src Source, rel, vaultRoot string, opts Options) (*Result, error)
- func ImportURL(ctx context.Context, rawURL, vaultRoot string, opts Options, fetch Fetcher) (*Result, error)
- type Source
- type StatusError
- type Vision
- type WatchConfig
Constants ¶
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).
const MinWatchInterval = 100 * time.Millisecond
MinWatchInterval is the shortest pause WatchLoop takes between polls; a shorter Interval is raised to it.
const NoteType = vault.ImportNoteType
NoteType is the type an imported note is filed as.
Variables ¶
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.
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
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
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
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
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 ¶
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 ImportFile ¶ added in v0.10.2
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.
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
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
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.