verbose live UI + tool-level SSE events + Groq default + regression tests

This commit is contained in:
2026-06-03 05:04:29 -03:00
parent 131f4d9b86
commit e124a8a7d9
69 changed files with 3030 additions and 137 deletions

57
api/tools/schema.py Normal file
View File

@@ -0,0 +1,57 @@
"""Warehouse schema retrieval.
Physical layer via SQLAlchemy's Inspector against the active dataset's
Postgres schema; semantic layer (table/column descriptions, metric catalog)
from YAML files under `api/datasets/<name>/`.
Cached on first call — the schema is stable for a process's lifetime.
Restart the api to pick up a dataset switch or YAML edits.
"""
from __future__ import annotations
from functools import lru_cache
from typing import Any
from sqlalchemy import inspect
from api.config import get_settings
from api.datasets import read_yaml
from api.tools.db import get_engine
from api.tools.types import Column, Metric, SchemaContext, Table
@lru_cache(maxsize=1)
def load_schema() -> SchemaContext:
dataset = get_settings().dataset
docs = read_yaml(dataset, "schema_docs.yaml")
metrics_yaml = read_yaml(dataset, "metrics.yaml")
# Postgres schema name comes from the dataset id; the schema_docs file
# can override it, but normally they match.
schema_name: str = docs.get("schema", dataset)
table_descs: dict[str, dict[str, Any]] = docs.get("tables", {}) or {}
insp = inspect(get_engine())
tables: dict[str, Table] = {
name: Table(
name=name,
description=(desc := table_descs.get(name, {})).get("description"),
columns=[
Column.from_inspector(c, (desc.get("columns") or {}).get(c["name"]))
for c in insp.get_columns(name, schema=schema_name)
],
)
for name in insp.get_table_names(schema=schema_name)
}
metrics: dict[str, Metric] = {
name: Metric.from_spec(name, spec)
for name, spec in (metrics_yaml.get("metrics", {}) or {}).items()
}
return SchemaContext(schema=schema_name, tables=tables, metrics=metrics)
def get_metric(name: str) -> Metric | None:
return load_schema().metrics.get(name)