zettelkasten.ingest¶
zettelkasten.ingest ¶
Source ingestion: the canonical front door for getting a paper into the zettelkasten.
A single resolver, :func:ingest, accepts a Zotero key, a local file path, or a
title and returns the extracted full text, saved annotations, a stable
content_hash (sha256 of the original file's bytes), and provenance
(zotero_key / source_path). The hash gives every source a stable identity
independent of Zotero, lets create_source dedup re-ingested files, and keys a
disposable full-text cache so the reference is reproducible offline.
Full source text is never committed: it is cached under
<ANGELO_DIR>/zettel/fulltext/<content_hash>.txt (gitignored, like the kglite
embedding caches), while the committed _meta.yaml keeps the pointer
(content_hash + source_path/zotero_key) needed to re-derive it.
sources_dir ¶
Convenience inbox directory for local source files.
Override with ZK_SOURCES_DIR; defaults to sources/ at the workspace
root. Paths passed to :func:ingest may be absolute, relative to the cwd, or
a bare filename resolved against this directory.
Source code in zettelkasten/ingest.py
compute_content_hash ¶
sha256 of a file's raw bytes — the source's stable identity.
Source code in zettelkasten/ingest.py
fulltext_cache_path ¶
cache_fulltext ¶
Write extracted text to the content-addressed cache.
Best-effort: returns the path on success, None if hashing/text is missing
or the write fails (the cache is disposable, so a failure is non-fatal).
Source code in zettelkasten/ingest.py
read_cached_fulltext ¶
Return cached full text for a content hash, or None if not cached.
Source code in zettelkasten/ingest.py
page_index_path ¶
cache_page_index ¶
cache_page_index(content_hash: str, *, num_pages: int, total_chars: int, page_offsets: list[int], outline: list[dict]) -> Path | None
Write the page-offset + chapter-outline sidecar beside the full-text cache.
Disposable and content-addressed like the full-text cache itself: it lets
:func:~zettelkasten.server.get_fulltext slice by page range and lets the
coordinator snap window boundaries to chapter starts. Best-effort -- returns
None if the hash is missing or the write fails.
Source code in zettelkasten/ingest.py
read_page_index ¶
Return the cached page/outline sidecar for a content hash, or None.
Shape: {num_pages, total_chars, page_offsets, outline} where each
outline entry is {title, page, char_offset}.
Source code in zettelkasten/ingest.py
extract_text ¶
Extract text from a local file. Returns (text, num_pages, warning).
PDFs go through the shared pypdf extractor; recognised text suffixes are read
directly; anything else is read as UTF-8 best-effort. num_pages is 0 for
non-PDF inputs.
Source code in zettelkasten/ingest.py
extract_text_full ¶
Extract the WHOLE file plus a page/char index and chapter outline.
The full-extract counterpart to :func:extract_text: it never truncates, so
the disposable cache can hold a complete book. PDFs go through the shared
page-aware extractor (page_offsets + outline); text files are a single
page (offset [0], no outline); unsupported types return empty.
Returns (text, num_pages, warning, page_offsets, outline).
Source code in zettelkasten/ingest.py
ingest ¶
ingest(key: str = '', path: str = '', title: str = '', max_chars: int = DEFAULT_MAX_CHARS, cache_full: bool = False) -> dict[str, Any]
Resolve a source to full text + a stable content hash + provenance.
Exactly one of key (Zotero item key), path (local file), or title
(looked up in Zotero) should be provided. title resolves to a Zotero key
when there is a single unambiguous match; otherwise the candidate list is
returned for the caller to disambiguate.
Returns a dict with text, annotations, content_hash,
source_path, optional zotero_key, num_pages, and any
text_warning. The extracted text is also written to the disposable cache
keyed by content_hash. On failure returns {"error": ...}.
When cache_full is set the WHOLE document is extracted and cached (plus a
<hash>.pages.json page/outline sidecar), while the returned text stays
capped at max_chars for the caller's token budget. This is the precondition
for book-scale extraction: a later chapter is only addressable if the cache
holds it. The result then also carries total_chars and outline.