diff --git a/hindsight-api-slim/hindsight_api/alembic/versions/d6e7f8a9b0c1_case_insensitive_entities_trgm_index.py b/hindsight-api-slim/hindsight_api/alembic/versions/2eee35aa3cfc_case_insensitive_entities_trgm_index.py similarity index 81% rename from hindsight-api-slim/hindsight_api/alembic/versions/d6e7f8a9b0c1_case_insensitive_entities_trgm_index.py rename to hindsight-api-slim/hindsight_api/alembic/versions/2eee35aa3cfc_case_insensitive_entities_trgm_index.py index 682a8520..8badf6be 100644 --- a/hindsight-api-slim/hindsight_api/alembic/versions/d6e7f8a9b0c1_case_insensitive_entities_trgm_index.py +++ b/hindsight-api-slim/hindsight_api/alembic/versions/2eee35aa3cfc_case_insensitive_entities_trgm_index.py @@ -4,8 +4,8 @@ The previous GIN trigram index on canonical_name was case-sensitive, causing "Alice" and "alice" to have different trigram sets. This recreates it on LOWER(canonical_name) so the % operator matches case-insensitively. -Revision ID: d6e7f8a9b0c1 -Revises: c5d6e7f8a9b0 +Revision ID: 2eee35aa3cfc +Revises: d6e7f8a9b0c1 Create Date: 2026-03-31 """ @@ -13,8 +13,8 @@ from collections.abc import Sequence from alembic import context, op -revision: str = "d6e7f8a9b0c1" -down_revision: str | Sequence[str] | None = "c5d6e7f8a9b0" +revision: str = "2eee35aa3cfc" +down_revision: str | Sequence[str] | None = "d6e7f8a9b0c1" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None @@ -27,7 +27,7 @@ def _get_schema_prefix() -> str: def upgrade() -> None: schema = _get_schema_prefix() # Drop the old case-sensitive trigram index - op.execute(f"DROP INDEX IF EXISTS entities_canonical_name_trgm_idx") + op.execute("DROP INDEX IF EXISTS entities_canonical_name_trgm_idx") # Create case-insensitive trigram index on LOWER(canonical_name) op.execute( f"CREATE INDEX IF NOT EXISTS entities_canonical_name_lower_trgm_idx " @@ -36,7 +36,7 @@ def upgrade() -> None: def downgrade() -> None: - op.execute(f"DROP INDEX IF EXISTS entities_canonical_name_lower_trgm_idx") + op.execute("DROP INDEX IF EXISTS entities_canonical_name_lower_trgm_idx") schema = _get_schema_prefix() # Restore original case-sensitive index op.execute( diff --git a/hindsight-api-slim/hindsight_api/alembic/versions/a4b5c6d7e8f9_fix_per_bank_vector_index_type.py b/hindsight-api-slim/hindsight_api/alembic/versions/a4b5c6d7e8f9_fix_per_bank_vector_index_type.py index b2f05da3..cbb6149b 100644 --- a/hindsight-api-slim/hindsight_api/alembic/versions/a4b5c6d7e8f9_fix_per_bank_vector_index_type.py +++ b/hindsight-api-slim/hindsight_api/alembic/versions/a4b5c6d7e8f9_fix_per_bank_vector_index_type.py @@ -21,7 +21,7 @@ from alembic import context, op from sqlalchemy import text revision: str = "a4b5c6d7e8f9" -down_revision: str | Sequence[str] | None = "d6e7f8a9b0c1" +down_revision: str | Sequence[str] | None = "2eee35aa3cfc" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None diff --git a/hindsight-api-slim/hindsight_api/engine/memory_engine.py b/hindsight-api-slim/hindsight_api/engine/memory_engine.py index f5e73cc2..6cbba7f8 100644 --- a/hindsight-api-slim/hindsight_api/engine/memory_engine.py +++ b/hindsight-api-slim/hindsight_api/engine/memory_engine.py @@ -4340,13 +4340,16 @@ class MemoryEngine(MemoryEngineInterface): # Get entity information — only for visible units if unit_ids: - unit_entities = await conn.fetch(f""" + unit_entities = await conn.fetch( + f""" SELECT ue.unit_id, e.canonical_name FROM {fq_table("unit_entities")} ue JOIN {fq_table("entities")} e ON ue.entity_id = e.id WHERE ue.unit_id = ANY($1::uuid[]) ORDER BY ue.unit_id - """, unit_ids) + """, + unit_ids, + ) else: unit_entities = [] diff --git a/hindsight-control-plane/src/components/constellation.tsx b/hindsight-control-plane/src/components/constellation.tsx index 81226779..d5151d10 100644 --- a/hindsight-control-plane/src/components/constellation.tsx +++ b/hindsight-control-plane/src/components/constellation.tsx @@ -71,9 +71,9 @@ function heatColor(t: number): string { // Brighter, more luminous stops — like stars in a night sky // teal glow → bright cyan → white-blue const stops = [ - [80, 200, 205], // bright teal - [100, 210, 255], // bright cyan - [140, 180, 255], // light blue-white + [80, 200, 205], // bright teal + [100, 210, 255], // bright cyan + [140, 180, 255], // light blue-white ]; const seg = v * (stops.length - 1); const i = Math.min(Math.floor(seg), stops.length - 2); @@ -678,7 +678,10 @@ export function Constellation({ const meta = node.metadata as Record | undefined; const fullText = meta?.text || node.label || node.id; const entities: string[] = meta?.entities - ? String(meta.entities).split(",").map((e: string) => e.trim()).filter(Boolean) + ? String(meta.entities) + .split(",") + .map((e: string) => e.trim()) + .filter(Boolean) : []; const nodeColor = preparedNodes[idx].heatColor; const linkCount = preparedNodes[idx].linkCount; @@ -717,9 +720,10 @@ export function Constellation({ if (date) { html += `
Date${date}
`; } else if (occurredStart) { - const timeRange = occurredEnd && occurredEnd !== occurredStart - ? `${occurredStart.slice(0, 10)} → ${occurredEnd.slice(0, 10)}` - : occurredStart.slice(0, 10); + const timeRange = + occurredEnd && occurredEnd !== occurredStart + ? `${occurredStart.slice(0, 10)} → ${occurredEnd.slice(0, 10)}` + : occurredStart.slice(0, 10); html += `
Occurred${timeRange}
`; } @@ -882,10 +886,7 @@ export function Constellation({ : { position: "relative", width: "100%", height: `${height}px` } } > - + {/* Fullscreen toggle */}