fix(vector): separate write transport fields

This commit is contained in:
2026-07-11 20:35:57 +02:00
parent ff4d662aba
commit fe8d70da47
6 changed files with 117 additions and 26 deletions
+66 -7
View File
@@ -3,12 +3,15 @@ from unittest.mock import MagicMock
import pytest
from tht.adapters.vector.thoth_http import ThothHttpVectorStore
from tht.evidence.model import EvidenceDoc
from tht.ports.vector import (
VectorHit,
VectorRecord,
VectorStore,
VectorWriteRecord,
VectorWriteUnavailable,
)
from tht.vectorstore.records import evidence_records
def test_http_store_reports_reader_without_writer():
@@ -67,13 +70,16 @@ def test_http_store_keeps_reader_and_writer_operations_separate():
writer.existing_hashes.assert_called_once_with("memory", ["memory"])
records = [
VectorRecord(
id="m1",
kind="memory",
ref="session:s1",
title="Choice",
content="Use the curated table",
metadata={"embedding": [0.1, 0.2], "content_hash": "abc"},
VectorWriteRecord(
record=VectorRecord(
id="m1",
kind="memory",
ref="session:s1",
title="Choice",
content="Use the curated table",
),
embedding=[0.1, 0.2],
content_hash="abc",
)
]
assert store.upsert("memory", records) == 1
@@ -81,11 +87,64 @@ def test_http_store_keeps_reader_and_writer_operations_separate():
reader.upsert_records.assert_not_called()
def test_http_upsert_serializes_a_canonical_builder_record():
record = evidence_records(
[EvidenceDoc(id="joins", title="Join guidance", body="Use the curated join")],
max_chunk_chars=1000,
)[0]
writer = MagicMock()
writer.upsert_records.return_value = 1
store = ThothHttpVectorStore(reader=MagicMock(), writer=writer)
assert store.upsert(
"evidence",
[VectorWriteRecord(record=record, embedding=[0.2, 0.3], content_hash="digest")],
) == 1
row = writer.upsert_records.call_args.args[1][0]
assert row["record_key"] == "evidence:joins:0"
assert row["metadata"]["status"] == "reviewed"
assert row["embedding"] == [0.2, 0.3]
assert row["content_hash"] == "digest"
def test_http_upsert_preserves_metadata_named_like_transport_fields():
record = VectorRecord(
id="collision",
kind="memory",
ref="session:s1",
title="Collision",
content="Semantic metadata must survive",
metadata={"embedding": "semantic embedding", "content_hash": "semantic hash"},
)
writer = MagicMock()
store = ThothHttpVectorStore(reader=MagicMock(), writer=writer)
store.upsert(
"memory",
[VectorWriteRecord(record=record, embedding=[0.4], content_hash="transport hash")],
)
row = writer.upsert_records.call_args.args[1][0]
assert row["embedding"] == [0.4]
assert row["content_hash"] == "transport hash"
assert row["metadata"]["embedding"] == "semantic embedding"
assert row["metadata"]["content_hash"] == "semantic hash"
def test_http_store_is_runtime_vector_store():
store = ThothHttpVectorStore(reader=MagicMock(), writer=None)
assert isinstance(store, VectorStore)
def test_vector_contract_is_exported_from_public_packages():
from tht.adapters.vector import ThothHttpVectorStore as PublicHttpStore
from tht.ports import VectorStore as PublicVectorStore
from tht.ports import VectorWriteRecord as PublicVectorWriteRecord
assert PublicHttpStore is ThothHttpVectorStore
assert PublicVectorStore is VectorStore
assert PublicVectorWriteRecord is VectorWriteRecord
def test_http_health_uses_reader_list_tables_and_reports_failure():
reader = MagicMock()
store = ThothHttpVectorStore(reader=reader, writer=None)