feat: P3 effective configuration, memory root, and revision-scoped records
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -16,6 +17,74 @@ from tht.ports.evidence import canonical_provenance_uri
|
||||
|
||||
_ENV_RE = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}")
|
||||
|
||||
def _canonical_fingerprint(value: str) -> str:
|
||||
return "sha256:" + hashlib.sha256(value.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def canonical_effective_config_document(cfg) -> dict:
|
||||
"""Non-secret effective DWH/preprocessing configuration (versioned, P3).
|
||||
|
||||
Mirrors backend/src/workspaces/effective-config.ts: only fields that determine whether a
|
||||
prepared DWH generation is reusable. Deliberately excludes session_storage, runtime_identity,
|
||||
evidence, memory, search, execution, and every credential value.
|
||||
"""
|
||||
dwh: dict = {"engine": "postgres"}
|
||||
dwh_cfg = getattr(cfg, "dwh", None)
|
||||
if dwh_cfg is None:
|
||||
raise ConfigError("DWH configuration is unavailable; cannot canonicalize effective config")
|
||||
transport = getattr(dwh_cfg, "type", None)
|
||||
if transport == "postgres_direct":
|
||||
conn = dwh_cfg.connection
|
||||
dwh["database"] = conn.database
|
||||
dwh["schema"] = getattr(conn, "db_schema", None) or getattr(conn, "schema", None) or conn.database
|
||||
dwh["transport"] = "postgres_direct"
|
||||
dwh["host"] = conn.host
|
||||
dwh["port"] = conn.port
|
||||
dwh["user"] = conn.user
|
||||
elif transport == "thoth_rest":
|
||||
dwh["database"] = dwh_cfg.database.database
|
||||
dwh["schema"] = dwh_cfg.database.db_schema
|
||||
dwh["transport"] = "rest_api"
|
||||
dwh["baseUrl"] = dwh_cfg.endpoint.base_url
|
||||
else:
|
||||
raise ConfigError("unsupported DWH transport in canonical effective config")
|
||||
vectors = getattr(cfg, "vectors", None)
|
||||
collection = getattr(vectors, "collection", None) if vectors is not None else None
|
||||
if not collection:
|
||||
raise ConfigError("vector configuration is unavailable; cannot canonicalize effective config")
|
||||
embeddings = getattr(cfg, "embeddings", None)
|
||||
model = getattr(embeddings, "model", None) if embeddings is not None else None
|
||||
embed_dim = getattr(embeddings, "dim", None) if embeddings is not None else None
|
||||
if not model or not embed_dim:
|
||||
raise ConfigError("embedding configuration is unavailable; cannot canonicalize effective config")
|
||||
return {
|
||||
"schemaVersion": 1,
|
||||
"dwh": dwh,
|
||||
"vector": {"collection": collection, "dimensions": 1024, "distance": "cosine"},
|
||||
"embedding": {"model": model, "dimensions": int(embed_dim)},
|
||||
"roots": {
|
||||
"artifacts": str(getattr(cfg.paths, "artifacts", Path("artifacts"))),
|
||||
"indexes": str(getattr(cfg.paths, "indexes", Path("indexes"))),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def canonical_effective_config_json(cfg) -> str:
|
||||
return json.dumps(canonical_effective_config_document(cfg), separators=(",", ":"), ensure_ascii=False)
|
||||
|
||||
|
||||
def effective_config_identity(workspace_id: str, cfg) -> str:
|
||||
digest = hashlib.sha256(canonical_effective_config_json(cfg).encode("utf-8")).hexdigest()
|
||||
return f"workspace://{workspace_id}@v1:{digest}"
|
||||
|
||||
|
||||
def effective_config_fingerprint(cfg) -> str:
|
||||
return _canonical_fingerprint(canonical_effective_config_json(cfg))
|
||||
|
||||
|
||||
def effective_config_input_fingerprint(workspace_id: str, cfg) -> str:
|
||||
return _canonical_fingerprint(effective_config_identity(workspace_id, cfg))
|
||||
|
||||
|
||||
class ConfigError(Exception):
|
||||
"""Errore di configurazione, con messaggio leggibile per l'utente."""
|
||||
@@ -252,6 +321,9 @@ class PathsConfig(BaseModel):
|
||||
artifacts: Path = Path("artifacts")
|
||||
indexes: Path = Path("indexes")
|
||||
sessions: Path = Path("sessions")
|
||||
# Explicit workspace-global memory root (P3). When absent, legacy `artifacts/memory` is used
|
||||
# only through the documented migration path.
|
||||
memory: Path | None = None
|
||||
|
||||
|
||||
class RuntimeIdentityConfig(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user