1
0
Fork 0
Code Issues Pull requests Projects Releases 2 Packages Wiki Activity Actions Pages
DocForge2/src/docforge/models.py

132 lines
2.8 KiB
Python
Raw Normal View History

"""Immutable generic project, node, edge, and context contracts."""
from __future__ import annotations
from dataclasses import asdict, dataclass
from pathlib import Path
@dataclass(frozen=True)
class Limits:
max_source_bytes: int = 1_000_000
max_nodes: int = 10_000
max_query_chars: int = 500
max_results: int = 100
max_traversal_depth: int = 8
max_context_tokens: int = 32_000
max_tool_output_chars: int = 200_000
2026-07-22 02:58:51 -04:00
max_changesets: int = 1_000
max_changeset_operations: int = 100
max_changeset_bytes: int = 1_000_000
max_render_views: int = 100
max_template_bytes: int = 1_000_000
max_render_bytes: int = 1_000_000
2026-07-22 02:58:51 -04:00
@dataclass(frozen=True)
class ProposalWriter:
writer_id: str
families: tuple[str, ...]
operations: tuple[str, ...]
@dataclass(frozen=True)
class RenderView:
view_id: str
renderer: str
template_path: Path
output_path: Path
title: str
families: tuple[str, ...]
@dataclass(frozen=True)
class RenderConfig:
template_root: Path
preview_root: Path
views: tuple[RenderView, ...]
@dataclass(frozen=True)
class ContextProfile:
profile_id: str
families: tuple[str, ...]
statuses: tuple[str, ...]
required_nodes: tuple[str, ...]
token_budget: int
dependency_depth: int
@dataclass(frozen=True)
class ProjectDescriptor:
schema_version: int
project_id: str
title: str
adapter: str
root: Path
descriptor_path: Path
descriptor_hash: str
content_roots: tuple[Path, ...]
authority_files: tuple[Path, ...]
cache_root: Path
index_path: Path
2026-07-22 02:58:51 -04:00
changeset_root: Path
proposal_writers: tuple[ProposalWriter, ...]
render: RenderConfig | None
allowed_relations: tuple[str, ...]
profiles: tuple[ContextProfile, ...]
limits: Limits
@dataclass(frozen=True)
class Node:
node_id: str
title: str
family: str
authority: str
status: str
tags: tuple[str, ...]
summary: str
content: str
source_path: str
source_anchor: str | None
content_hash: str
def as_dict(self, *, include_content: bool = True) -> dict[str, object]:
result = asdict(self)
if not include_content:
result.pop("content")
return result
@dataclass(frozen=True)
class Edge:
source_id: str
relation: str
target_id: str
def as_dict(self) -> dict[str, str]:
return asdict(self)
@dataclass(frozen=True)
class ProjectSnapshot:
descriptor: ProjectDescriptor
nodes: tuple[Node, ...]
edges: tuple[Edge, ...]
source_hash: str
revision: str
@dataclass(frozen=True)
class ContextEntry:
node_id: str
reason: str
estimated_tokens: int
source_path: str
content_hash: str
text: str
def as_dict(self) -> dict[str, object]:
return asdict(self)