Files
Open_Ultra_SAST/src/openultrasast/index.py
T

75 lines
2.5 KiB
Python
Raw Normal View History

"""Text chunking for the skill router (`skills.py`).
The vector index that once lived beside the chunker (`VectorIndex`, `build_vector_index`, `query_vector_index`,
`build_retrieval_package`) and the `ousast index` subcommand that fed it were removed on 2026-10-02: nothing ever
read the `chunks.json` they wrote. The decision engine's embeddings live in `learn/embeddings.py`.
"""
2026-06-17 21:13:51 +02:00
from __future__ import annotations
import hashlib
from dataclasses import dataclass
2026-06-17 21:13:51 +02:00
VALID_NAMESPACES = {"repo_code", "docs", "static_findings", "mechanisms", "skills", "traces"}
@dataclass(frozen=True)
class CodeChunk:
chunk_id: str
namespace: str
path: str
language: str
start_line: int
end_line: int
text: str
metadata: dict[str, str | int | bool]
def chunk_text_namespace(
*,
namespace: str,
path: str,
text: str,
metadata: dict[str, str | int | bool] | None = None,
max_lines: int = 80,
) -> list[CodeChunk]:
if namespace not in VALID_NAMESPACES:
raise ValueError(f"unsupported namespace: {namespace}")
if max_lines < 1:
raise ValueError("max_lines must be at least 1")
lines = text.splitlines()
chunks: list[CodeChunk] = []
for start in range(0, len(lines), max_lines):
chunk_lines = lines[start : start + max_lines]
if not any(line.strip() for line in chunk_lines):
continue
start_line = start + 1
end_line = start + len(chunk_lines)
chunk_text = "\n".join(chunk_lines)
2026-06-18 10:06:21 +02:00
chunk_metadata: dict[str, str | int | bool] = {
"path": path,
"namespace": namespace,
"start_line": start_line,
"end_line": end_line,
}
2026-06-17 21:13:51 +02:00
if metadata:
2026-06-18 10:06:21 +02:00
chunk_metadata.update({key: value for key, value in metadata.items() if isinstance(value, str | int | bool)})
2026-06-17 21:13:51 +02:00
chunks.append(
CodeChunk(
chunk_id=_chunk_id(f"{namespace}:{path}", start_line, end_line, chunk_text),
namespace=namespace,
path=path,
language=str(chunk_metadata.get("language", "text")),
start_line=start_line,
end_line=end_line,
text=chunk_text,
metadata=chunk_metadata,
)
)
return chunks
def _chunk_id(path: str, start_line: int, end_line: int, text: str) -> str:
digest = hashlib.sha256(f"{path}:{start_line}:{end_line}:{text}".encode()).hexdigest()[:16]
return f"{path}:{start_line}-{end_line}:{digest}"