Skip to content

v0.5.4

Choose a tag to compare

@github-actions github-actions released this 26 Jan 23:02
· 245 commits to main since this release
9839015

Security

  • User data isolation enforcement — added user_id parameter to all storage methods that operate on user-owned data (GetFactsByIDs, GetTopicsByIDs, GetPeopleByIDs, GetFactsByTopicID, DeleteTopic, DeleteTopicCascade, SetTopicFactsExtracted, SetTopicConsolidationChecked, UpdateMessageTopic, GetMessagesByIDs, UpdateFactsTopic). All queries now include WHERE user_id = ? to prevent cross-user data leakage. Critical fix for GetFactsByIDs which previously accepted user-provided fact IDs from LLM tool calls without ownership validation.

Internal

  • Test helper extraction — created internal/rag/test_helpers.go with RAG-specific test utilities (TestRAGService, TestRAGServiceNoStart, TestRAGServiceWithSetup, SetupCommonRAGMocks, MockTopic, MockFact, MockPerson). Reduced test boilerplate from 15-25 lines to 3-12 lines per test, eliminated code duplication across consolidation_test.go, vector_test.go, shutdown_test.go.

Added

  • Unified ID format with explicit prefixes — all IDs now use explicit prefixes to prevent confusion between different entity types: [Fact:N] for user profile facts, [Topic:N] for conversation topics, [Person:N] for people in memory. Reranker returns prefixed IDs in JSON ("id": "Topic:42", "id": "Person:5"), prompts require prefixed format, display updated to show [Fact:123] instead of generic [ID:123]. Hybrid parsing accepts both prefixed format (preferred) and numeric fallback (with warning logs) for backward compatibility.

Changed

  • Reranker ID parsing — TopicSelection and PersonSelection now use string IDs with prefixes, added GetNumericID() methods for backward compatibility. Accepts both "Topic:42" (new) and 42 (legacy with warning).
  • Archivist JSON parsing — supports fact_id/person_id fields (prefixed strings like "Fact:1522", "Person:5") alongside legacy id (numeric) with warning logs on fallback.
  • manage_memory and manage_people tools — accept both "Fact:123"/"Person:123" format (preferred) and numeric IDs (with warning) for update/delete operations.

Fixed

  • OpenRouter retry on response read timeout — fixed retry logic that failed to catch timeout errors during io.ReadAll(resp.Body). Previously, network timeouts while reading the response body (error: context deadline exceeded (Client.Timeout or context cancellation while reading body)) were not retried, causing immediate request failure. Now all retryable errors (timeout, connection errors) trigger exponential backoff with up to 3 retry attempts.
  • OpenRouter request timeout increased — global HTTP client timeout increased from 120s to 300s (5 minutes) to accommodate large contexts (30-40K tokens) that require longer generation time. This fixes timeout errors on complex queries with rich RAG context.
  • OpenRouter context size logging — added context_chars and estimated_tokens fields to request logs for better observability. Now logs show the actual size of context being sent to LLM (e.g., context_chars=154725 estimated_tokens=38681), making it easier to diagnose performance issues and timeout errors.
  • Archivist JSON format error — added explicit JSON example to archivist prompt to prevent LLM from generating wrong format. Previously, the prompt only described the expected format textually, causing Gemini to return raw fact arrays ({"facts": [{...}]}) instead of operation structure ({"facts": {"added": [...], "updated": [...], "removed": [...]}}). Added fallback parser to handle malformed responses gracefully with warning log. This fixes parse_error: json: cannot unmarshal array into Go struct field Result.facts errors on production.
  • Archivist profile bio duplication — when updating existing people profiles, the archivist now intelligently merges new information with old bio instead of concatenating them. Added explicit prompt instructions: "You see the old bio in section — DO NOT repeat its content! Add ONLY new information that is not already in the old bio". This fixes duplicate information appearing like "NetSec инженер в Альфа-Капитал. Владелец Keenetic" repeated twice in the same bio.
  • Archivist aggressive profile compression — people bios now preserve significant details (work history, technical expertise, major life events) instead of aggressively compressing to 2-3 sentences. The prompt was changed from "Write 2-3 sentences" to "Write 4-8 sentences for complex profiles" with explicit instructions to preserve specific technologies, years of experience, relocations, and notable achievements. This fixes profiles losing critical context like "12 years at company", "moved to city", or specific project details.
  • Person merge username/telegram_id loss — when merging people records, the target now correctly inherits username and telegram_id from source if target doesn't have them. Previously these fields were lost during merge operations.
  • Archivist automatic deduplication — the archivist agent now ALWAYS checks for duplicate people records and suggests merges, even when no new people are added. Previously it only checked duplicates when adding new people, leaving existing duplicates unmerged.
  • Testbot check-people shows actual database IDs — the check-people command now displays actual database IDs in brackets (e.g., [67] John Doe), matching the format of check-topics and check-messages. Previously it showed sequential numbers, causing confusion during debugging.
  • LaTeX arrow symbols — \uparrow (↑) and \downarrow (↓) for notation like Invest ↑, Debt ↓
  • Docker image cleanup — disabled automatic deletion of container images from GHCR. The cleanup job was incorrectly removing tagged images, causing "manifest not found" errors when pulling versioned tags.

Removed

  • Legacy database code — dropped old facts table (replaced by structured_facts), removed entity column migration logic, deleted migration scripts (migrations/001_cleanup_other_facts.sql, migrations/002_drop_entity_column.sql). All installations already on fresh schema.