Files
ThothII/harness/tht/evidence/sources.py
Codex 82e2c91f42
Publish documentation / publish (push) Successful in 1m27s
feat: implement memory and evidence administration with guided repairs
Add PostgreSQL-backed memory, editable evidence with source review and activation, and human-approved archive repairs across the harness, API, and UI. Include migrations, deployment support, regression coverage, and validation documentation.

Refresh permissions from validated session roles so existing administrator logins can access newly deployed archive management features.
2026-09-10 10:31:34 +02:00

87 lines
3.7 KiB
Python

"""Construction of configured Evidence source adapters."""
from __future__ import annotations
from typing import TYPE_CHECKING
from tht.evidence.adapters import FilesystemEvidenceSource, HttpManifestEvidenceSource
from tht.evidence.adapters.s3 import S3EvidenceSource
from tht.evidence.contracts import EvidenceSource
if TYPE_CHECKING:
from tht.config import EvidenceSourcesConfig
def build_sources(evidence: EvidenceSourcesConfig | None, *, acquisition: bool = False) -> list[EvidenceSource]:
"""Build configured Evidence adapters in the existing deterministic order."""
if evidence is None:
return []
if evidence.local_archive_root is not None and not acquisition:
from tht.evidence.local_archive import LocalEvidenceArchive
archive = LocalEvidenceArchive(evidence.local_archive_root)
if (archive.metadata / "state.yaml").exists():
snapshot = archive.active_snapshot()
if snapshot is None:
raise ValueError("Local Evidence has not been activated; run Evidence consolidation")
return [FilesystemEvidenceSource(snapshot, patterns=("curated/**/*.md",))]
sources: list[EvidenceSource] = []
if evidence.source_root is not None:
legacy_root = evidence.source_root / evidence.evidence_dir
legacy_patterns = (
("**/*.md",) if legacy_root.name == "curated" else ("curated/**/*.md",)
)
sources.append(FilesystemEvidenceSource(legacy_root, patterns=legacy_patterns))
for resource in evidence.sources:
match resource.type:
case "filesystem":
sources.append(
FilesystemEvidenceSource(
resource.root,
patterns=resource.patterns,
max_bytes=resource.max_bytes,
)
)
case "http":
sources.append(
HttpManifestEvidenceSource(
resource.transport_urls(),
connect_timeout=resource.connect_timeout,
read_timeout=resource.read_timeout,
max_bytes=resource.max_bytes,
max_redirects=resource.max_redirects,
allow_private_hosts=resource.allow_private_hosts,
max_cache_bytes=resource.max_cache_bytes,
)
)
case "s3":
def secret(value):
return value.get_secret_value() if value is not None else None
sources.append(
S3EvidenceSource(
bucket=resource.bucket,
prefix=resource.prefix,
endpoint_url=resource.endpoint_url,
region=resource.region,
access_key=secret(resource.access_key),
secret_key=secret(resource.secret_key),
session_token=secret(resource.session_token),
trusted_endpoint=resource.trusted_endpoint,
allow_private_endpoint=resource.allow_private_endpoint,
allow_insecure_endpoint=resource.allow_insecure_endpoint,
max_bytes=resource.max_bytes,
max_objects=resource.max_objects,
max_pages=resource.max_pages,
page_size=resource.page_size,
)
)
case other: # pragma: no cover - Pydantic rejects unsupported discriminators.
from tht.config import ConfigError
raise ConfigError(f"Adapter evidence non supportato: {other}")
return sources
__all__ = ["build_sources"]