Skip to content

Ports

Ports are the Protocol contracts that isolate the domain and application layers from infrastructure. Every adapter under refindery.adapters.* implements one of these; the composition root wires the selected adapter behind its port. Because they are Protocols, no adapter type ever leaks into domain/ or application/.

The module inventory below is discovered from refindery/application/ports at build time, so adding a port automatically adds it to this page.

chunker

Chunking port: canonical, model-independent, sentence-aware chunking.

Chunker

Bases: Protocol

Splits page body text into canonical chunks.

Pure CPU work — services call it via an executor. One chunking is shared by every embedding model, so chunk size must respect the smallest registered model budget (enforced at model registration, not here).

chunk

chunk(*, page_id, text)

Split text into ordered chunks with char offsets and token counts.

clock

Injectable clock port; tests use a controllable fake.

Clock

Bases: Protocol

Source of the current time (always tz-aware UTC).

now

now()

Return the current UTC time.

cluster_engine

Clustering engine port (implemented in M4).

ClusterParams dataclass

ClusterParams(
    algorithm="hdbscan",
    reducer="umap",
    n_components=10,
    n_neighbors=15,
    min_dist=0.0,
    min_cluster_size=5,
    min_samples=3,
    leiden_resolution=1.0,
    random_state=42,
)

Parameters crossing the process-pool boundary (primitives only).

algorithm class-attribute instance-attribute

algorithm = 'hdbscan'

reducer class-attribute instance-attribute

reducer = 'umap'

n_components class-attribute instance-attribute

n_components = 10

n_neighbors class-attribute instance-attribute

n_neighbors = 15

min_dist class-attribute instance-attribute

min_dist = 0.0

min_cluster_size class-attribute instance-attribute

min_cluster_size = 5

min_samples class-attribute instance-attribute

min_samples = 3

leiden_resolution class-attribute instance-attribute

leiden_resolution = 1.0

random_state class-attribute instance-attribute

random_state = 42

ClusterFitResult dataclass

ClusterFitResult(
    labels, probabilities, reduce_ms, cluster_ms, projection
)

Labels (-1 = noise), soft membership, and worker-side stage timings.

labels instance-attribute

labels

probabilities instance-attribute

probabilities

reduce_ms instance-attribute

reduce_ms

cluster_ms instance-attribute

cluster_ms

projection instance-attribute

projection

ClusterEngine

Bases: Protocol

Fits cluster labels over page vectors.

fit async

fit(*, vectors, params)

Cluster the vectors; CPU-heavy work runs in a process pool.

content_extractor

Content extraction ports: fetching a URL and extracting body text.

FetchResult is a pydantic model because it wraps a raw HTTP response — an external input that must be validated (size caps, content type parsing).

MAX_FETCH_BYTES module-attribute

MAX_FETCH_BYTES = 10000000

FetchRoute

Bases: StrEnum

Explicit fetcher selection persisted with deferred fetch jobs.

AUTO class-attribute instance-attribute

AUTO = 'auto'

AUDIO class-attribute instance-attribute

AUDIO = 'audio'

FetchResult

Bases: BaseModel

Validated result of fetching a URL.

model_config class-attribute instance-attribute

model_config = ConfigDict(frozen=True)

url instance-attribute

url

final_url instance-attribute

final_url

status_code instance-attribute

status_code

content_type instance-attribute

content_type

charset instance-attribute

charset

body instance-attribute

body

Fetcher

Bases: Protocol

Fetches a URL for the fetch_and_index path.

fetch async

fetch(url)

Fetch url; raises on network errors and non-2xx statuses.

RoutedFetcher

Bases: Fetcher, Protocol

Fetcher with explicit adapter selection when URL shape is insufficient.

fetch_routed async

fetch_routed(url, *, route)

Fetch url through the requested adapter route.

ContentExtractor

Bases: Protocol

Extracts markdown body text from one family of content types.

content_types property

content_types

Lowercase content types this extractor handles (e.g. text/html).

extract async

extract(*, raw, charset)

Extract body text (and title when derivable) from raw bytes.

embedder

Embedding port; one instance per registered embedding model.

Embedder

Bases: Protocol

Embeds documents and queries into a single model's vector space.

dim and max_input_tokens come from the model registry / settings (not every provider SDK exposes them); adapters must assert returned vector length equals dim on first use.

model_id property

model_id

Registry id of the model this embedder serves.

dim property

dim

Dimensionality of produced vectors.

max_input_tokens property

max_input_tokens

Maximum tokens the model accepts per input.

embed_documents async

embed_documents(texts)

Embed document chunks (storage side).

embed_query async

embed_query(text)

Embed a query (query side; providers may use asymmetric prompts).

entity_extractor

Entity extraction port (implemented in M4).

EntityExtractor

Bases: Protocol

Extracts typed entity mentions from page text.

health_check

health_check()

Run a cheap canary check that this extractor produces sane output.

extract async

extract(text)

Extract mentions with character offsets.

job_queue

Durable job queue port.

Implementations pair an execution engine (huey) with the jobs ledger in the metadata store; the ledger is the source of truth for status.

JobQueue

Bases: Protocol

Enqueue and manage durable jobs.

enqueue async

enqueue(*, kind, payload, idempotency_key)

Enqueue a job; returns None when the idempotency key is a duplicate.

retry async

retry(job_id)

Re-enqueue a dead job (resets attempts).

recover async

recover()

Startup recovery: re-enqueue expired leases and orphaned pending rows.

Returns the number of jobs re-enqueued.

start async

start()

Start the embedded consumer.

stop async

stop()

Stop the embedded consumer and wait for the in-flight job.

metadata_store

Metadata store port: pages, chunks, models, jobs, blacklist.

Grows in later milestones (entities, clusters, tombstones). Implementations must keep all SQL dialect-neutral outside the adapter.

PageVectorRow dataclass

PageVectorRow(page_id, vector)

Stored pooled page vector for a single model.

page_id instance-attribute

page_id

vector instance-attribute

vector

ClusterMemberRow dataclass

ClusterMemberRow(page_id, probability)

One cluster membership row.

page_id instance-attribute

page_id

probability instance-attribute

probability

ChunkStats dataclass

ChunkStats(n_chunks, total_tokens)

Corpus-level chunk count and token total.

n_chunks instance-attribute

n_chunks

total_tokens instance-attribute

total_tokens

MetadataStore

Bases: Protocol

Transactional metadata + durable job ledger.

connect async

connect()

Open connections; idempotent.

migrate async

migrate()

Apply pending schema migrations.

close async

close()

Close connections.

insert_page async

insert_page(page)

Insert a new page row.

get_page async

get_page(page_id)

Fetch a page by id.

get_page_by_canonical_url async

get_page_by_canonical_url(canonical_url)

Fetch a page by canonical URL (revisit detection).

get_pages async

get_pages(page_ids)

Fetch multiple pages preserving input order; missing ids dropped.

record_revisit async

record_revisit(*, page_id, seen_at)

Bump last_seen_at and visit_count.

list_page_ids_by_domain async

list_page_ids_by_domain(*, domain, limit=20, status=None)

Page ids for one domain, most recently seen first; optionally by status.

set_page_status async

set_page_status(*, page_id, status, indexed_at=None)

Update page lifecycle status.

set_page_body async

set_page_body(
    *,
    page_id,
    body_text,
    content_hash,
    title,
    metadata=None,
)

Fill the body after a deferred fetch resolved it.

metadata, when given, is shallow-merged into the page's existing metadata JSON (e.g. to persist section boundaries alongside the body).

replace_chunks async

replace_chunks(*, page_id, chunks)

Replace all chunks of a page (canonical chunking).

get_chunks async

get_chunks(chunk_ids)

Hydrate chunks by id; missing ids dropped.

upsert_page_vector async

upsert_page_vector(*, page_id, model_id, vector)

Store the pooled page vector (float32 bytes) for one model.

get_page_vectors async

get_page_vectors(*, model_id)

All page vectors for one model (clustering / similarity).

clear_index_artifacts async

clear_index_artifacts(page_id)

Remove chunks and page vectors for a page after a core index failure.

register_model async

register_model(model)

Insert a model registry row.

get_model async

get_model(model_id)

Fetch one registered model.

list_models async

list_models(*, statuses=None)

List registered models, optionally filtered by status.

get_active_model async

get_active_model()

Return the single active model used by /search.

set_model_status async

set_model_status(*, model_id, status)

Update a model's lifecycle status.

activate_model async

activate_model(model_id)

Atomically make this the only active model.

create_job async

create_job(job)

Insert a ledger row; False when the idempotency key already exists.

get_job async

get_job(job_id)

Fetch one job.

list_jobs async

list_jobs(*, status=None, kind=None, limit=100)

List jobs, newest first.

latest_job_for_page async

latest_job_for_page(*, page_id, kind=None)

Newest job row for a page payload, optionally restricted by kind.

indexed_pages_missing_entity_extraction async

indexed_pages_missing_entity_extraction()

Indexed pages whose current content has no extract_entities job.

mark_job_running async

mark_job_running(*, job_id, lease_until, now)

Transition a job to running with a lease.

mark_job_done async

mark_job_done(*, job_id, now)

Transition a job to done.

mark_job_failed async

mark_job_failed(*, job_id, attempts, last_error, now)

Record a failed attempt (job stays retryable).

mark_job_dead async

mark_job_dead(*, job_id, last_error, now)

Dead-letter a job after attempts are exhausted.

reset_job_for_retry async

reset_job_for_retry(*, job_id, now)

Reset a dead job to pending with attempts=0 (manual re-enqueue).

reset_expired_leases async

reset_expired_leases(*, now)

Flip running-past-lease jobs back to pending; return them.

list_pending_jobs async

list_pending_jobs()

All pending ledger rows (startup recovery re-enqueues them).

list_expired_running_jobs async

list_expired_running_jobs(*, now)

Return running jobs whose lease expired (read-only; watchdog telemetry).

count_jobs_by_status async

count_jobs_by_status()

Job counts grouped by ledger status (absent statuses omitted).

count_tombstones_by_status async

count_tombstones_by_status()

Vector tombstone counts grouped by status (absent statuses omitted).

create_watch async

create_watch(watch)

Insert a watch row; False when (kind, url) already exists.

get_watch async

get_watch(watch_id)

Fetch one watch.

list_watches async

list_watches()

All watches, newest first.

update_watch async

update_watch(watch)

Full-row update by id; False when the watch does not exist.

delete_watch async

delete_watch(watch_id)

Delete a watch; False when it does not exist.

list_due_watches async

list_due_watches(*, now, limit)

Return enabled watches with next_run_at <= now, most overdue first.

mark_watch_run async

mark_watch_run(*, watch_id, last_run_at, next_run_at)

Advance the schedule at enqueue time (decoupled from poll outcome).

record_watch_result async

record_watch_result(
    *, watch_id, status, last_error, item_count, now
)

Record the outcome of a poll.

find_blacklist_match async

find_blacklist_match(*, canonical_url, domain)

Return the first blacklist rule matching this URL/domain, if any.

purge_and_blacklist async

purge_and_blacklist(rule)

Atomically: upsert the rule, tombstone + delete matching pages.

Idempotent on pattern (re-forgetting returns the existing rule). Returns the effective rule and the purged page ids. Metadata is authoritative immediately; vectors are deleted asynchronously.

list_blacklist async

list_blacklist()

All blacklist rules, newest first.

delete_blacklist async

delete_blacklist(blacklist_id)

Remove a rule (does not restore purged content); False if missing.

list_tombstones async

list_tombstones(*, status, limit=500)

Tombstones in one status, oldest first.

set_tombstone_status async

set_tombstone_status(
    *, page_ids, status, now, last_error=None
)

Advance tombstones.

delete_tombstones async

delete_tombstones(page_ids)

Remove tombstones (after verified retention expires).

find_entity_by_alias async

find_entity_by_alias(*, normalized, entity_type)

Exact normalized-alias match within a type.

entities_in_block async

entities_in_block(*, entity_type, key)

Candidate entities sharing (type, first-token block key).

create_entity async

create_entity(*, entity, surface_form, normalized, key)

Insert an entity with its first alias.

add_alias async

add_alias(*, entity_id, surface_form, normalized, key)

Attach an alias (idempotent on (surface_form, entity_id)).

add_mentions async

add_mentions(*, page_id, linked)

Record mentions (idempotent) and refresh affected entity counts.

get_entity async

get_entity(entity_id)

Fetch one entity.

resolve_entity async

resolve_entity(ref)

Resolve id -> canonical form -> alias (merge-stable references).

entity_aliases async

entity_aliases(entity_id)

All surface forms of an entity.

page_ids_for_entity async

page_ids_for_entity(entity_id)

Pages mentioning an entity.

entities_for_page async

entities_for_page(page_id)

Entities mentioned on a page.

entity_blocks_with_duplicates async

entity_blocks_with_duplicates()

Blocks holding more than one entity (periodic re-canonicalization).

merge_entities async

merge_entities(
    *, source_id, target_id, method, similarity, now
)

Merge source into target (snapshot logged first); returns merge id.

undo_merge async

undo_merge(merge_id, *, now)

Restore a merged entity (LIFO only); returns the restored id.

refresh_entity_idf async

refresh_entity_idf()

Recompute idf = ln(N_pages / page_count) for all entities.

upsert_cluster async

upsert_cluster(cluster)

Insert or update a cluster row.

Label/keywords are preserved on update when the new values are empty.

replace_cluster_members async

replace_cluster_members(*, cluster_id, members)

Replace a cluster's membership.

tombstone_clusters async

tombstone_clusters(cluster_ids, *, now)

Mark clusters tombstoned (rows retained, excluded from listings).

get_cluster async

get_cluster(cluster_id)

Fetch a cluster (tombstoned included — stale refs degrade gracefully).

list_clusters async

list_clusters(*, include_tombstoned=False)

Live clusters (optionally tombstoned too), largest first.

cluster_members async

cluster_members(cluster_id)

Members with soft-membership probability.

cluster_for_page async

cluster_for_page(page_id)

Return the live cluster containing this page, if any.

clusters_for_pages async

clusters_for_pages(page_ids)

Live cluster per page id; pages without one are absent.

set_cluster_label async

set_cluster_label(*, cluster_id, label)

Attach an LLM label.

insert_cluster_run async

insert_cluster_run(run)

Record a run start.

finalize_cluster_run async

finalize_cluster_run(run)

Record a run's completion stats.

list_cluster_runs async

list_cluster_runs(*, limit=100)

List cluster runs newest first.

get_cluster_run async

get_cluster_run(*, run_id)

Fetch one cluster run by id.

insert_cluster_projection async

insert_cluster_projection(*, points, centroids)

Persist a run's page and cluster projection coordinates.

get_cluster_projection async

get_cluster_projection(*, run_id)

Read page and centroid coordinates for a run.

insert_lineage async

insert_lineage(*, run_id, records)

Record lineage events for a run.

recent_run_durations_ms async

recent_run_durations_ms(limit=5)

Durations of the most recent finished runs.

last_run_finished_at async

last_run_finished_at()

When the last cluster run finished.

count_indexed_pages async

count_indexed_pages()

Pages with status=indexed.

pages_indexed_since async

pages_indexed_since(ts)

Pages indexed after ts.

last_ingest_at async

last_ingest_at()

Most recent last_seen_at across pages (idle detection).

chunk_stats async

chunk_stats()

(n_chunks, total_tokens) over the whole corpus — exact estimate.

pages_with_chunks_after async

pages_with_chunks_after(*, cursor, limit=50)

Page ids (with chunks) ordered by id, after the cursor.

chunks_for_page async

chunks_for_page(page_id)

All chunks of one page in ordinal order.

upsert_backfill async

upsert_backfill(backfill)

Insert or replace backfill state.

get_backfill async

get_backfill(model_id)

Fetch backfill state.

put_eval_replay_result async

put_eval_replay_result(result)

Persist a completed replay report or terminal error.

get_eval_replay_result async

get_eval_replay_result(job_id)

Fetch a durable replay result.

delete_model async

delete_model(model_id)

Remove a model row and its page vectors (retire).

podcast_producer

Podcast producer port: resolve a podcast episode into a transcript envelope.

Given the transcript/chapters URLs discovered from a podcast feed, the producer fetches and normalizes them into a FetchResult carrying the synthetic podcast-transcript content type, so the result rides the normal extraction rails (router -> extractor -> chunker) without special-casing indexing.

PodcastProducer

Bases: Protocol

Builds a podcast transcript FetchResult from feed-discovered URLs.

build async

build(
    *,
    episode_url,
    transcript_url,
    transcript_type,
    chapters_url,
    description,
)

Fetch and normalize the transcript + chapters into an envelope.

query_log

Query log port: the eval substrate.

Every search logs its full pre-rerank candidate set and both retrieval arms, so reranker lift and per-arm contribution can be measured offline without re-running retrieval. Logging is non-blocking by contract — implementations buffer and must never stall the query path.

LoggedHit dataclass

LoggedHit(chunk_id, page_id, score)

One scored chunk hit as logged.

chunk_id instance-attribute

chunk_id

page_id instance-attribute

page_id

score instance-attribute

score

LoggedPage dataclass

LoggedPage(page_id, score, rank)

One final ranked page as logged.

page_id instance-attribute

page_id

score instance-attribute

score

rank instance-attribute

rank

QueryLogRecord dataclass

QueryLogRecord(
    query_id,
    ts,
    kind,
    query_text,
    params,
    active_model,
    reranker_model,
    candidate_set,
    dense_hits,
    sparse_hits,
    final_pages,
    timing_ms,
    compare_id=None,
)

One /search execution (or one /compare arm).

query_id instance-attribute

query_id

ts instance-attribute

ts

kind instance-attribute

kind

query_text instance-attribute

query_text

params instance-attribute

params

active_model instance-attribute

active_model

reranker_model instance-attribute

reranker_model

candidate_set instance-attribute

candidate_set

dense_hits instance-attribute

dense_hits

sparse_hits instance-attribute

sparse_hits

final_pages instance-attribute

final_pages

timing_ms instance-attribute

timing_ms

compare_id class-attribute instance-attribute

compare_id = None

FeedbackRecord dataclass

FeedbackRecord(query_id, page_id, relevant, *, ts)

Relevance feedback joined to the log at eval time.

query_id instance-attribute

query_id

page_id instance-attribute

page_id

relevant instance-attribute

relevant

ts class-attribute instance-attribute

ts = field(compare=False, kw_only=True)

QueryLogSink

Bases: Protocol

Non-blocking, append-only query log.

log_query

log_query(record)

Buffer a query record; never blocks.

log_feedback

log_feedback(record)

Buffer a feedback record; never blocks.

query_log_reader

Read side of the query log: the offline eval substrate.

The sink (QueryLogSink) is write-only by design; eval opens the log separately and read-only, so scoring never contends with the serving path. Rows are projected down to page-level rankings — feedback labels are page-level, so pages are the unit every metric is computed over.

LoggedRun dataclass

LoggedRun(
    query_id,
    ts,
    kind,
    query_text,
    params,
    active_model,
    reranker_model,
    final_page_ids,
    final_page_ranks,
    prererank_page_ids,
)

One query_log row projected to page-level rankings.

final_page_ids is the ranking the user actually saw (post-rerank, post-rollup, exact matches pinned); final_page_ranks preserves its absolute ranks when the response was paginated. A paginated row only sees its own slice: relevant pages outside it count as absent, so metrics computed from such a row understate the full ranking. prererank_page_ids is the first-occurrence page order of the fused candidate set — under the default max rollup this is the ranking rerank-off would have produced, modulo exact-match pins and recency decay.

query_id instance-attribute

query_id

ts instance-attribute

ts

kind instance-attribute

kind

query_text instance-attribute

query_text

params instance-attribute

params

active_model instance-attribute

active_model

reranker_model instance-attribute

reranker_model

final_page_ids instance-attribute

final_page_ids

final_page_ranks instance-attribute

final_page_ranks

prererank_page_ids instance-attribute

prererank_page_ids

QueryLogReader

Bases: Protocol

Read-only access to logged runs and feedback labels.

read_runs

read_runs(*, since=None)

All logged runs, oldest first; optionally bounded below by ts.

read_labels

read_labels()

Feedback labels per query; the latest label per page wins.

reranker

Reranker port: cross-encoder scoring of chunks against a query.

Reranks chunks, never pages — page rollup happens after, preserving the chunk-level signal that makes long pages findable.

RerankCandidate dataclass

RerankCandidate(chunk_id, text)

One chunk offered to the reranker.

chunk_id instance-attribute

chunk_id

text instance-attribute

text

RerankScore dataclass

RerankScore(chunk_id, score)

Reranker relevance score for one chunk.

chunk_id instance-attribute

chunk_id

score instance-attribute

score

Reranker

Bases: Protocol

Scores candidate chunks against a query.

model_name property

model_name

Identifier of the reranking model (for the query log).

rerank async

rerank(*, query, candidates)

Score all candidates; order of the result is not significant.

surface_embedder

Surface-form embedding port for entity canonicalization.

A dedicated small static model (not the active document embedder) keeps the cosine threshold calibrated across active-model swaps and costs nothing at ingest. The active-embedder alternative exists behind config.

SurfaceFormEmbedder

Bases: Protocol

Embeds normalized entity surface forms (synchronous, cheap).

embedder_id property

embedder_id

Cache key for surface_vectors.

embed

embed(forms)

Embed normalized surface forms; L2-normalized outputs.

transcriber

Transcriber port: local speech-to-text over a downloaded audio file.

TranscriptionSegment dataclass

TranscriptionSegment(text, start_time_s, end_time_s)

One timed, non-empty span returned by a speech-to-text provider.

text instance-attribute

text

start_time_s instance-attribute

start_time_s

end_time_s instance-attribute

end_time_s

TranscriptionResult dataclass

TranscriptionResult(text, segments=())

Normalized transcript plus provider-derived timed segments.

text instance-attribute

text

segments class-attribute instance-attribute

segments = ()

timed_offsets property

timed_offsets

Return segment character offsets when they align with text.

Transcriber

Bases: Protocol

Transcribes an audio file to normalized text and timed segments.

transcribe async

transcribe(audio_path, *, language=None)

Return normalized transcription; raise on unreadable audio.

vector_store

Vector store port: dense + sparse retrieval over chunk vectors.

Write shape: a ChunkPoint carries the vectors of every model being indexed (in Qdrant, one point holds all named vectors — a per-model upsert would clobber the others). upsert_chunks fully replaces points and is used by the indexing pipeline (which always embeds for all active/backfilling models); backfill_vectors adds one model's vectors to existing points without touching the rest.

The sparse arm takes raw text; how it is represented (BM25 sparse vectors, tantivy FTS, ...) is an adapter concern. Hybrid fusion is client-side via refindery.domain.retrieval.rrf_fuse in every adapter so results are identical across stores (the conformance suite asserts this).

ChunkPoint dataclass

ChunkPoint(
    chunk_id,
    page_id,
    ordinal,
    text,
    vectors,
    domain,
    first_seen_at,
    cluster_id=None,
)

One chunk to upsert: per-model vectors plus the filterable payload.

chunk_id instance-attribute

chunk_id

page_id instance-attribute

page_id

ordinal instance-attribute

ordinal

text instance-attribute

text

vectors instance-attribute

vectors

domain instance-attribute

domain

first_seen_at instance-attribute

first_seen_at

cluster_id class-attribute instance-attribute

cluster_id = None

StoreFilter dataclass

StoreFilter(
    domain=None, after=None, before=None, page_ids=None
)

Filters pushed into the store (pre-filter where the store supports it).

domain class-attribute instance-attribute

domain = None

after class-attribute instance-attribute

after = None

before class-attribute instance-attribute

before = None

page_ids class-attribute instance-attribute

page_ids = None

HybridQuery dataclass

HybridQuery(
    model_id,
    dense_vector,
    sparse_text,
    per_arm_limit,
    fused_limit,
    rrf_k=60,
    filters=None,
)

A hybrid retrieval request over one model's space plus the shared sparse arm.

model_id instance-attribute

model_id

dense_vector instance-attribute

dense_vector

sparse_text instance-attribute

sparse_text

per_arm_limit instance-attribute

per_arm_limit

fused_limit instance-attribute

fused_limit

rrf_k class-attribute instance-attribute

rrf_k = 60

filters class-attribute instance-attribute

filters = None

ArmTiming dataclass

ArmTiming(dense_ms, sparse_ms, fuse_ms)

Per-arm latency breakdown filled by the adapter.

dense_ms instance-attribute

dense_ms

sparse_ms instance-attribute

sparse_ms

fuse_ms instance-attribute

fuse_ms

HybridHits dataclass

HybridHits(dense, sparse, fused, timing)

Hybrid query result.

Both arms are always populated (the query log records them) alongside the RRF-fused ranking.

dense instance-attribute

dense

sparse instance-attribute

sparse

fused instance-attribute

fused

timing instance-attribute

timing

VectorStore

Bases: Protocol

Upsert/query dense + sparse chunk vectors with payload filtering.

ensure_schema async

ensure_schema(models)

Create/update storage so every model has a vector space.

add_model async

add_model(model)

Add a vector space for a newly registered model.

drop_model async

drop_model(model_id)

Drop a retired model's vector space.

upsert_chunks async

upsert_chunks(points)

Idempotently upsert chunks (full point replace, all models).

backfill_vectors async

backfill_vectors(*, model_id, points)

Add one model's vectors to existing chunks without clobbering others.

delete_pages async

delete_pages(page_ids)

Delete all chunks of the given pages across every model space.

count_chunks async

count_chunks(page_id)

Count stored chunks for a page (tombstone verification).

dense_query async

dense_query(*, model_id, vector, limit, filters=None)

Run dense kNN over one model's vectors.

sparse_query async

sparse_query(*, text, limit, filters=None)

Sparse/lexical arm; shared across models.

hybrid_query async

hybrid_query(query)

Run both arms and fuse; returns arms + fused + timings.

close async

close()

Release connections/resources.

watch_source

Watch source port: enumerate the current child items of a watched URL.

Sources own their I/O (an RSS source fetches bytes and parses them; a yt-dlp-backed source drives its own extraction), so the port is a single discover call rather than a raw-bytes parser.

WatchItem

Bases: BaseModel

One discovered child URL; validates parser/backend output.

Podcast feeds additionally surface the episode's audio enclosure and any Podcasting 2.0 <podcast:transcript> / <podcast:chapters> links, which the watch fan-out threads into ingest so the transcript is chapter-chunked.

model_config class-attribute instance-attribute

model_config = ConfigDict(frozen=True)

url instance-attribute

url

title class-attribute instance-attribute

title = None

published_at class-attribute instance-attribute

published_at = None

enclosure_url class-attribute instance-attribute

enclosure_url = None

transcript_url class-attribute instance-attribute

transcript_url = None

transcript_type class-attribute instance-attribute

transcript_type = None

chapters_url class-attribute instance-attribute

chapters_url = None

description class-attribute instance-attribute

description = None

WatchSource

Bases: Protocol

Enumerates the current items of one watch kind.

discover async

discover(*, url, config)

Return current child items; raises FetchFailedError on I/O failure.