| """ |
| builder.py |
| Markdown / XML builder |
| """ |
|
|
| from __future__ import annotations |
|
|
| from pathlib import Path |
|
|
| from utils import ( |
| estimate_tokens, |
| short_sha256, |
| xml_safe, |
| safe_relative, |
| ) |
|
|
|
|
| def build_markdown(root: Path, contents: list[tuple[Path, str]], include_hash=True): |
|
|
| parts = [] |
|
|
| for path, text in contents: |
|
|
| rel = safe_relative(path, root) |
|
|
| parts.append(f"# {rel}\n") |
|
|
| if include_hash: |
| parts.append(f"SHA256: {short_sha256(text)}\n") |
|
|
| parts.append("```") |
| parts.append(text.rstrip()) |
| parts.append("```\n") |
|
|
| return "\n".join(parts) |
|
|
|
|
| def build_xml(root: Path, contents: list[tuple[Path, str]], include_hash=True): |
|
|
| xml = ["<project>"] |
|
|
| for path, text in contents: |
|
|
| rel = safe_relative(path, root) |
|
|
| xml.append(f'<file path="{rel}">') |
|
|
| if include_hash: |
| xml.append( |
| f"<sha256>{short_sha256(text)}</sha256>" |
| ) |
|
|
| xml.append("<content><![CDATA[") |
|
|
| xml.append(xml_safe(text)) |
|
|
| xml.append("]]></content>") |
|
|
| xml.append("</file>") |
|
|
| xml.append("</project>") |
|
|
| return "\n".join(xml) |
|
|
|
|
| def split_output(text: str, max_tokens: int): |
|
|
| if max_tokens <= 0: |
| return [text] |
|
|
| chunks = [] |
|
|
| current = [] |
|
|
| current_tokens = 0 |
|
|
| for line in text.splitlines(True): |
|
|
| t = estimate_tokens(line) |
|
|
| if current and current_tokens + t > max_tokens: |
|
|
| chunks.append("".join(current)) |
|
|
| current = [] |
|
|
| current_tokens = 0 |
|
|
| current.append(line) |
|
|
| current_tokens += t |
|
|
| if current: |
| chunks.append("".join(current)) |
|
|
| return chunks |