fix: complete P2 Task 2 schema machine contracts
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
# ruff: noqa: BLE001
|
||||
from pathlib import Path
|
||||
from typing import TypedDict
|
||||
|
||||
import typer
|
||||
|
||||
from tht.cli._guards import require_server_profile, require_vector_write_allowed
|
||||
from tht.cli._guards import (
|
||||
has_vector_write_rest,
|
||||
require_server_profile,
|
||||
require_vector_write_allowed,
|
||||
)
|
||||
from tht.cli.config_cmd import CONFIG_OPT
|
||||
from tht.cli.schema_cmd import _load_config_or_exit, annotations_path, physical_path
|
||||
from tht.ports.vector import VectorWriteRecord
|
||||
@@ -117,20 +122,63 @@ def init_cmd(
|
||||
)
|
||||
|
||||
|
||||
def index_schema_data(config: Path) -> dict:
|
||||
class _MachineVectorError(Exception):
|
||||
"""Expected vector CLI failure with a stable machine-readable code."""
|
||||
|
||||
def __init__(self, code: str):
|
||||
self.code = code
|
||||
super().__init__(code)
|
||||
|
||||
|
||||
class IndexCounts(TypedDict):
|
||||
added: int
|
||||
updated: int
|
||||
deleted: int
|
||||
unchanged: int
|
||||
|
||||
|
||||
class IndexSchemaResult(TypedDict):
|
||||
status: str
|
||||
code: str
|
||||
counts: IndexCounts
|
||||
|
||||
|
||||
def _vector_cfg_or_error(cfg) -> None:
|
||||
missing = []
|
||||
if cfg.embeddings is None:
|
||||
missing.append("embeddings")
|
||||
if cfg.vectors is None:
|
||||
missing.append("vectors")
|
||||
if missing:
|
||||
raise _MachineVectorError("vector_configuration_missing")
|
||||
|
||||
|
||||
def _vector_write_or_error(cfg) -> None:
|
||||
if cfg.profile == "workstation" and not has_vector_write_rest(cfg):
|
||||
raise _MachineVectorError("vector_write_not_allowed")
|
||||
|
||||
|
||||
def index_schema_data(config: Path) -> IndexSchemaResult:
|
||||
"""Synchronize schema records and return a bounded machine result."""
|
||||
from tht.cli.schema_cmd import _machine_config
|
||||
from tht.mschema.models import Annotations, PhysicalSchema
|
||||
from tht.vectorstore.records import schema_records
|
||||
|
||||
cfg = _machine_config(config)
|
||||
require_vector_write_allowed(cfg, "vector index-schema")
|
||||
require_vector_cfg(cfg)
|
||||
try:
|
||||
cfg = _machine_config(config)
|
||||
except Exception:
|
||||
# Keep this helper free of Typer rendering while preserving a stable code.
|
||||
raise _MachineVectorError("invalid_configuration") from None
|
||||
_vector_write_or_error(cfg)
|
||||
_vector_cfg_or_error(cfg)
|
||||
phys_file = physical_path(cfg)
|
||||
if not phys_file.exists():
|
||||
raise ValueError("physical schema missing")
|
||||
physical = PhysicalSchema.from_yaml(phys_file)
|
||||
annotations = Annotations.from_yaml(annotations_path(cfg))
|
||||
raise _MachineVectorError("physical_schema_missing")
|
||||
try:
|
||||
physical = PhysicalSchema.from_yaml(phys_file)
|
||||
annotations = Annotations.from_yaml(annotations_path(cfg))
|
||||
except Exception:
|
||||
raise _MachineVectorError("schema_artifacts_invalid") from None
|
||||
records = schema_records(physical, annotations)
|
||||
from tht.adapters.factory import build_vector_store
|
||||
|
||||
@@ -158,14 +206,44 @@ def index_schema_cmd(
|
||||
json_output: bool = typer.Option(False, "--json", help="Emetti JSON puro su stdout."),
|
||||
) -> None:
|
||||
"""Embedda e sincronizza i record schema (tabelle e colonne) nel semantic store."""
|
||||
import json
|
||||
|
||||
if json_output:
|
||||
try:
|
||||
payload = index_schema_data(config)
|
||||
except Exception:
|
||||
payload = {"status": "failed", "code": "schema_index_failed"}
|
||||
typer.echo(__import__("json").dumps(payload, sort_keys=True, separators=(",", ":")))
|
||||
except _MachineVectorError as error:
|
||||
typer.echo(json.dumps({"status": "failed", "code": error.code}, sort_keys=True, separators=(",", ":")))
|
||||
raise typer.Exit(code=1) from None
|
||||
typer.echo(__import__("json").dumps(payload, sort_keys=True, separators=(",", ":")))
|
||||
except Exception:
|
||||
typer.echo(json.dumps({"status": "failed", "code": "schema_index_failed"}, sort_keys=True, separators=(",", ":")))
|
||||
raise typer.Exit(code=1) from None
|
||||
typer.echo(json.dumps(payload, sort_keys=True, separators=(",", ":")))
|
||||
return
|
||||
payload = index_schema_data(config)
|
||||
try:
|
||||
payload = index_schema_data(config)
|
||||
except _MachineVectorError as error:
|
||||
_render_index_schema_error(error, config)
|
||||
except Exception:
|
||||
typer.secho("ERRORE: impossibile indicizzare lo schema.", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1) from None
|
||||
_print_stats(type("Stats", (), payload["counts"])())
|
||||
|
||||
|
||||
def _render_index_schema_error(error: _MachineVectorError, config: Path) -> None:
|
||||
"""Render expected failures without changing the old human CLI messages."""
|
||||
cfg = _load_config_or_exit(config)
|
||||
if error.code == "physical_schema_missing":
|
||||
typer.secho(
|
||||
f"ERRORE: {physical_path(cfg)} non trovato. Esegui prima `tht schema introspect`.",
|
||||
fg=typer.colors.RED,
|
||||
err=True,
|
||||
)
|
||||
elif error.code == "vector_configuration_missing":
|
||||
require_vector_cfg(cfg)
|
||||
elif error.code == "vector_write_not_allowed":
|
||||
require_vector_write_allowed(cfg, "vector index-schema")
|
||||
elif error.code == "schema_artifacts_invalid":
|
||||
typer.secho("ERRORE: schema artifacts non validi.", fg=typer.colors.RED, err=True)
|
||||
else:
|
||||
typer.secho("ERRORE: impossibile indicizzare lo schema.", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1) from None
|
||||
|
||||
Reference in New Issue
Block a user