Skip to content

Conversation

@thestumonkey
Copy link
Contributor

@thestumonkey thestumonkey commented Dec 5, 2025

Relies on Robot2 being merged first as well as memory service

Summary by CodeRabbit

  • New Features

    • Speaker-based memory filtering to control memory processing by participant presence.
    • JWT token lifetime made configurable via environment variable.
  • Configuration

    • Default memory provider updated with legacy-name compatibility.
  • Documentation

    • Extensive rebranding and docs/config examples updated to reflect the new product name and related guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
backends/advanced/docker-compose-test.yml (1)

41-42: Environment variables reference commented-out service.

Lines 41-42 and 151-152 configure MYCELIA_URL and MYCELIA_DB pointing to mycelia-backend-test, but that service is now commented out and won't run by default. This creates a mismatch: the environment expects the service, but it's unavailable unless the mycelia profile is explicitly enabled.

Recommended fixes:

  1. If Mycelia is truly optional: Conditionally set these variables only when the Mycelia profile is active. Docker Compose doesn't support conditional env vars directly, but you can use .env.mycelia or a separate compose override file.

  2. If Mycelia should always run: Uncomment the Mycelia service blocks (lines 171-201 and 205-222) to restore them to active status.

Example approach (Option 1 – move to separate override file):

Create docker-compose-test.mycelia.yml:

services:
  chronicle-backend-test:
    environment:
      - MYCELIA_URL=http://mycelia-backend-test:5173
      - MYCELIA_DB=mycelia_test
  workers-test:
    environment:
      - MYCELIA_URL=http://mycelia-backend-test:5173
      - MYCELIA_DB=mycelia_test

Then run: docker-compose -f docker-compose-test.yml -f docker-compose-test.mycelia.yml up when Mycelia is needed.

Also applies to: 151-152

extras/havpe-relay/main.py (2)

333-333: Move import time to the top of the file.

Imports must be placed at the top of the file after the docstring, grouped with standard library imports. Moving this into the function body violates the import organization guidelines and makes the code less readable.

Apply this diff to move the import to the top:

  import os
  import argparse
  import asyncio
  import logging
  import pathlib
+ import time
  from typing import Optional
  import random

Then remove the import from inside the function:

  async def process_esp32_audio(
      esp32_server: ESP32TCPServer, 
      socket_client: Optional[SocketClient] = None,
      asr_client: Optional[AsyncClient] = None,
      file_sink: Optional[RollingFileSink] = None
  ):
      """Process audio chunks from ESP32 server, save to file sink and send to authenticated backend."""
      if (not socket_client) and (not asr_client):
          raise ValueError("Either socket_client or asr_client must be provided")

      try:
-         import time
          start_time = time.time()

As per coding guidelines, all imports must appear at the top of the file after the docstring.


94-98: Replace bare except with explicit exception handling.

The bare except: pass silently ignores errors when parsing the JSON response. This violates the guideline to always raise errors explicitly and use explicit error handling rather than silent failures.

Apply this diff:

            try:
                error_data = response.json()
                error_msg = error_data.get('detail', error_msg)
-           except:
-               pass
+           except Exception:
+               pass  # Fall back to default error message

This makes the caught exception explicit. Alternatively, if you want to be more specific about network errors, catch httpx.ResponseError or json.JSONDecodeError.

As per coding guidelines, always raise errors explicitly and use explicit error handling with proper exceptions rather than silent failures.

backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (2)

97-97: Remove redundant import inside function.

datetime is already imported at line 10, and the coding guidelines explicitly state: "NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring."

As per coding guidelines, all imports must be at the top of the file.

Apply this diff:

     # Update conversation in database with end reason and completion time
     from advanced_omi_backend.models.conversation import Conversation
-    from datetime import datetime
 
     conversation = await Conversation.find_one(Conversation.conversation_id == conversation_id)

602-602: Remove redundant import inside function.

asyncio is already imported at line 7, and the coding guidelines explicitly state: "NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring."

As per coding guidelines, all imports must be at the top of the file.

Apply this diff:

         # Generate all three summaries in parallel for efficiency
-        import asyncio
-
         title, short_summary, detailed_summary = await asyncio.gather(
extras/speaker-omni-experimental/README.md (1)

356-377: Branding/license text is good; double-check advanced backend path

The integration description and license line now correctly reference the Chronicle project, which matches the rest of the repo. One minor docs nit: this file lives under extras/speaker-omni-experimental/, while the backend code in this PR is under backends/advanced/src/..., so the bullet ../../backends/advanced-backend/ may not match the actual directory name. If the real path is backends/advanced/, consider updating that link to avoid confusing readers.

Also applies to: 395-397

🧹 Nitpick comments (35)
extras/havpe-relay/main.py (1)

407-409: Use logging.exception() for better error context and exception chaining.

When re-raising exceptions, preserve the original context using raise ... from e. Additionally, logging.exception() automatically logs the full stack trace, which is more valuable for debugging than manually formatting the exception message.

Apply these diffs:

For line 407-409:

      except asyncio.CancelledError:
          logger.info("🛑 ESP32 audio processor cancelled")
          raise
      except Exception as e:
-         logger.error(f"❌ Error in ESP32 audio processor: {e}")
-         raise
+         logger.exception("❌ Error in ESP32 audio processor")
+         raise from e

For line 461-462:

      except Exception as e:
-         logger.error(f"❌ Audio processor error: {e}")
+         logger.exception("❌ Audio processor error")

Based on learnings, use logging.exception() inside except blocks to preserve full stack trace context. When re-raising, chain with raise ... from e to maintain the original exception context for better debuggability.

Also applies to: 461-462

backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py (2)

85-90: Use logging.exception() and chain exceptions for better debuggability.

Throughout the error handlers, use logging.exception() inside except blocks to automatically capture full stack traces. When re-raising exceptions, preserve the original exception context with raise ... from e. This improves debuggability by maintaining exception chains and logging complete stack information.

Example refactoring for lines 85-90:

  except Exception as e:
-     logger.error(f"Failed to create chat session for user {current_user.id}: {e}")
-     raise HTTPException(
-         status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
-         detail="Failed to create chat session"
-     )
+     logger.exception(f"Failed to create chat session for user {current_user.id}")
+     raise HTTPException(
+         status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+         detail="Failed to create chat session"
+     ) from e

Apply this pattern consistently across all exception handlers (approximately 11 locations).

Based on learnings, prefer logging.exception() in except blocks to automatically log full stack traces, and chain exceptions with raise ... from e to preserve context. This pattern is documented in the chronicle codebase best practices.

Also applies to: 124-129, 154-161, 201-208, 228-235, 273-280, 321-328, 340-347, 364-369, 402-407, 424-429


410-429: Prefer public API over private attribute access in health check.

Line 416 accesses the private attribute _initialized on the chat service. Relying on private implementation details makes the code fragile if the service implementation changes. Consider using a public method or simplifying the health check to rely on the service's public interface.

  try:
      chat_service = get_chat_service()
-     # Simple health check - verify service can be initialized
-     if not chat_service._initialized:
-         await chat_service.initialize()
+     # Simple health check - verify service is available
+     await chat_service.initialize()

Avoid accessing private implementation details; rely on the service's public API for better maintainability.

backends/advanced/scripts/create_mycelia_api_key.py (1)

75-75: API key name label updated; verify no callers depend on old literal

Changing "Friend-Lite Integration" to "Chronicle Integration" is correct for the rebrand, but if any dashboards, scripts, or tests filter by the old name they may silently stop matching. Suggest a quick scan to confirm nothing still expects the previous literal.

You can run this from the repo root to look for remaining usages or assumptions:

#!/bin/bash
# Find any use of the old integration name
rg -n --fixed-strings "Friend-Lite Integration"

# Optionally, see where the new name is referenced
rg -n --fixed-strings "Chronicle Integration"
backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (1)

9-9: Split imports onto separate lines.

Multiple imports should be on separate lines per PEP 8.

Apply this diff:

-import time, os
+import os
+import time
backends/advanced/src/advanced_omi_backend/auth.py (1)

123-132: Avoid duplicated JWT lifetime and reuse a single timestamp

The Chronicle payload shape looks fine, but you’re now hard‑coding the 24‑hour lifetime separately from JWT_LIFETIME_SECONDS and calling datetime.utcnow() twice. To keep things in sync with the rest of the auth stack and reduce drift, consider:

-    # Create JWT payload matching Chronicle's standard format
-    payload = {
-        "sub": user_id,  # Subject = user ID
-        "email": user_email,
-        "iss": "chronicle",  # Issuer
-        "aud": "chronicle",  # Audience
-        "exp": datetime.utcnow() + timedelta(hours=24),  # 24 hour expiration
-        "iat": datetime.utcnow(),  # Issued at
-    }
+    # Create JWT payload matching Chronicle's standard format
+    now = datetime.utcnow()
+    payload = {
+        "sub": user_id,  # Subject = user ID
+        "email": user_email,
+        "iss": "chronicle",  # Issuer
+        "aud": "chronicle",  # Audience
+        "exp": now + timedelta(seconds=JWT_LIFETIME_SECONDS),
+        "iat": now,
+    }

Also, please double‑check that all external consumers (e.g., Mycelia, any other services using this token) are expecting iss="chronicle" and aud="chronicle" so the rebrand doesn’t break validation downstream.

backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2)

28-33: Keep docstring provider list in sync with actual MemoryProvider options

Docstring step 3 now mentions “chronicle or openmemory_mcp”, but the MemoryProvider enum also includes MYCELIA. To avoid future drift, either (a) list all providers (chronicle, openmemory_mcp, mycelia) or (b) phrase this generically (e.g., “Uses the configured memory provider”) without hardcoding names.


147-155: Defaulting to CHRONICLE is correct; avoid silently swallowing provider detection errors

The new default of conversation_model.MemoryProvider.CHRONICLE matches the rebranded enum and the config default, so the functional change looks good. However, the surrounding try/except Exception: pass completely hides any issues in get_memory_service() or the provider-name detection, which conflicts with the project guideline to avoid silent failures and makes debugging harder.

At minimum, it would be better to log the exception (with stack trace) while still defaulting to CHRONICLE, for example:

-                try:
-                    memory_service_obj = get_memory_service()
-                    provider_name = memory_service_obj.__class__.__name__
-                    if "OpenMemory" in provider_name:
-                        memory_provider = conversation_model.MemoryProvider.OPENMEMORY_MCP
-                except Exception:
-                    pass
+                try:
+                    memory_service_obj = get_memory_service()
+                    provider_name = type(memory_service_obj).__name__
+                    if "OpenMemory" in provider_name:
+                        memory_provider = conversation_model.MemoryProvider.OPENMEMORY_MCP
+                except Exception:
+                    logger.exception(
+                        "Failed to determine memory provider; defaulting to %s",
+                        memory_provider,
+                    )

This preserves the non-fatal behavior while surfacing problems in logs with full context, consistent with the project’s preference for logging.exception() in except blocks. Based on learnings, this aligns with existing memory-service error-handling patterns.

extras/asr-services/tests/test_parakeet_service.py (1)

14-17: Remove hardcoded absolute path from documentation.

The documentation contains a hardcoded absolute path specific to one developer's machine (/home/ankush/workspaces/chronicle/), which reduces portability and maintainability.

Apply this diff to use a relative path instruction:

 Run with:
   # Run the test (service management is automatic)
-  cd /home/ankush/workspaces/chronicle/extras/asr-services
+  cd extras/asr-services
   uv run pytest tests/test_parakeet_service.py -v -s
backends/advanced/Docs/auth.md (1)

5-6: Auth docs branding + Mongo DB name are correct; update remaining service names

The overview now correctly describes Chronicle’s auth system, and the Mongo shell command targeting the chronicle database aligns with the backend rename.

However, the surrounding debug commands still reference the old friend-backend service name:

  • Line 263: docker compose logs friend-backend | grep -i admin
  • Line 275: docker compose logs friend-backend | grep -i auth

If the service was renamed to chronicle-backend in docker-compose.yml, consider updating these commands for consistency, e.g.:

-docker compose logs friend-backend | grep -i admin
+docker compose logs chronicle-backend | grep -i admin

-docker compose logs friend-backend | grep -i auth
+docker compose logs chronicle-backend | grep -i auth

Also applies to: 260-279

extras/local-omi-bt/connect-omi.py (1)

52-60: Consider upstreaming list_devices helper or clarifying the TODO

The list_devices helper plus the # Add this to chronicle sdk comment make sense for now, but it’s effectively a TODO.

If you plan to move this into chronicle.bluetooth, consider either:

  • Converting the comment into a clear # TODO: Move this helper into chronicle.bluetooth, or
  • Opening an issue/PR on the SDK and removing the comment here once it’s available.

Do you want help drafting a small SDK-side implementation + tests for this helper so it can be shared?

backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py (1)

18-20: Align Opus decoder import with Chronicle SDK

This module imports OmiOpusDecoder from friend_lite.decoder while other parts of the repo (e.g., extras/local-omi-bt/connect-omi.py) import it from chronicle.decoder. Aligning to the chronicle.decoder source maintains consistency across the codebase:

-from friend_lite.decoder import OmiOpusDecoder
+from chronicle.decoder import OmiOpusDecoder
extras/havpe-relay/README.md (1)

162-164: Branding sentence looks good; consider casing consistency

“This project is part of the chronicle ecosystem.” reads fine. If you generally treat the product name as “Chronicle” elsewhere, you may want to capitalize it here for consistency; otherwise this matches the lower-case “chronicle” style used in some docs.

backends/advanced/Docs/README.md (1)

1-6: Docs header rebrand looks good; check remaining friend-backend mention

Title and intro now clearly reference Chronicle, which fits the PR’s goal. Elsewhere in this file, docker compose logs friend-backend is still referenced; if the service/container has been renamed as part of this rebrand, consider updating that command in a follow-up for consistency.

backends/advanced/Docs/architecture.md (1)

1-8: Architecture doc branding updated; consider aligning container naming

Renaming the architecture title and overview paragraph to Chronicle is consistent with the rest of the docs. The deployment diagram/container spec sections still refer to a friend-backend service—if the Compose service has also been renamed as part of this effort, it would be worth updating those labels to avoid confusion.

extras/openmemory-mcp/test_standalone.py (1)

44-45: Pre-existing: Bare except clause silently swallows all exceptions.

While outside the scope of this PR's branding changes, this bare except: at line 44 (and similarly at line 128) suppresses all exceptions without logging. Consider addressing in a follow-up to improve debuggability.

     async def test_connection(self) -> bool:
         """Test if server is reachable."""
         try:
             response = await self.client.get(f"{self.server_url}/")
             return response.status_code in [200, 404, 422]
-        except:
+        except Exception:
             return False
backends/charts/advanced-backend/Chart.yaml (1)

3-12: Consider aligning Helm chart metadata URLs with Chronicle repo

The description/keywords are updated to Chronicle, but sources/home still point to the BasedHardware/Friend repo. If this chart is now primarily maintained in chronicler-ai/chronicle, consider updating those URLs; if you intentionally want to reference the upstream Friend project, this is fine as-is.

app/app/hooks/useDeviceScanning.ts (1)

1-4: Verify chronicle-react-native Omi types import and clean up comment

The path update to chronicle-react-native is appropriate for the rebrand, assuming it exports OmiConnection and OmiDevice with the same names. Once confirmed by TypeScript/Metro, consider dropping the “Assuming this is the correct import” comment to avoid future confusion:

-import { OmiConnection, OmiDevice } from 'chronicle-react-native'; // Assuming this is the correct import for Omi types
+import { OmiConnection, OmiDevice } from 'chronicle-react-native';
backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py (1)

185-203: Prefer logger.exception in exception handlers for better diagnostics

In the DB and connection exception handlers you currently log with logger.error, which loses stack traces. For easier debugging, consider switching to logger.exception inside these handlers so the full traceback is recorded:

-        logger.error(f"Database connection error: {type(exc).__name__}: {exc}")
+        logger.exception("Database connection error")

...
-        logger.error(f"Connection error: {exc}")
+        logger.exception("Connection error")

This retains the original context while keeping responses unchanged. Based on learnings, this pattern is preferred across Chronicle’s Python code.

backends/advanced/webui/README.md (1)

57-60: Ensure Docker service names and paths are aligned with Chronicle backend/webui layout

The README still references friend-backend in Docker Compose commands and mentions a webui-react directory for manual builds, while other parts of the repo now use Chronicle/advanced-backend terminology and backends/advanced/webui. Please verify that:

  • The service name in docker-compose matches these docs (e.g., friend-backend vs advanced-backend/chronicle-backend), and
  • The manual build path (backends/advanced/webui-react vs backends/advanced/webui) matches the actual directory structure.

Adjusting these if they’ve been renamed will avoid setup confusion post-rebrand.

Also applies to: 72-75, 80-83, 90-93

backends/advanced/src/advanced_omi_backend/models/job.py (1)

48-52: Beanie DB default looks right, but fallback/flagging/logging can be cleaned up

  • Using "chronicle" as the default DB name here is consistent with the rest of the Chronicle backend.
  • In the except ConfigurationError block you assign database = client["chronicle"] and then immediately raise, so the fallback assignment is never actually used; either drop the assignment or remove the bare raise (and perhaps log a warning) depending on whether you intend to recover or fail-fast.
  • _beanie_initialized is set twice (before and after init_beanie); you can set it only once after successful initialization to avoid confusion.
  • The except Exception as e below only uses logger.error(...); switching to logger.exception("❌ Failed to initialize Beanie in RQ worker") will capture full stack traces and aligns with the memory-service logging pattern. If you want to wrap the exception, prefer raise RuntimeError("...") from e.
  • Also consider moving the import os, AsyncIOMotorClient, init_beanie, model imports, and ConfigurationError to the top of the module unless there’s a documented circular-import reason to keep them here.

Also applies to: 62-64

backends/advanced/webui/src/pages/System.tsx (1)

360-365: Chronicle provider label update is consistent; consider a fallback label

The new "Chronicle (Sophisticated)" label for provider 'chronicle' fits the rebranding and is consistent with the other provider labels. You might optionally add a fallback like {!known && provider} so any unexpected provider value still renders something instead of an empty <option>.

backends/advanced/docker-compose.yml (1)

2-56: Backend service rename to chronicle-backend is wired correctly

The docker-compose service has been cleanly renamed to chronicle-backend, and all depends_on entries (webui, caddy, webui-dev, commented ngrok) now reference the new name while preserving the existing healthcheck behavior. As a minor follow‑up, you might also consider renaming the friend-network at the bottom to something like chronicle-network for branding consistency, though this is purely cosmetic.

Also applies to: 90-107, 112-124, 129-145, 215-220

CLAUDE.md (1)

7-7: Consider hyphenating compound adjective.

Static analysis suggests "speaker-specific" instead of "speaker specific" when used as a compound adjective modifying "transcription."

This is purely stylistic and doesn't affect clarity.

backends/advanced/scripts/sync_friendlite_mycelia.py (3)

114-116: Inconsistent variable naming: fl_db should be renamed.

The variable fl_db appears to be a leftover abbreviation from "friend_lite_db". For consistency with the Chronicle rebranding, consider renaming it to chronicle_db or simply db.

-        # Update Chronicle user document
-        fl_db = self.client[self.chronicle_db]
-        fl_db["users"].update_one(
+        # Update Chronicle user document
+        chronicle_db = self.client[self.chronicle_db]
+        chronicle_db["users"].update_one(

The same issue appears at lines 234 and 364.


53-56: Remove extraneous f-string prefixes.

Lines 53, 163, and 190 contain f-strings without any placeholders. Remove the f prefix for these literal strings.

-        print(f"📊 Connected to MongoDB:")
+        print("📊 Connected to MongoDB:")

Similar changes needed at lines 163 and 190:

-        print(f"{'='*80}")
+        print("=" * 80)

154-156: Improve exception handling with logging and exception chaining.

Per project conventions, use logging.exception() in except blocks to capture the full stack trace. If re-raising, chain with raise ... from e.

+import logging
+
+logger = logging.getLogger(__name__)
+
 # In sync_user method:
         except Exception as e:
-            print(f"✗ {user_email:40} Failed: {e}")
+            logger.exception("Failed to sync user %s", user_email)
+            print(f"✗ {user_email:40} Failed: {e}")
             return False

Based on learnings, this improves debuggability by preserving the full stack trace.

backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (2)

39-42: Avoid in-function import for ChronicleMemoryService

The Chronicle provider is mandatory (unlike the optional MCP/Mycelia backends), so this lazy import is not strictly needed and violates the “no mid-function imports” guideline.

Consider moving the import to the module top level and just returning the alias here:

-from .base import MemoryServiceBase
-from .config import build_memory_config_from_env, MemoryConfig, MemoryProvider
+from .base import MemoryServiceBase
+from .config import build_memory_config_from_env, MemoryConfig, MemoryProvider
+from .providers.chronicle import MemoryService as ChronicleMemoryService
@@
-    if config.memory_provider == MemoryProvider.CHRONICLE:
-        # Use the sophisticated Chronicle implementation
-        from .providers.chronicle import MemoryService as ChronicleMemoryService
-        return ChronicleMemoryService(config)
+    if config.memory_provider == MemoryProvider.CHRONICLE:
+        # Use the sophisticated Chronicle implementation
+        return ChronicleMemoryService(config)

If there is a known circular-import issue forcing the lazy import, keeping it is acceptable but should be documented in a brief comment.


106-108: Improve error logging and exception chaining on memory service creation

The generic Exception handler currently logs only the message and discards the original traceback when raising RuntimeError, which hurts debuggability.

You can keep the message while preserving full context:

-                except Exception as e:
-                    memory_logger.error(f"❌ Failed to create memory service: {e}")
-                    raise RuntimeError(f"Memory service creation failed: {e}")
+                except Exception as e:
+                    memory_logger.exception("❌ Failed to create memory service")
+                    raise RuntimeError(f"Memory service creation failed: {e}") from e

Based on learnings, this aligns with the project preference for logging.exception plus raise ... from e.

backends/advanced/Docs/HTTPS_SETUP.md (1)

1-3: Chronicle branding looks good; verify remaining friend-backend service references

The updated title and section headings correctly refer to “Chronicle Advanced Backend”, and the new “alongside Chronicle” example is clear.

The doc still refers to the backend compose service as friend-backend in the profiles and troubleshooting sections. If the Docker service name is still friend-backend, that’s fine but a bit confusing branding-wise; if it was renamed as part of this PR, those references should be updated to match.

Also applies to: 43-47, 241-247

backends/advanced/src/advanced_omi_backend/controllers/system_controller.py (1)

23-37: Align memory provider handling with the central enum to avoid drift

The switch of the default provider to "chronicle" and the memory_provider_supports_threshold flag keyed on "chronicle" look consistent with the new enum values.

However, the provider lists are duplicated as raw strings in multiple places:

  • get_current_metrics: implicit knowledge that only "chronicle" supports thresholds.
  • get_memory_provider: available_providers = ["chronicle", "openmemory_mcp", "mycelia"]
  • set_memory_provider: valid_providers = ["chronicle", "openmemory_mcp", "mycelia"]

To avoid these drifting from the actual MemoryProvider enum, consider deriving them from a single source, e.g., a helper or the enum itself, and using that both for validation and for the API response. That keeps future provider additions/renames from requiring manual updates in multiple places.

Also applies to: 470-497

backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (1)

31-32: Branding updates are correct; move os/re imports to the top of the module

The default client_name="chronicle" and "source": "chronicle" metadata align MCPClient with the new branding and should work fine with OpenMemory.

To match the “no mid-function imports” guideline, the os and re imports can be hoisted to the top of the file without changing behavior:

-import logging
-import uuid
-from typing import List, Dict, Any, Optional
-import httpx
-
-memory_logger = logging.getLogger("memory_service")
+import logging
+import os
+import re
+import uuid
+from typing import Any, Dict, List, Optional
+
+import httpx
+
+memory_logger = logging.getLogger("memory_service")
@@
-        # Use custom CA certificate if available
-        import os
-        ca_bundle = os.getenv('REQUESTS_CA_BUNDLE')
+        # Use custom CA certificate if available
+        ca_bundle = os.getenv("REQUESTS_CA_BUNDLE")
@@
-                if "message" in result:
-                    # Parse message like "Successfully deleted 5 memories"
-                    import re
-                    match = re.search(r'(\d+)', result["message"])
+                if "message" in result:
+                    # Parse message like "Successfully deleted 5 memories"
+                    match = re.search(r"(\d+)", result["message"])
                     return int(match.group(1)) if match else len(memory_ids)

This keeps imports organized (stdlib vs third-party) and removes unnecessary per-call import overhead.

Also applies to: 64-81, 117-124, 285-295, 333-337

Docs/init-system.md (1)

1-8: Init system docs match Chronicle architecture; double-check backend service name

The initialization/ orchestration narrative now correctly reflects the Chronicle wizard + services split and the new recommended commands.

In the logs section, the backend compose service is still referenced as friend-backend:

cd backends/advanced && docker compose logs friend-backend

If the docker service is intentionally still named friend-backend, this is technically correct but slightly off-brand; if it was renamed to something Chronicle-specific in this PR, this line should be updated accordingly.

Also applies to: 136-156, 189-205, 212-217

backends/advanced/src/advanced_omi_backend/services/memory/config.py (2)

112-124: OpenMemory Chronicle client defaults are coherent; consider migration impact

The default client_name="chronicle" in create_openmemory_config and the corresponding env-based default OPENMEMORY_CLIENT_NAME"chronicle" keep the OpenMemory integration consistent with the new branding and the default MEMORY_PROVIDER="chronicle".

One thing to be aware of: if any existing OpenMemory server instances or dashboards are keyed on the old "friend_lite" client name, this will change their grouping/metrics unless the server side has been migrated as well. If you expect mixed deployments, you might want a brief transitional shim (e.g., treat "friend_lite" as an alias for "chronicle" when parsing MEMORY_PROVIDER or client names) or at least document the required env var update.

Also applies to: 148-170


202-297: Chronicle branch log messaging is accurate; consider import placement per guidelines

The updated comment and log line:

  • Clearly label this branch as the Chronicle provider path.
  • Log the provider name as "Chronicle" alongside LLM/vector store/extraction flags, which will help ops distinguish from the OpenMemory/Mycelia paths.

One stylistic point: from advanced_omi_backend.memory_config_loader import get_config_loader is still imported inside the function. Per the project’s Python guidelines, imports should live at the top of the file and lazy imports be reserved for true circular-import cases. If there’s no cycle here, consider lifting this import to module scope to align with those guidelines.

As per coding guidelines, imports should be at the top of the file unless a circular dependency forces a lazy import.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb506dd and dc5ec6f.

⛔ Files ignored due to path filters (1)
  • backends/advanced/webui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (107)
  • .env.template (5 hunks)
  • CLAUDE.md (8 hunks)
  • Docs/features.md (3 hunks)
  • Docs/getting-started.md (7 hunks)
  • Docs/init-system.md (3 hunks)
  • Docs/ports-and-access.md (1 hunks)
  • Makefile (9 hunks)
  • README-K8S.md (10 hunks)
  • README.md (1 hunks)
  • app/README.md (7 hunks)
  • app/app.json (2 hunks)
  • app/app/components/DeviceDetails.tsx (1 hunks)
  • app/app/components/DeviceListItem.tsx (1 hunks)
  • app/app/hooks/useAudioListener.ts (1 hunks)
  • app/app/hooks/useDeviceConnection.ts (1 hunks)
  • app/app/hooks/useDeviceScanning.ts (1 hunks)
  • app/app/index.tsx (2 hunks)
  • app/package.json (2 hunks)
  • backends/README.md (1 hunks)
  • backends/advanced/Docs/HTTPS_SETUP.md (3 hunks)
  • backends/advanced/Docs/README.md (1 hunks)
  • backends/advanced/Docs/UI.md (1 hunks)
  • backends/advanced/Docs/architecture.md (2 hunks)
  • backends/advanced/Docs/auth.md (2 hunks)
  • backends/advanced/Docs/memories.md (4 hunks)
  • backends/advanced/Docs/quickstart.md (7 hunks)
  • backends/advanced/docker-compose-test.yml (7 hunks)
  • backends/advanced/docker-compose.yml (6 hunks)
  • backends/advanced/init-https.sh (3 hunks)
  • backends/advanced/init.py (7 hunks)
  • backends/advanced/scripts/create_mycelia_api_key.py (2 hunks)
  • backends/advanced/scripts/sync_friendlite_mycelia.py (12 hunks)
  • backends/advanced/setup-https.sh (2 hunks)
  • backends/advanced/src/advanced_omi_backend/app_config.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/app_factory.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/auth.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/chat_service.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/config.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/database.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/conversation.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/models/job.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py (6 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (8 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (10 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2 hunks)
  • backends/advanced/ssl/generate-ssl.sh (1 hunks)
  • backends/advanced/start-k8s.sh (1 hunks)
  • backends/advanced/start-workers.sh (1 hunks)
  • backends/advanced/start.sh (1 hunks)
  • backends/advanced/tests/test_conversation_models.py (6 hunks)
  • backends/advanced/tests/test_integration.py (2 hunks)
  • backends/advanced/upload_files.py (3 hunks)
  • backends/advanced/webui/README.md (1 hunks)
  • backends/advanced/webui/package.json (2 hunks)
  • backends/advanced/webui/src/components/layout/Layout.tsx (2 hunks)
  • backends/advanced/webui/src/pages/LoginPage.tsx (1 hunks)
  • backends/advanced/webui/src/pages/Memories.tsx (2 hunks)
  • backends/advanced/webui/src/pages/MemoriesRouter.tsx (2 hunks)
  • backends/advanced/webui/src/pages/System.tsx (1 hunks)
  • backends/advanced/webui/tsconfig.json (1 hunks)
  • backends/charts/advanced-backend/Chart.yaml (1 hunks)
  • backends/charts/advanced-backend/templates/deployment.yaml (2 hunks)
  • backends/charts/advanced-backend/templates/workers-deployment.yaml (1 hunks)
  • backends/charts/advanced-backend/values.yaml (1 hunks)
  • backends/charts/webui/Chart.yaml (1 hunks)
  • backends/charts/webui/templates/deployment.yaml (1 hunks)
  • backends/charts/webui/values.yaml (1 hunks)
  • extras/asr-services/README.md (2 hunks)
  • extras/asr-services/quickstart.md (2 hunks)
  • extras/asr-services/tests/test_parakeet_service.py (1 hunks)
  • extras/havpe-relay/README.md (1 hunks)
  • extras/havpe-relay/main.py (1 hunks)
  • extras/local-omi-bt/connect-omi.py (2 hunks)
  • extras/openmemory-mcp/README.md (9 hunks)
  • extras/openmemory-mcp/run.sh (2 hunks)
  • extras/openmemory-mcp/test_standalone.py (1 hunks)
  • extras/speaker-omni-experimental/README.md (3 hunks)
  • extras/speaker-recognition/charts/templates/speaker-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/templates/webui-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/values.yaml (1 hunks)
  • extras/speaker-recognition/init.py (1 hunks)
  • extras/speaker-recognition/quickstart.md (1 hunks)
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py (1 hunks)
  • extras/speaker-recognition/ssl/generate-ssl.sh (1 hunks)
⛔ Files not processed due to max files limit (25)
  • extras/speaker-recognition/tests/test_speaker_service_integration.py
  • k8s-manifests/cross-namespace-rbac.yaml
  • quickstart.md
  • run-test.sh
  • scripts/generate-k8s-configs.py
  • scripts/k8s/cluster-status.sh
  • scripts/k8s/load-env.sh
  • scripts/manage-audio-files.sh
  • services.py
  • skaffold.yaml
  • status.py
  • tests/.env.test
  • tests/Makefile
  • tests/README.md
  • tests/TESTING_USER_GUIDE.md
  • tests/browser/browser_auth.robot
  • tests/infrastructure/infra_tests.robot
  • tests/libs/audio_stream_library.py
  • tests/resources/transcript_verification.robot
  • tests/resources/websocket_keywords.robot
  • tests/setup/setup_keywords.robot
  • tests/setup/test_env.py
  • tests/setup/test_manager_keywords.robot
  • tests/tags.md
  • wizard.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use uv run python command instead of direct python or python3 for executing Python scripts
Use Black formatter with 100-character line length for Python code style
Use isort for Python import organization
NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring
Group imports in order: standard library, third-party, local imports
Use lazy imports sparingly and only when absolutely necessary for circular import issues in Python
Always raise errors explicitly in Python code, never silently ignore errors or failures
Use explicit error handling with proper exceptions in Python rather than silent failures
Understand data structures and research input/response or class structure instead of adding defensive hasattr() checks in Python

Files:

  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • extras/havpe-relay/main.py
  • extras/speaker-recognition/init.py
  • extras/openmemory-mcp/test_standalone.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • backends/advanced/src/advanced_omi_backend/models/job.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/tests/test_integration.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/auth.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/init.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/upload_files.py
app/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use standard React Native conventions for TypeScript/JavaScript code style

Files:

  • app/app/hooks/useAudioListener.ts
  • app/app/index.tsx
  • app/app/hooks/useDeviceConnection.ts
  • app/app/components/DeviceDetails.tsx
  • app/app/components/DeviceListItem.tsx
  • app/app/hooks/useDeviceScanning.ts
🧠 Learnings (2)
📚 Learning: 2025-12-07T18:52:48.868Z
Learnt from: CR
Repo: chronicler-ai/chronicle PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T18:52:48.868Z
Learning: Check backends/advanced/Docs for up-to-date information on advanced backend development

Applied to files:

  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/Docs/README.md
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/Docs/HTTPS_SETUP.md
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
📚 Learning: 2025-12-08T23:52:34.959Z
Learnt from: AnkushMalaker
Repo: chronicler-ai/chronicle PR: 178
File: backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py:218-223
Timestamp: 2025-12-08T23:52:34.959Z
Learning: In Python code (chronicle project), prefer logging.exception() inside except blocks to automatically log the full stack trace. When re-raising exceptions, always chain with 'raise ... from e' to preserve the original context; use 'raise ... from None' only if you explicitly want to suppress the context. This improves debuggability across Python files.

Applied to files:

  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • extras/havpe-relay/main.py
  • extras/speaker-recognition/init.py
  • extras/openmemory-mcp/test_standalone.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • backends/advanced/src/advanced_omi_backend/models/job.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/tests/test_integration.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/auth.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/init.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/upload_files.py
🧬 Code graph analysis (8)
backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-33)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)
backends/advanced/setup-https.sh (1)
backends/advanced/init.py (1)
  • print_header (36-45)
backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/tests/test_conversation_models.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • add_memory_version (260-288)
backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (3)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-33)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)
backends/advanced/src/advanced_omi_backend/services/memory/providers/chronicle.py (1)
  • MemoryService (23-705)
backends/advanced/init.py (1)
extras/speaker-recognition/init.py (3)
  • prompt_choice (89-104)
  • prompt_value (48-54)
  • print_header (31-40)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-33)
🪛 dotenv-linter (4.0.0)
.env.template

[warning] 14-14: [UnorderedKey] The APPLICATION_NAMESPACE key should go before the INFRASTRUCTURE_NAMESPACE key

(UnorderedKey)


[warning] 108-108: [UnorderedKey] The MONGODB_K8S_URI key should go before the MONGODB_URI key

(UnorderedKey)


[warning] 128-128: [UnorderedKey] The OPENMEMORY_CLIENT_NAME key should go before the OPENMEMORY_MCP_URL key

(UnorderedKey)

🪛 LanguageTool
CLAUDE.md

[grammar] ~7-~7: Use a hyphen to join words.
Context: ...at the very least audio capture, speaker specific transcription, memory extractio...

(QB_NEW_EN_HYPHEN)

Docs/getting-started.md

[style] ~9-~9: For conciseness, consider replacing this expression with an adverb.
Context: ...ort "AI wearable" agents/functionality. At the moment, the basic functionalities are: - Audio...

(AT_THE_MOMENT)

backends/advanced/Docs/quickstart.md

[style] ~7-~7: For conciseness, consider replacing this expression with an adverb.
Context: ...ort "AI wearable" agents/functionality. At the moment, the basic functionalities are: - Audio...

(AT_THE_MOMENT)

🪛 Ruff (0.14.8)
backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py

260-260: Do not catch blind exception: Exception

(BLE001)


262-262: Use explicit conversion flag

Replace with conversion flag

(RUF010)

backends/advanced/scripts/sync_friendlite_mycelia.py

53-53: f-string without any placeholders

Remove extraneous f prefix

(F541)


163-163: f-string without any placeholders

Remove extraneous f prefix

(F541)


190-190: f-string without any placeholders

Remove extraneous f prefix

(F541)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (3)

55-65: Align type hints with actual return values (API key may be None).

_create_mycelia_api_key can return (client_id, None) when an existing key is reused, but the annotations declare Tuple[str, str]. That also flows through sync_user_to_mycelia and sync_admin_user.

A minimal fix:

-from typing import Optional, Tuple
+from typing import Optional, Tuple
...
-    def _create_mycelia_api_key(self, user_id: str, user_email: str) -> Tuple[str, str]:
+    def _create_mycelia_api_key(self, user_id: str, user_email: str) -> Tuple[str, Optional[str]]:
...
-    def sync_user_to_mycelia(self, user_id: str, user_email: str) -> Optional[Tuple[str, str]]:
+    def sync_user_to_mycelia(
+        self, user_id: str, user_email: str
+    ) -> Optional[Tuple[str, Optional[str]]]:
...
-    def sync_admin_user(self) -> Optional[Tuple[str, str]]:
+    def sync_admin_user(self) -> Optional[Tuple[str, Optional[str]]]:

Also applies to: 91-96, 123-124, 167-173


163-165: Prefer logger.exception in except blocks for full tracebacks.

You already pass exc_info=True; logger.exception is a bit more idiomatic and avoids embedding the exception string into the message.

Example adjustment:

-        except Exception as e:
-            logger.error(f"Failed to sync {user_email} to Mycelia: {e}", exc_info=True)
+        except Exception:
+            logger.exception("Failed to sync %s to Mycelia", user_email)
             return None
...
-        except Exception as e:
-            logger.error(f"Failed to sync admin user: {e}", exc_info=True)
+        except Exception:
+            logger.exception("Failed to sync admin user")
             return None

Based on learnings, this improves debuggability by always recording the full stack trace.

Also applies to: 216-218


195-211: Update CLI instructions to use uv run python per project guidelines.

The log message shows python create_mycelia_api_key.py, but repo guidelines prefer uv run python for Python invocations.

-                    logger.info("   cd backends/advanced/scripts")
-                    logger.info("   python create_mycelia_api_key.py")
+                    logger.info("   cd backends/advanced/scripts")
+                    logger.info("   uv run python create_mycelia_api_key.py")

As per coding guidelines, this keeps user-facing instructions aligned with the standard tooling.

backends/advanced/src/advanced_omi_backend/services/memory/config.py (2)

35-46: Memory provider enum, defaults, and env mapping look coherent post‑rebrand.

  • MemoryProvider now exposes only CHRONICLE, OPENMEMORY_MCP, and MYCELIA, with MemoryConfig.memory_provider defaulting to CHRONICLE.
  • build_memory_config_from_env lower‑cases MEMORY_PROVIDER, maps legacy "friend-lite"/"friend_lite" to "chronicle", validates against MemoryProvider, and branches cleanly for OpenMemory MCP and Mycelia before falling through to the Chronicle config loader path.
  • The final log line correctly reports Provider=Chronicle for the Chronicle branch.

This all lines up with the Chronicle‑first behavior and should keep legacy env values working.

Optionally, you could make the Chronicle branch explicit for readability and future providers:

if memory_provider_enum == MemoryProvider.OPENMEMORY_MCP:
    ...
elif memory_provider_enum == MemoryProvider.MYCELIA:
    ...
else:  # Chronicle
    ...

Also applies to: 144-159, 177-207, 291-303


208-213: Consider justifying or revisiting the in‑function import of get_config_loader.

from advanced_omi_backend.memory_config_loader import get_config_loader lives inside build_memory_config_from_env, which goes against the project rule to keep imports at the top unless lazy import is required (e.g., circular dependency).

If there is no circular‑import issue, moving this import to the module top would better match the guidelines. If there is a circular dependency, a short comment explaining that here would be helpful. As per coding guidelines, imports should generally not be placed inside functions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c79e61 and 21e2a5c.

⛔ Files ignored due to path filters (1)
  • backends/advanced/webui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • backends/advanced/.env.template (3 hunks)
  • backends/advanced/src/advanced_omi_backend/models/conversation.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py (5 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use uv run python command instead of direct python or python3 for executing Python scripts
Use Black formatter with 100-character line length for Python code style
Use isort for Python import organization
NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring
Group imports in order: standard library, third-party, local imports
Use lazy imports sparingly and only when absolutely necessary for circular import issues in Python
Always raise errors explicitly in Python code, never silently ignore errors or failures
Use explicit error handling with proper exceptions in Python rather than silent failures
Understand data structures and research input/response or class structure instead of adding defensive hasattr() checks in Python

Files:

  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
🧠 Learnings (1)
📚 Learning: 2025-12-08T23:52:34.959Z
Learnt from: AnkushMalaker
Repo: chronicler-ai/chronicle PR: 178
File: backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py:218-223
Timestamp: 2025-12-08T23:52:34.959Z
Learning: In Python code (chronicle project), prefer logging.exception() inside except blocks to automatically log the full stack trace. When re-raising exceptions, always chain with 'raise ... from e' to preserve the original context; use 'raise ... from None' only if you explicitly want to suppress the context. This improves debuggability across Python files.

Applied to files:

  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
🧬 Code graph analysis (2)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
🪛 Ruff (0.14.8)
backends/advanced/src/advanced_omi_backend/services/memory/config.py

156-156: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (6)
backends/advanced/.env.template (2)

102-124: Configuration update aligns with Chronicle rebranding — verify backend implementation.

The MEMORY_PROVIDER section is well-documented and the default is now properly set to "chronicle." The comments clearly explain the three memory provider options and their respective trade-offs.

Please confirm that the new MemoryProvider.CHRONICLE is properly implemented and wired in the backend initialization code to ensure that setting MEMORY_PROVIDER=chronicle will work as expected at runtime.


134-134: OPENMEMORY_CLIENT_NAME example updated for consistency.

The commented example for OPENMEMORY_CLIENT_NAME has been updated to "chronicle," which maintains consistency with the new branding when users enable the OpenMemory MCP provider.

backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (3)

85-89: Chronicle‑scoped Mycelia key lookup and document shape look consistent.

Using owner = user_id (Chronicle user ID) plus a Chronicle‑specific name discriminator should avoid collisions with other keys and makes the policy block explicit. This matches the intent to map back to Chronicle users.

Also applies to: 100-109


138-142: Chronicle DB selection for user sync is correct and consistent.

Using self.chronicle_db when updating and reading the users collection correctly separates Chronicle user documents from the Mycelia DB and matches the new Chronicle naming.

Also applies to: 180-182


238-241: MEMORY_PROVIDER normalization resolves earlier case‑sensitivity issue.

Lower‑casing MEMORY_PROVIDER before comparing to "mycelia" means values like "MYCELIA" or "Mycelia" will now correctly enable the startup sync, addressing the previous review comment.

backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)

112-125: OpenMemory MCP client naming defaults are consistent with Chronicle branding.

Using "chronicle" as the default client_name both in create_openmemory_config and in OPENMEMORY_CLIENT_NAME fallback keeps naming consistent and makes it easy to override via env vars.

Also applies to: 160-175

Comment on lines +38 to +46
# Chronicle database - extract from MONGODB_URI or use default
# Test env: test_db, Production: chronicle
if "/" in self.mongo_url and self.mongo_url.count("/") >= 3:
# Extract database name from mongodb://host:port/database
self.friendlite_db = self.mongo_url.split("/")[-1].split("?")[0] or "friend-lite"
self.chronicle_db = self.mongo_url.split("/")[-1].split("?")[0] or "chronicle"
else:
self.friendlite_db = "friend-lite"
self.chronicle_db = "chronicle"

logger.info(
f"MyceliaSyncService initialized: {self.mongo_url}, Mycelia DB: {self.mycelia_db}, Friend-Lite DB: {self.friendlite_db}"
)
logger.info(f"MyceliaSyncService initialized: {self.mongo_url}, Mycelia DB: {self.mycelia_db}, Chronicle DB: {self.chronicle_db}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging full MongoDB URI (credentials may leak into logs).

logger.info currently logs self.mongo_url, which can embed usernames/passwords from MONGODB_URI. That’s a security and compliance risk; you only need DB names here.

Consider something like:

-        logger.info(f"MyceliaSyncService initialized: {self.mongo_url}, Mycelia DB: {self.mycelia_db}, Chronicle DB: {self.chronicle_db}")
+        logger.info(
+            "MyceliaSyncService initialized: Mycelia DB=%s, Chronicle DB=%s",
+            self.mycelia_db,
+            self.chronicle_db,
+        )
🤖 Prompt for AI Agents
In backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py around
lines 38 to 46, the logger.info call prints self.mongo_url which may contain
credentials; replace that log to avoid leaking sensitive info by removing
self.mongo_url and instead log only the derived database names (self.mycelia_db
and self.chronicle_db) or an obfuscated/host-only form of the URI; update the
log message accordingly so no raw MONGODB_URI is emitted.

@SimpleOpenSoftware SimpleOpenSoftware deleted a comment from coderabbitai bot Dec 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (15)
backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py (1)

150-203: Move import to the top of the file per coding guidelines.

The import statement at line 152 violates the explicit coding guideline: "NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring."

As per coding guidelines, move the import to the top of the file with other local imports:

 from advanced_omi_backend.controllers.queue_controller import redis_conn
 from advanced_omi_backend.client_manager import get_client_manager
 from advanced_omi_backend.llm_client import async_health_check
 from advanced_omi_backend.services.memory import get_memory_service
 from advanced_omi_backend.services.transcription import get_transcription_provider
+from advanced_omi_backend.controllers.queue_controller import get_queue_health

Then remove the import from inside the function:

     # Check Redis and RQ Workers (critical for queue processing)
     try:
-        from advanced_omi_backend.controllers.queue_controller import get_queue_health
-
         # Get queue health (includes Redis connection test and worker count)
         queue_health = await asyncio.wait_for(
extras/openmemory-mcp/test_standalone.py (4)

44-45: Add error handling for bare except clause.

Bare except blocks that silently fail make debugging difficult. Log the error or be more specific about which exceptions to catch.

     async def test_connection(self) -> bool:
         """Test if server is reachable."""
         try:
             response = await self.client.get(f"{self.server_url}/")
             return response.status_code in [200, 404, 422]
-        except:
+        except Exception as e:
+            logger.debug(f"Connection test failed: {e}")
             return False

128-129: Add error handling for bare except clause.

Bare except blocks that silently fail make debugging difficult. Log the error or be more specific about which exceptions to catch.

     async def get_stats(self) -> Dict[str, Any]:
         """Get memory statistics."""
         try:
             response = await self.client.get(
                 f"{self.server_url}/api/v1/stats/",
                 params={"user_id": self.user_id}
             )
             response.raise_for_status()
             return response.json()
-        except:
+        except Exception as e:
+            logger.debug(f"Failed to get stats: {e}")
             return {}

313-344: Move all imports to the top of the file.

Line 317 imports load_dotenv inside the load_env_files() function. Per coding guidelines, all imports must be at the top of the file after the docstring. Only use lazy imports sparingly for circular import issues.

 #!/usr/bin/env python3
 """Standalone test script for OpenMemory MCP server.
@@ -13,6 +13,12 @@ import subprocess
 import sys
 from typing import List, Dict, Any
 import httpx
 from pathlib import Path
+
+# Try to import dotenv for .env file support
+try:
+    from dotenv import load_dotenv
+except ImportError:
+    load_dotenv = None

 # Test Configuration Flags (following project patterns)
 # TODO: Update CLAUDE.md documentation to reflect FRESH_RUN flag usage across all integration tests

Then update the load_env_files() function:

 def load_env_files():
     """Load environment from .env.test (priority) or .env (fallback), following project patterns."""
     try:
-        # Try to import python-dotenv for proper .env parsing
-        from dotenv import load_dotenv
-        
+        if load_dotenv is None:
+            raise ImportError("python-dotenv not available")
+
         env_test_path = Path('.env.test')
         env_path = Path('.env')
         
         if env_test_path.exists():

160-160: Move Response import to the top of the file.

Line 160 imports Response inside the dispatch() method. Move this to the top with other FastAPI/Starlette imports.

 from fastapi import FastAPI, HTTPException, Request
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.responses import JSONResponse, StreamingResponse
+from starlette.responses import Response
 from pymongo.errors import ConnectionFailure, PyMongoError
 from starlette.middleware.base import BaseHTTPMiddleware

Then remove the import inside the function:

                 # Recreate response with the body we consumed
-                from starlette.responses import Response
                 return Response(
backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py (1)

160-160: Move Response import to the top of the file.

Line 160 imports Response inside the dispatch() method. Per coding guidelines, all imports must be at the top of the file.

 from fastapi import FastAPI, HTTPException, Request
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.responses import JSONResponse, StreamingResponse
+from starlette.responses import Response
 from pymongo.errors import ConnectionFailure, PyMongoError
 from starlette.middleware.base import BaseHTTPMiddleware

Then remove the import inside the function:

                 # Recreate response with the body we consumed
-                from starlette.responses import Response
                 return Response(
backends/advanced/Docs/HTTPS_SETUP.md (2)

92-92: Inconsistent naming: friend-backend should be chronicle-backend.

This line still references friend-backend which is inconsistent with the Chronicle rebranding throughout this PR. The Docker Compose profiles section should reflect the new service name.

-- ✅ friend-backend (port 8000, internal)
+- ✅ chronicle-backend (port 8000, internal)

102-102: Same inconsistency: friend-backend reference.

Another reference to friend-backend that should be updated to chronicle-backend for consistency.

-- ✅ friend-backend (port 8000)
+- ✅ chronicle-backend (port 8000)
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (2)

47-52: Move os import to top of file.

Per coding guidelines, all imports must be at the top of the file. The os module is imported inside __init__ on line 48.

Move to the imports section at the top:

 import logging
+import os
 import uuid
 from typing import List, Dict, Any, Optional
 import httpx

Then remove the inline import:

         # Use custom CA certificate if available
-        import os
         ca_bundle = os.getenv('REQUESTS_CA_BUNDLE')

114-141: Dead code: payload variable is defined but never used.

The payload dictionary at lines 114-124 is constructed but then ignored—the actual POST request at line 128 passes a new inline json= dict. Additionally, the unused payload still contains the old branding ("source": "friend_lite" on line 119), while the actually-used inline dict correctly uses "source": "chronicle" on line 135.

Remove the unused payload variable to avoid confusion and dead code.

-            payload = {
-                "user_id": self.user_id,
-                "text": text,
-                "app": self.client_name,  # Use app name (OpenMemory accepts name or UUID)
-                "metadata": {
-                    "source": "friend_lite",
-                    "client": self.client_name,
-                    "user_email": self.user_email
-                },
-                "infer": True
-            }
-
-            memory_logger.info(f"POSTing memory to {self.server_url}/api/v1/memories/ with payload={payload}")
+            memory_logger.info(f"POSTing memory to {self.server_url}/api/v1/memories/")

             response = await self.client.post(
                 f"{self.server_url}/api/v1/memories/",
backends/advanced/init.py (1)

230-230: Typo: gpt-5-mini should be gpt-4o-mini.

Same issue as in CLAUDE.md—the default model is gpt-5-mini but should be gpt-4o-mini to match the rest of the codebase.

-            model = self.prompt_value("OpenAI model", "gpt-5-mini")
+            model = self.prompt_value("OpenAI model", "gpt-4o-mini")
backends/charts/advanced-backend/Chart.yaml (1)

10-12: Repository URLs still reference the old Friend repository.

The sources and home fields point to https://github.com/BasedHardware/Friend, which is inconsistent with the Chronicle rebranding. These should be updated to reflect the new repository location.

 sources:
-  - https://github.com/BasedHardware/Friend
-home: https://github.com/BasedHardware/Friend
+  - https://github.com/chronicler-ai/chronicle
+home: https://github.com/chronicler-ai/chronicle
backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (1)

149-155: Silent exception swallowing reduces debuggability.

The bare except Exception: pass silently discards errors when determining the memory provider. At minimum, log the exception for debugging purposes.

                 try:
                     memory_service_obj = get_memory_service()
                     provider_name = memory_service_obj.__class__.__name__
                     if "OpenMemory" in provider_name:
                         memory_provider = conversation_model.MemoryProvider.OPENMEMORY_MCP
-                except Exception:
-                    pass
+                except Exception:
+                    logger.debug("Could not determine memory provider from service, using default")
extras/speaker-recognition/init.py (2)

74-77: Move import to top of file.

The get_key import from dotenv should be at the top of the file alongside the existing set_key import on line 17. As per coding guidelines, imports must be at the top of the file.

Update line 17 to include both imports:

-from dotenv import set_key
+from dotenv import get_key, set_key

Then remove the import from inside the function:

     def read_existing_env_value(self, key: str) -> str:
         """Read a value from existing .env file"""
         env_path = Path(".env")
         if not env_path.exists():
             return None
 
-        from dotenv import get_key
         value = get_key(str(env_path), key)

170-171: Move re import to top of file.

The re module import should be at the top of the file with other standard library imports. As per coding guidelines, imports must be at the top of the file.

Add to the standard library imports section (after line 13):

import re

Then remove line 170 from inside the function.

♻️ Duplicate comments (3)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)

38-46: Potential credentials leak: MongoDB URI logged.

The logger.info on line 46 still logs self.mongo_url, which may contain embedded credentials. This was flagged in a previous review but remains unaddressed.

-        logger.info(f"MyceliaSyncService initialized: {self.mongo_url}, Mycelia DB: {self.mycelia_db}, Chronicle DB: {self.chronicle_db}")
+        logger.info(
+            "MyceliaSyncService initialized: Mycelia DB=%s, Chronicle DB=%s",
+            self.mycelia_db,
+            self.chronicle_db,
+        )
backends/charts/advanced-backend/templates/workers-deployment.yaml (1)

25-29: Naming updates are consistent, but referenced resources must exist.

The chronicle-config and chronicle-secrets references align with the rebranding. However, as noted in a previous review, these ConfigMap and Secret resources are not defined in the Helm chart templates. Ensure they are created (either as chart templates or externally provisioned) before deployment, or pods will fail to start.

README-K8S.md (1)

270-271: Fix directory reference after git clone.

Line 270 now clones the repository as chronicle, but line 271 still references cd friend-lite. This will cause a "directory not found" error.

Apply this fix:

 git clone --recursive https://github.com/chronicle-ai/chronicle.git
-cd friend-lite
+cd chronicle
🧹 Nitpick comments (17)
backends/advanced/src/advanced_omi_backend/app_config.py (3)

28-33: Double‑check MongoDB default database name vs. rebrand

Default self.mongodb_database is still "friend-lite", while the rest of the file/PR is moving to Chronicle naming. If new deployments are expected to use a chronicle DB by default, this may be surprising; if you’re intentionally keeping the old DB name for backward compatibility/migration, consider adding a short comment to make that explicit.


67-71: MEMORY_PROVIDER default change to chronicle—ensure ecosystem alignment

Changing the default MEMORY_PROVIDER to "chronicle" (lower‑cased) is fine, but it relies on this exact string matching what other components (enums, clients, services, infra manifests) expect. Please confirm:

  • Any enums or typed configs use the same canonical value "chronicle".
  • Env templates/docs/examples were updated to use MEMORY_PROVIDER=chronicle.

If there is already a central MemoryProvider enum/constant set, wiring this to that instead of a raw string would further reduce drift risk, but that can be deferred.


86-88: Threshold support flag tied to specific provider string

memory_service_supports_threshold = self.memory_provider == "chronicle" is correct for the immediate rename, but it bakes feature support into a string comparison. If additional providers will also support threshold behavior later, this will have to be updated in multiple places. Consider, when convenient, deriving this from provider metadata (e.g., an enum or a provider config map) so feature flags follow the provider definition rather than hard‑coded conditionals here.

backends/advanced/upload_files.py (1)

191-213: Comment about 20‑minute duration filtering is out of sync with implementation.

The comment says “filter out files over 20 minutes,” but the code only logs duration and always appends files without enforcing any max-length rule. Either implement the documented filter or update the comment/docstring to match current behavior.

backends/advanced/src/advanced_omi_backend/auth.py (1)

123-133: JWT payload now aligned with Chronicle branding and 24h lifetime

The JWT payload for generate_jwt_for_user now uses iss="chronicle" and aud="chronicle" with a 24‑hour expiry via timedelta(hours=24), which is consistent with the documented 24‑hour validity and the broader Chronicle rebranding.

If you want to keep lifetimes centralized, you could optionally derive exp from JWT_LIFETIME_SECONDS instead of hard‑coding hours=24, but the current behavior is correct.

extras/asr-services/tests/test_parakeet_service.py (1)

14-18: Consider making the example cd path repo-agnostic

The updated path points to a specific user directory under .../chronicle/.... To make the instructions friendlier for other contributors, consider switching to a relative example such as:

  • cd extras/asr-services (from repo root), or
  • cd path/to/chronicle/extras/asr-services
backends/advanced/Docs/memories.md (1)

475-477: Optional: align CLI example with uv‑based workflow

The docs currently suggest running the test script with python test_memory_creation.py. For consistency with the project’s Python workflow, consider updating this to use uv, for example:

-# Run the memory test script
-python test_memory_creation.py
+# Run the memory test script
+uv run python test_memory_creation.py

As per coding guidelines, this keeps Python execution consistent with the rest of the project.

backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (2)

145-152: Update leftover “Friend‑Lite” mentions in comments

These comments still refer to “Friend-Lite user details”, while the rest of the file and PR have moved to Chronicle terminology. For consistency and to avoid confusion, consider updating them:

-            # Pass Friend-Lite user details to OpenMemory for proper user tracking
+            # Pass Chronicle user details to OpenMemory for proper user tracking
@@
-            # Update MCP client with Friend-Lite user details
+            # Update MCP client with Chronicle user details

102-105: Improve exception logging and error chaining during initialization

Right now initialization failures log only the message and then raise a new RuntimeError, losing the original traceback context. Consider switching to logging.exception and chaining the error:

-        except Exception as e:
-            memory_logger.error(f"OpenMemory MCP service initialization failed: {e}")
-            raise RuntimeError(f"Initialization failed: {e}")
+        except Exception as e:
+            memory_logger.exception("OpenMemory MCP service initialization failed")
+            raise RuntimeError("Initialization failed") from e

This preserves the full stack trace and original exception while keeping logs clean. You may want to apply the same pattern to other broad except Exception blocks in this module over time. Based on learnings, this aligns with the preferred error‑handling style in this project.

backends/advanced/docker-compose.yml (1)

227-229: Optional: consider renaming the shared Docker network for branding consistency

The default network is still named friend-network. Not a functional problem, but if you want the Docker resources to fully reflect the Chronicle branding, you could rename it:

networks:
  default:
-    name: friend-network
+    name: chronicle-network

This would change the user‑visible network name, so only do this if you’re comfortable with that minor compatibility impact.

backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (1)

96-109: Move Conversation import to the top of the module and remove redundant datetime import

handle_end_of_conversation currently performs:

from advanced_omi_backend.models.conversation import Conversation
from datetime import datetime

inside the function body, and datetime is already imported at the top of the file. Per the project’s Python guidelines (no mid‑file imports unless strictly necessary for circularity), it would be cleaner to:

  • Move Conversation to the top import section.
  • Drop the inner from datetime import datetime entirely.

For example:

-from datetime import datetime
+from datetime import datetime
+from advanced_omi_backend.models.conversation import Conversation
...
-    # Update conversation in database with end reason and completion time
-    from advanced_omi_backend.models.conversation import Conversation
-    from datetime import datetime
+    # Update conversation in database with end reason and completion time

If there is a circular‑import concern, consider adding a short comment explaining why the lazy import is required instead. As per coding guidelines, this keeps imports consistent and easier to reason about.

backends/advanced/scripts/sync_friendlite_mycelia.py (1)

115-115: Consider renaming the variable for consistency.

The variable fl_db appears to be a holdover from "Friend-Lite" naming. Consider renaming it to chronicle_db_conn or simply db to maintain consistency with the Chronicle rebranding.

Apply this diff to improve consistency:

-        fl_db = self.client[self.chronicle_db]
-        fl_db["users"].update_one(
+        chronicle_db_conn = self.client[self.chronicle_db]
+        chronicle_db_conn["users"].update_one(

Similar changes should be applied at lines 234 and 364.

extras/speaker-recognition/charts/templates/speaker-deployment.yaml (1)

35-39: Hardcoded configMapRef name may reduce deployment flexibility.

The configMapRef is hardcoded to chronicle-config while secretRef on line 39 uses a templated value with a fallback. This inconsistency could cause issues if deploying multiple instances or if the configMap naming convention changes.

Consider templating this similar to the secretRef pattern:

          envFrom:
            - configMapRef:
-               name: chronicle-config
+               name: {{ .Values.configMap.name | default "chronicle-config" }}
            - secretRef:
                name: {{ .Values.secrets.name | default (printf "%s-secrets" .Release.Name) }}
backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (1)

222-223: Use logging.exception() to capture the full stack trace.

Per project conventions, prefer logging.exception() inside except blocks to automatically log the full stack trace, improving debuggability. Based on learnings.

                 except Exception as e:
-                    logger.warning(f"Failed to fetch memory details for UI: {e}")
+                    logger.exception("Failed to fetch memory details for UI")
extras/speaker-recognition/init.py (1)

436-438: Consider using logging.exception() for better stack traces.

When catching exceptions, using logging.exception() automatically includes the full stack trace, improving debuggability. Based on learnings.

         except Exception as e:
-            self.console.print(f"[red][ERROR][/red] Setup failed: {e}")
+            import logging
+            logging.exception("Setup failed")
+            self.console.print(f"[red][ERROR][/red] Setup failed: {e}")
             sys.exit(1)

Alternatively, if you add a module-level logger, use logger.exception("Setup failed").

backends/advanced/webui/src/pages/Memories.tsx (1)

259-262: Consider mapping legacy friend_lite to a friendlier label.

The new mapping for 'chronicle' and 'openmemory_mcp' looks good. If the backend can still return 'friend_lite' (for legacy data), you may want to special‑case it here as well so users don’t see a raw provider ID string in the UI.

backends/advanced/tests/test_conversation_models.py (1)

91-106: Tests correctly target MemoryProvider.CHRONICLE; optionally also cover legacy FRIEND_LITE.

Updating all usages to MemoryProvider.CHRONICLE and asserting its string value "chronicle" matches the new enum is correct and aligned with the model changes.

Given the enum now also includes a legacy FRIEND_LITE = "friend_lite" for backward compatibility, you might optionally add an assertion in test_provider_enums to ensure that legacy value stays supported:

     # Test MemoryProvider enum
-    assert MemoryProvider.CHRONICLE == "chronicle"
-    assert MemoryProvider.OPENMEMORY_MCP == "openmemory_mcp"
+    assert MemoryProvider.CHRONICLE == "chronicle"
+    assert MemoryProvider.OPENMEMORY_MCP == "openmemory_mcp"
+    assert MemoryProvider.FRIEND_LITE == "friend_lite"  # legacy compatibility

Also applies to: 150-157, 201-202, 220-222, 230-231

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dededcd and 0bc569a.

⛔ Files ignored due to path filters (1)
  • backends/advanced/webui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (107)
  • .env.template (5 hunks)
  • CLAUDE.md (8 hunks)
  • Docs/features.md (3 hunks)
  • Docs/getting-started.md (7 hunks)
  • Docs/init-system.md (3 hunks)
  • Docs/ports-and-access.md (1 hunks)
  • Makefile (9 hunks)
  • README-K8S.md (10 hunks)
  • README.md (1 hunks)
  • app/README.md (7 hunks)
  • app/app.json (1 hunks)
  • backends/README.md (1 hunks)
  • backends/advanced/.env.template (3 hunks)
  • backends/advanced/Docs/HTTPS_SETUP.md (3 hunks)
  • backends/advanced/Docs/README.md (1 hunks)
  • backends/advanced/Docs/UI.md (1 hunks)
  • backends/advanced/Docs/architecture.md (2 hunks)
  • backends/advanced/Docs/auth.md (2 hunks)
  • backends/advanced/Docs/memories.md (4 hunks)
  • backends/advanced/Docs/quickstart.md (7 hunks)
  • backends/advanced/docker-compose-test.yml (7 hunks)
  • backends/advanced/docker-compose.yml (6 hunks)
  • backends/advanced/init-https.sh (3 hunks)
  • backends/advanced/init.py (7 hunks)
  • backends/advanced/scripts/create_mycelia_api_key.py (2 hunks)
  • backends/advanced/scripts/sync_friendlite_mycelia.py (12 hunks)
  • backends/advanced/setup-https.sh (2 hunks)
  • backends/advanced/src/advanced_omi_backend/app_config.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/app_factory.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/auth.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/chat_service.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/config.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/database.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/conversation.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py (5 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (7 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (10 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2 hunks)
  • backends/advanced/ssl/generate-ssl.sh (1 hunks)
  • backends/advanced/start-k8s.sh (1 hunks)
  • backends/advanced/start-workers.sh (1 hunks)
  • backends/advanced/start.sh (1 hunks)
  • backends/advanced/tests/test_conversation_models.py (6 hunks)
  • backends/advanced/tests/test_integration.py (2 hunks)
  • backends/advanced/upload_files.py (3 hunks)
  • backends/advanced/webui/README.md (1 hunks)
  • backends/advanced/webui/package.json (2 hunks)
  • backends/advanced/webui/src/components/layout/Layout.tsx (2 hunks)
  • backends/advanced/webui/src/pages/LoginPage.tsx (1 hunks)
  • backends/advanced/webui/src/pages/Memories.tsx (2 hunks)
  • backends/advanced/webui/src/pages/MemoriesRouter.tsx (2 hunks)
  • backends/advanced/webui/src/pages/System.tsx (1 hunks)
  • backends/advanced/webui/tsconfig.json (1 hunks)
  • backends/charts/advanced-backend/Chart.yaml (1 hunks)
  • backends/charts/advanced-backend/templates/deployment.yaml (2 hunks)
  • backends/charts/advanced-backend/templates/workers-deployment.yaml (1 hunks)
  • backends/charts/advanced-backend/values.yaml (1 hunks)
  • backends/charts/webui/Chart.yaml (1 hunks)
  • backends/charts/webui/templates/deployment.yaml (1 hunks)
  • backends/charts/webui/values.yaml (1 hunks)
  • extras/asr-services/README.md (2 hunks)
  • extras/asr-services/quickstart.md (2 hunks)
  • extras/asr-services/tests/test_parakeet_service.py (1 hunks)
  • extras/havpe-relay/README.md (1 hunks)
  • extras/havpe-relay/main.py (1 hunks)
  • extras/local-omi-bt/connect-omi.py (2 hunks)
  • extras/openmemory-mcp/README.md (9 hunks)
  • extras/openmemory-mcp/run.sh (2 hunks)
  • extras/openmemory-mcp/test_standalone.py (1 hunks)
  • extras/speaker-omni-experimental/README.md (3 hunks)
  • extras/speaker-recognition/charts/templates/speaker-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/templates/webui-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/values.yaml (1 hunks)
  • extras/speaker-recognition/init.py (1 hunks)
  • extras/speaker-recognition/quickstart.md (1 hunks)
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py (1 hunks)
  • extras/speaker-recognition/ssl/generate-ssl.sh (1 hunks)
  • extras/speaker-recognition/tests/test_speaker_service_integration.py (1 hunks)
  • k8s-manifests/cross-namespace-rbac.yaml (1 hunks)
  • quickstart.md (6 hunks)
  • run-test.sh (2 hunks)
  • scripts/generate-k8s-configs.py (4 hunks)
  • scripts/k8s/cluster-status.sh (1 hunks)
  • scripts/k8s/load-env.sh (1 hunks)
⛔ Files not processed due to max files limit (17)
  • scripts/manage-audio-files.sh
  • services.py
  • skaffold.yaml
  • status.py
  • tests/.env.test
  • tests/Makefile
  • tests/README.md
  • tests/TESTING_USER_GUIDE.md
  • tests/browser/browser_auth.robot
  • tests/infrastructure/infra_tests.robot
  • tests/libs/audio_stream_library.py
  • tests/resources/websocket_keywords.robot
  • tests/setup/setup_keywords.robot
  • tests/setup/test_env.py
  • tests/setup/test_manager_keywords.robot
  • tests/tags.md
  • wizard.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use uv run python command instead of direct python or python3 for executing Python scripts
Use Black formatter with 100-character line length for Python code style
Use isort for Python import organization
NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring
Group imports in order: standard library, third-party, local imports
Use lazy imports sparingly and only when absolutely necessary for circular import issues in Python
Always raise errors explicitly in Python code, never silently ignore errors or failures
Use explicit error handling with proper exceptions in Python rather than silent failures
Understand data structures and research input/response or class structure instead of adding defensive hasattr() checks in Python

Files:

  • extras/openmemory-mcp/test_standalone.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/src/advanced_omi_backend/auth.py
  • extras/speaker-recognition/init.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • extras/speaker-recognition/tests/test_speaker_service_integration.py
  • backends/advanced/init.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/tests/test_integration.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/upload_files.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • scripts/generate-k8s-configs.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • extras/havpe-relay/main.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
🧠 Learnings (2)
📚 Learning: 2025-12-08T23:52:34.959Z
Learnt from: AnkushMalaker
Repo: chronicler-ai/chronicle PR: 178
File: backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py:218-223
Timestamp: 2025-12-08T23:52:34.959Z
Learning: In Python code (chronicle project), prefer logging.exception() inside except blocks to automatically log the full stack trace. When re-raising exceptions, always chain with 'raise ... from e' to preserve the original context; use 'raise ... from None' only if you explicitly want to suppress the context. This improves debuggability across Python files.

Applied to files:

  • extras/openmemory-mcp/test_standalone.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/src/advanced_omi_backend/auth.py
  • extras/speaker-recognition/init.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • extras/speaker-recognition/tests/test_speaker_service_integration.py
  • backends/advanced/init.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/tests/test_integration.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/upload_files.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • scripts/generate-k8s-configs.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • extras/havpe-relay/main.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
📚 Learning: 2025-12-07T18:52:48.868Z
Learnt from: CR
Repo: chronicler-ai/chronicle PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T18:52:48.868Z
Learning: Check backends/advanced/Docs for up-to-date information on advanced backend development

Applied to files:

  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/Docs/README.md
  • backends/advanced/Docs/HTTPS_SETUP.md
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
🧬 Code graph analysis (11)
run-test.sh (2)
extras/speaker-recognition/run-test.sh (2)
  • print_info (34-36)
  • print_error (46-48)
backends/advanced/run-test.sh (2)
  • print_info (16-18)
  • print_error (28-30)
backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py (1)
backends/advanced/src/advanced_omi_backend/services/memory/providers/chronicle.py (1)
  • MemoryService (23-705)
backends/advanced/setup-https.sh (1)
backends/advanced/init.py (1)
  • print_header (36-45)
backends/advanced/init.py (1)
extras/speaker-recognition/init.py (3)
  • prompt_choice (89-104)
  • prompt_value (48-54)
  • print_header (31-40)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)
backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/tests/test_conversation_models.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • add_memory_version (261-289)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (2)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)

Comment on lines 360 to 365
{availableProviders.map((provider) => (
<option key={provider} value={provider}>
{provider === 'friend_lite' && 'Friend-Lite (Sophisticated)'}
{provider === 'chronicle' && 'Chronicle (Sophisticated)'}
{provider === 'openmemory_mcp' && 'OpenMemory MCP (Cross-client)'}
{provider === 'mycelia' && 'Mycelia (Advanced)'}
</option>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a fallback label for unknown/legacy providers in the select.

Right now the <option> only renders text when provider is one of 'chronicle' | 'openmemory_mcp' | 'mycelia'. Any other value (including potential legacy 'friend_lite' or future providers) will show a blank option.

Recommend adding a fallback to display the raw provider string:

-                    {availableProviders.map((provider) => (
-                      <option key={provider} value={provider}>
-                          {provider === 'chronicle' && 'Chronicle (Sophisticated)'}
-                          {provider === 'openmemory_mcp' && 'OpenMemory MCP (Cross-client)'}
-                          {provider === 'mycelia' && 'Mycelia (Advanced)'}
-                        </option>
-                      ))}
+                    {availableProviders.map((provider) => (
+                      <option key={provider} value={provider}>
+                        {provider === 'chronicle'
+                          ? 'Chronicle (Sophisticated)'
+                          : provider === 'openmemory_mcp'
+                          ? 'OpenMemory MCP (Cross-client)'
+                          : provider === 'mycelia'
+                          ? 'Mycelia (Advanced)'
+                          : provider}
+                      </option>
+                    ))}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In backends/advanced/webui/src/pages/System.tsx around lines 360 to 365, the
option label logic only renders text for 'chronicle', 'openmemory_mcp', and
'mycelia', leaving other provider values blank; update the JSX so the <option>
shows a human-friendly label for those three cases and falls back to rendering
the raw provider string (provider) for any unknown/legacy/future providers
(e.g., 'friend_lite') so the select never displays an empty option.

@SimpleOpenSoftware SimpleOpenSoftware deleted a comment from coderabbitai bot Dec 11, 2025
# Conflicts:
#	README-K8S.md
#	backends/advanced/src/advanced_omi_backend/auth.py
#	backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
#	backends/advanced/webui/package-lock.json
#	backends/advanced/webui/package.json
#	quickstart.md
#	tests/infrastructure/infra_tests.robot
#	tests/integration/websocket_streaming_tests.robot
Copy link
Collaborator

@AnkushMalaker AnkushMalaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments and a question, otherwise looks good!

# Conflicts:
#	README-K8S.md
#	backends/advanced/src/advanced_omi_backend/auth.py
#	backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
#	backends/advanced/webui/package-lock.json
#	backends/advanced/webui/package.json
#	quickstart.md
#	tests/infrastructure/infra_tests.robot
#	tests/integration/websocket_streaming_tests.robot
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Comprehensive rebranding of the project from "Friend-Lite" to "Chronicle": names, defaults, env vars, Kubernetes/Helm references, docs, UI strings, memory provider enums/exports, and some public class names were updated. No new control flow or feature additions detected.

Changes

Cohort / File(s) Summary
Configuration & Environment Files
\.env.template, backends/advanced/\.env.template, backends/advanced/docker-compose.yml, backends/advanced/docker-compose-test.yml, scripts/generate-k8s-configs.py, scripts/k8s/load-env.sh
MEMORY_PROVIDER default changed from friend_litechronicle; MongoDB DB path defaults updated; service names and namespace defaults renamed (friend-backend → chronicle-backend, friend-lite → chronicle).
Documentation & Guides
README.md, README-K8S.md, quickstart.md, CLAUDE.md, Docs/*, Docs/getting-started.md, Docs/features.md, Docs/init-system.md, Docs/ports-and-access.md, backends/advanced/Docs/*, extras/*/README.md, extras/*/quickstart.md
Systematic textual rebrand: "Friend-Lite" → "Chronicle" across headings, examples, env docs and guides. No logic changes.
Backend Initialization & Scripts
backends/advanced/init.py, backends/advanced/init-https.sh, backends/advanced/setup-https.sh, backends/advanced/scripts/sync_friendlite_mycelia.py, backends/advanced/scripts/create_mycelia_api_key.py, backends/advanced/scripts/sync_chronicle_mycelia.py
Main setup class renamed (FriendLiteSetup → ChronicleSetup); CLI/help text and script messages rebranded; Mycelia sync script classes, parameters and API-key naming updated to Chronicle.
Backend Python (core) & Config
backends/advanced/src/advanced_omi_backend/app_config.py, app_factory.py, config.py, auth.py, database.py, app_middleware.py, controllers/*, routers/*, services/*
Docstrings updated to Chronicle; auth adds JWT_LIFETIME_SECONDS (env-driven); memory provider defaults/mapping updated to treat legacy names (friend-lite, friend_lite) → chronicle.
Memory Provider & MCP Clients
backends/advanced/src/advanced_omi_backend/services/memory/config.py, services/memory/providers/__init__.py, mcp_client.py, openmemory_mcp.py, mycelia.py, service_factory.py
MemoryProvider enum and defaults switched to CHRONICLE; legacy-name mappings added; MCP/OpenMemory client default client_name changed to chronicle; provider export alias updated to ChronicleMemoryService.
Models & Workers
backends/advanced/src/advanced_omi_backend/models/conversation.py, workers/conversation_jobs.py, workers/memory_jobs.py
Conversation.MemoryProvider enum adds CHRONICLE and keeps legacy FRIEND_LITE; conversation job end_reason precedence logic improved (websocket_disconnect → inactivity_timeout → max_duration → user_stopped).
WebUI / Frontend
backends/advanced/webui/package.json, backends/advanced/webui/src/...
WebUI package name changed (friend-lite-webuichronicle-webui); UI labels and provider display strings updated; tsconfig relaxed (noImplicitAny: false).
Kubernetes / Helm
backends/charts/*/Chart.yaml, backends/charts/*/templates/*, backends/charts/*/values.yaml, extras/*/charts/*, k8s-manifests/cross-namespace-rbac.yaml
ConfigMap/Secret names and TLS secret examples renamed (friend-lite-config/secrets/tls → chronicle-config/secrets/tls); chart descriptions/keywords updated; RBAC namespace/resource names updated.
Shell Scripts & Makefile
Makefile, backends/advanced/start*.sh, backends/advanced/ssl/generate-ssl.sh, run-test.sh, scripts/*
Startup banners, help text, and script references rebranded to Chronicle; minor command name updates (sync_friendlite_mycelia.py → sync_chronicle_mycelia.py).
Extras & Integrations
extras/local-omi-bt/connect-omi.py, extras/openmemory-mcp/*, extras/speaker-recognition/*, extras/havpe-relay/*, extras/speaker-omni-experimental/*
Import paths, docstrings, metadata, and startup messages updated to Chronicle; some imports changed from friend_litechronicle.
Tests
backends/advanced/tests/test_conversation_models.py, backends/advanced/tests/test_integration.py, extras/*/tests/*
Tests updated to use MemoryProvider.CHRONICLE and updated default provider expectations; minor doc/comment updates in other tests.
App Manifests
app/app.json, app/README.md
iOS microphone usage string adjusted ("Friend-Lite" → "Friend Lite"); app README rebranded.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas requiring extra attention:

  • backends/advanced/src/advanced_omi_backend/services/memory/config.py and app_config.py — legacy-name mapping and default propagation.
  • backends/advanced/scripts/sync_friendlite_mycelia.py — class/parameter renames and DB name extraction consistency.
  • models/conversation.py (MemoryProvider enum) — verify all call sites and serialization/deserialization handle both CHRONICLE and legacy values.
  • Helm/k8s templates and RBAC (templates + k8s-manifests) — ensure ConfigMap/Secret names and namespace changes align with deployment tooling.
  • auth.py — new JWT_LIFETIME_SECONDS export and issuer/audience changes should be reviewed for compatibility.

Possibly related PRs

  • chronicler-ai/chronicle#131 — overlaps changes to backends/advanced/init.py (init system and setup flow).
  • chronicler-ai/chronicle#179 — overlaps Mycelia sync script and memory provider renames (sync script/class updates).
  • chronicler-ai/chronicle#187 — related to backend MongoDB database-name handling and app_config/database logic.

Suggested reviewers

  • AnkushMalaker

Poem

🐰 I hopped through code, light on my feet,

Friend‑Lite renamed, Chronicle upbeat.
Strings and enums now wear new hue,
Defaults aligned, the rollout’s due—
A tiny hop, a celebratory tweet.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'name change to chronicle' is vague and uses non-descriptive terminology that doesn't convey what is actually being renamed or why, despite the changeset being a comprehensive rebranding from Friend-Lite to Chronicle across 100+ files. Consider using a more descriptive title like 'Rebrand Friend-Lite to Chronicle across codebase' or 'Rebrand: Friend-Lite → Chronicle' to clearly communicate the scope and nature of the changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 91.23% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49323e7 and bc6911f.

📒 Files selected for processing (1)
  • backends/advanced/.env.template (4 hunks)

Comment @coderabbitai help to get the list of available commands and usage tips.

… into namechange

# Conflicts:
#	README-K8S.md
#	backends/advanced/src/advanced_omi_backend/app_config.py
#	backends/advanced/src/advanced_omi_backend/auth.py
#	backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
#	backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
#	backends/advanced/webui/package-lock.json
#	backends/advanced/webui/package.json
#	backends/advanced/webui/src/pages/System.tsx
#	tests/setup/test_env.py
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
backends/advanced/src/advanced_omi_backend/app_factory.py (5)

78-78: Move other mid-function imports to the top of the file.

Additional imports appear in the middle of the lifespan function at lines 78, 86, 111, and 138. These must also be moved to the top per coding guidelines.

Move these imports to the top-level import section:

+from advanced_omi_backend.services.mycelia_sync import sync_admin_on_startup
+from advanced_omi_backend.controllers.queue_controller import redis_conn
+from advanced_omi_backend.services.audio_stream import AudioStreamProducer
+from advanced_omi_backend.controllers.websocket_controller import cleanup_client_state

Then remove them from within the function (lines 78, 86, 111, 138).

If any of these cannot be moved due to circular imports, consider using lazy imports at the top and documenting the reason as a comment.

Also applies to: 86-86, 111-111, 138-138


65-67: Improve exception handling with proper error chaining.

When re-raising exceptions, chain with raise ... from e to preserve the original context. Additionally, use logging.exception() to automatically capture the full stack trace.

Apply this diff:

     except Exception as e:
-        application_logger.error(f"Failed to initialize Beanie: {e}")
-        raise
+        application_logger.exception("Failed to initialize Beanie")
+        raise from e

Based on learnings, this pattern should be applied consistently across all exception handlers in the lifespan function.


72-74: Apply consistent exception handling across all error blocks.

Multiple exception handlers use inconsistent approaches. Apply the same pattern throughout for consistency and better debuggability.

For blocks that re-raise (lines 65-67), use:

except Exception as e:
    application_logger.exception("Description of error")
    raise from e

For blocks that do not re-raise (lines 72-74, 80-82, 90-92, 100-102, 114-116, 140-141, 151-152, 159-160), use:

except Exception as e:
    application_logger.exception("Description of error")

Based on learnings, using logging.exception() automatically logs the stack trace, improving debuggability across Python files.

Also applies to: 80-82, 90-92, 100-102, 114-116, 140-141, 151-152, 159-160


189-189: Fix indentation before comment.

Line 189 has extra leading spaces.

Apply this diff:

-   # Add authentication routers
+    # Add authentication routers

55-58: Move all imports to the top of the file after the docstring.

Per coding guidelines, all imports must be at the top of the file, not in the middle of functions. Move these imports from lines 55–58, 78, 86, 111, and 138 to the top-level import section. No circular import dependencies prevent this refactoring.

Additionally, fix the indentation on line 189 (extra spaces before the comment "# Add authentication routers").

backends/advanced/tests/test_integration.py (2)

174-176: Remove redundant import inside function.

json is already imported at the top of the file (line 32). This inner import is redundant and violates coding guidelines. As per coding guidelines, all imports must be at the top of the file.

             with open(memories_path, 'r', encoding='utf-8') as f:
-                import json
                 data = json.load(f)

1063-1064: Remove redundant import inside function.

openai is already imported at the top of the file (line 43). This inner import is redundant. As per coding guidelines, all imports must be at the top of the file.

     def check_memory_similarity_simple(self, actual_memories: list, expected_memories: list) -> dict:
         """Use OpenAI to check if extracted memories are similar to expected memories."""
         try:
-            import openai
-            
             client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
README-K8S.md (1)

281-281: Update stale "Friend-Lite" reference in note.

This note still mentions "Friend-Lite memory system" instead of "Chronicle memory system", inconsistent with the rest of the rebranding.

-   > **Note:** The `--recursive` flag downloads the optional Mycelia submodule (an alternative memory backend with timeline visualization). Most deployments use the default Friend-Lite memory system and don't need Mycelia.
+   > **Note:** The `--recursive` flag downloads the optional Mycelia submodule (an alternative memory backend with timeline visualization). Most deployments use the default Chronicle memory system and don't need Mycelia.
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (1)

114-140: Remove unused payload variable.

The payload variable defined at lines 114-124 is never used—the actual POST request (lines 130-140) uses an inline dictionary instead. Additionally, the unused payload still contains the old value "source": "friend_lite" (line 119), while the actual payload correctly uses "source": "chronicle" (line 135).

Since we're updating this area for rebranding, this is a good opportunity to clean up the dead code.

Apply this diff to remove the unused variable:

             memory_logger.info(f"No matching app name, using first app ID: {app_id}")
 
         if not app_id:
             memory_logger.error("No apps found in OpenMemory - cannot create memory")
             raise MCPError("No apps found in OpenMemory")
 
-        # Use REST API endpoint for creating memories
-        # The 'app' field can be either app name (string) or app UUID
-        payload = {
-            "user_id": self.user_id,
-            "text": text,
-            "app": self.client_name,  # Use app name (OpenMemory accepts name or UUID)
-            "metadata": {
-                "source": "friend_lite",
-                "client": self.client_name,
-                "user_email": self.user_email
-            },
-            "infer": True
-        }
-
-        memory_logger.info(f"POSTing memory to {self.server_url}/api/v1/memories/ with payload={payload}")
-
+        # Use REST API endpoint for creating memories
+        # The 'app' field can be either app name (string) or app UUID
         response = await self.client.post(
             f"{self.server_url}/api/v1/memories/",
             json={
Makefile (1)

356-384: Script file not renamed—Makefile references will fail.

The Makefile references sync_chronicle_mycelia.py (lines 356, 362, 370, 374, 384), but the actual file is still named sync_friendlite_mycelia.py in backends/advanced/scripts/. Either rename the script to match the Makefile references or update all Makefile references back to the original filename.

♻️ Duplicate comments (9)
backends/advanced/webui/src/pages/System.tsx (1)

362-364: The previously flagged missing fallback for unknown providers remains unaddressed.

The option labels were updated for the rebranding, but any provider value outside of 'chronicle', 'openmemory_mcp', or 'mycelia' will still render as a blank option. Consider adding a fallback to display the raw provider string for legacy or future values (e.g., friend_lite or any new providers).

backends/advanced/src/advanced_omi_backend/auth.py (1)

26-29: Critical bug: JWT_LIFETIME_SECONDS is defined twice, env var is ignored.

Line 26 correctly reads from the environment variable, but line 29 immediately overwrites it with a hardcoded value of 86400. This means the JWT_LIFETIME_SECONDS environment variable configuration is completely ignored.

Remove the duplicate hardcoded definition:

 load_dotenv()
 JWT_LIFETIME_SECONDS = int(os.getenv("JWT_LIFETIME_SECONDS", "86400"))
 
-# JWT configuration
-JWT_LIFETIME_SECONDS = 86400  # 24 hours
-
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)

46-46: Address the MongoDB URI logging security concern.

This line logs self.mongo_url which may contain embedded credentials from MONGODB_URI. This security issue was flagged in a previous review but remains unresolved.

Based on learnings from past reviews, consider logging only the database names:

-        logger.info(f"MyceliaSyncService initialized: {self.mongo_url}, Mycelia DB: {self.mycelia_db}, Chronicle DB: {self.chronicle_db}")
+        logger.info(
+            "MyceliaSyncService initialized: Mycelia DB=%s, Chronicle DB=%s",
+            self.mycelia_db,
+            self.chronicle_db,
+        )
extras/speaker-recognition/charts/templates/webui-deployment.yaml (1)

29-33: Duplicate concern: chronicle-config and chronicle-secrets resources not defined.

This deployment references chronicle-config ConfigMap and chronicle-secrets Secret, but these resources are not defined in the Helm chart templates. This is the same issue flagged in the past review for backends/charts/advanced-backend/templates/workers-deployment.yaml.

backends/charts/webui/templates/deployment.yaml (1)

25-29: Duplicate concern: chronicle-config and chronicle-secrets resources not defined.

This deployment references chronicle-config ConfigMap and chronicle-secrets Secret. As flagged in previous reviews, these resources are not defined in the Helm chart templates and need to be created.

backends/charts/advanced-backend/templates/deployment.yaml (2)

26-30: Duplicate concern: chronicle-config and chronicle-secrets resources not defined.

The main container references chronicle-config ConfigMap and chronicle-secrets Secret. These resources need to be defined in the Helm chart templates.


71-75: Duplicate concern: chronicle-config and chronicle-secrets resources not defined.

The workers sidecar also references chronicle-config ConfigMap and chronicle-secrets Secret. These resources need to be defined in the Helm chart templates.

backends/charts/advanced-backend/templates/workers-deployment.yaml (1)

25-29: Duplicate concern: chronicle-config and chronicle-secrets resources not defined.

As previously flagged in past reviews, these ConfigMap and Secret resources are not defined in the Helm chart templates. The pods will fail to start until these resources are created.

README-K8S.md (1)

270-271: Fix directory reference after git clone.

The repository is cloned as chronicle but the next command attempts to cd friend-lite, which will fail with "directory not found".

   git clone --recursive https://github.com/chronicle-ai/chronicle.git
-  cd friend-lite
+  cd chronicle
🧹 Nitpick comments (5)
backends/advanced/webui/tsconfig.json (1)

19-19: Reconsider disabling noImplicitAny for better type safety.

Setting noImplicitAny: false while keeping strict: true creates an inconsistent type checking configuration. This allows implicit any types, which can hide type-related bugs and reduce the benefits of TypeScript's static type checking.

If this was added to work around existing type errors, consider addressing those errors directly or using explicit any annotations where truly needed. This provides better code maintainability and catches more potential issues at compile time.

Note: This change appears unrelated to the Chronicle rebranding. Was it intentionally included in this PR?

scripts/generate-k8s-configs.py (1)

33-33: Remove extraneous f-string prefixes.

Lines 33 and 53 use f-string prefixes without any placeholders. These should be regular strings for cleaner code.

Apply this diff:

-        f.write(f"  name: chronicle-config\n")
+        f.write("  name: chronicle-config\n")
-        f.write(f"  name: chronicle-secrets\n")
+        f.write("  name: chronicle-secrets\n")

Also applies to: 53-53

extras/speaker-recognition/charts/templates/speaker-deployment.yaml (1)

35-39: Consider templating the configMapRef for consistency.

The configMapRef is hardcoded to chronicle-config while the secretRef on line 39 uses Helm templating with a fallback pattern. This inconsistency could cause issues if the ConfigMap is named differently across environments.

Consider aligning with the secretRef pattern:

          envFrom:
            - configMapRef:
-               name: chronicle-config
+               name: {{ .Values.config.name | default "chronicle-config" }}
            - secretRef:
                name: {{ .Values.secrets.name | default (printf "%s-secrets" .Release.Name) }}
backends/charts/webui/Chart.yaml (1)

10-12: Update repository URLs to match Chronicle branding.

The sources and home URLs still reference the old BasedHardware/Friend repository, while the PR is renaming the project to Chronicle. Based on the changes in README-K8S.md (line 270), the new repository URL appears to be github.com/chronicle-ai/chronicle.

 sources:
-  - https://github.com/BasedHardware/Friend
-home: https://github.com/BasedHardware/Friend
+  - https://github.com/chronicle-ai/chronicle
+home: https://github.com/chronicle-ai/chronicle
backends/advanced/tests/test_conversation_models.py (1)

219-221: Consider adding a test for FRIEND_LITE backward compatibility.

Since FRIEND_LITE was kept as a legacy enum value for backward compatibility with existing database records, consider adding a test to verify that MemoryProvider.FRIEND_LITE still works correctly. This ensures the backward compatibility guarantee is maintained.

def test_legacy_friend_lite_provider(self):
    """Test that legacy FRIEND_LITE provider still works for backward compatibility."""
    # Verify enum value exists and works
    assert MemoryProvider.FRIEND_LITE == "friend_lite"
    
    # Verify it can be used in MemoryVersion
    version = MemoryVersion(
        version_id="legacy-v1",
        memory_count=1,
        transcript_version_id="v1",
        provider=MemoryProvider.FRIEND_LITE,
        created_at=datetime.now()
    )
    assert version.provider == MemoryProvider.FRIEND_LITE
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dededcd and 49323e7.

⛔ Files ignored due to path filters (1)
  • backends/advanced/webui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (107)
  • .env.template (5 hunks)
  • CLAUDE.md (8 hunks)
  • Docs/features.md (3 hunks)
  • Docs/getting-started.md (7 hunks)
  • Docs/init-system.md (3 hunks)
  • Docs/ports-and-access.md (1 hunks)
  • Makefile (9 hunks)
  • README-K8S.md (10 hunks)
  • README.md (1 hunks)
  • app/README.md (7 hunks)
  • app/app.json (1 hunks)
  • backends/README.md (1 hunks)
  • backends/advanced/.env.template (3 hunks)
  • backends/advanced/Docs/HTTPS_SETUP.md (3 hunks)
  • backends/advanced/Docs/README.md (1 hunks)
  • backends/advanced/Docs/UI.md (1 hunks)
  • backends/advanced/Docs/architecture.md (2 hunks)
  • backends/advanced/Docs/auth.md (2 hunks)
  • backends/advanced/Docs/memories.md (4 hunks)
  • backends/advanced/Docs/quickstart.md (7 hunks)
  • backends/advanced/docker-compose-test.yml (7 hunks)
  • backends/advanced/docker-compose.yml (6 hunks)
  • backends/advanced/init-https.sh (3 hunks)
  • backends/advanced/init.py (7 hunks)
  • backends/advanced/scripts/create_mycelia_api_key.py (2 hunks)
  • backends/advanced/scripts/sync_friendlite_mycelia.py (12 hunks)
  • backends/advanced/setup-https.sh (2 hunks)
  • backends/advanced/src/advanced_omi_backend/app_config.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/app_factory.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/auth.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/chat_service.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/config.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/database.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/models/conversation.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py (2 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py (5 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py (4 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (8 hunks)
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (3 hunks)
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (10 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py (1 hunks)
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2 hunks)
  • backends/advanced/ssl/generate-ssl.sh (1 hunks)
  • backends/advanced/start-k8s.sh (1 hunks)
  • backends/advanced/start-workers.sh (1 hunks)
  • backends/advanced/start.sh (1 hunks)
  • backends/advanced/tests/test_conversation_models.py (6 hunks)
  • backends/advanced/tests/test_integration.py (2 hunks)
  • backends/advanced/upload_files.py (3 hunks)
  • backends/advanced/webui/README.md (1 hunks)
  • backends/advanced/webui/package.json (3 hunks)
  • backends/advanced/webui/src/components/layout/Layout.tsx (2 hunks)
  • backends/advanced/webui/src/pages/LoginPage.tsx (1 hunks)
  • backends/advanced/webui/src/pages/Memories.tsx (2 hunks)
  • backends/advanced/webui/src/pages/MemoriesRouter.tsx (2 hunks)
  • backends/advanced/webui/src/pages/System.tsx (1 hunks)
  • backends/advanced/webui/tsconfig.json (1 hunks)
  • backends/charts/advanced-backend/Chart.yaml (1 hunks)
  • backends/charts/advanced-backend/templates/deployment.yaml (2 hunks)
  • backends/charts/advanced-backend/templates/workers-deployment.yaml (1 hunks)
  • backends/charts/advanced-backend/values.yaml (1 hunks)
  • backends/charts/webui/Chart.yaml (1 hunks)
  • backends/charts/webui/templates/deployment.yaml (1 hunks)
  • backends/charts/webui/values.yaml (1 hunks)
  • extras/asr-services/README.md (2 hunks)
  • extras/asr-services/quickstart.md (2 hunks)
  • extras/asr-services/tests/test_parakeet_service.py (1 hunks)
  • extras/havpe-relay/README.md (1 hunks)
  • extras/havpe-relay/main.py (1 hunks)
  • extras/local-omi-bt/connect-omi.py (2 hunks)
  • extras/openmemory-mcp/README.md (9 hunks)
  • extras/openmemory-mcp/run.sh (2 hunks)
  • extras/openmemory-mcp/test_standalone.py (1 hunks)
  • extras/speaker-omni-experimental/README.md (3 hunks)
  • extras/speaker-recognition/charts/templates/speaker-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/templates/webui-deployment.yaml (1 hunks)
  • extras/speaker-recognition/charts/values.yaml (1 hunks)
  • extras/speaker-recognition/init.py (1 hunks)
  • extras/speaker-recognition/quickstart.md (1 hunks)
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py (1 hunks)
  • extras/speaker-recognition/ssl/generate-ssl.sh (1 hunks)
  • extras/speaker-recognition/tests/test_speaker_service_integration.py (1 hunks)
  • k8s-manifests/cross-namespace-rbac.yaml (1 hunks)
  • quickstart.md (6 hunks)
  • run-test.sh (2 hunks)
  • scripts/generate-k8s-configs.py (4 hunks)
  • scripts/k8s/cluster-status.sh (1 hunks)
  • scripts/k8s/load-env.sh (1 hunks)
⛔ Files not processed due to max files limit (17)
  • scripts/manage-audio-files.sh
  • services.py
  • skaffold.yaml
  • status.py
  • tests/.env.test
  • tests/Makefile
  • tests/README.md
  • tests/TESTING_USER_GUIDE.md
  • tests/browser/browser_auth.robot
  • tests/infrastructure/infra_tests.robot
  • tests/libs/audio_stream_library.py
  • tests/resources/websocket_keywords.robot
  • tests/setup/setup_keywords.robot
  • tests/setup/test_env.py
  • tests/setup/test_manager_keywords.robot
  • tests/tags.md
  • wizard.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Use uv run python command instead of direct python or python3 for executing Python scripts
Use Black formatter with 100-character line length for Python code style
Use isort for Python import organization
NEVER import modules in the middle of functions or files - ALL imports must be at the top of the file after the docstring
Group imports in order: standard library, third-party, local imports
Use lazy imports sparingly and only when absolutely necessary for circular import issues in Python
Always raise errors explicitly in Python code, never silently ignore errors or failures
Use explicit error handling with proper exceptions in Python rather than silent failures
Understand data structures and research input/response or class structure instead of adding defensive hasattr() checks in Python

Files:

  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/init.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • extras/openmemory-mcp/test_standalone.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • extras/havpe-relay/main.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • extras/speaker-recognition/init.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/upload_files.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • extras/speaker-recognition/tests/test_speaker_service_integration.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • scripts/generate-k8s-configs.py
  • backends/advanced/tests/test_integration.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/src/advanced_omi_backend/auth.py
🧠 Learnings (2)
📚 Learning: 2025-12-07T18:52:48.881Z
Learnt from: CR
Repo: chronicler-ai/chronicle PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-07T18:52:48.881Z
Learning: Check backends/advanced/Docs for up-to-date information on advanced backend development

Applied to files:

  • backends/advanced/Docs/README.md
  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/Docs/HTTPS_SETUP.md
  • backends/advanced/upload_files.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
📚 Learning: 2025-12-08T23:52:34.959Z
Learnt from: AnkushMalaker
Repo: chronicler-ai/chronicle PR: 178
File: backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py:218-223
Timestamp: 2025-12-08T23:52:34.959Z
Learning: In Python code (chronicle project), prefer logging.exception() inside except blocks to automatically log the full stack trace. When re-raising exceptions, always chain with 'raise ... from e' to preserve the original context; use 'raise ... from None' only if you explicitly want to suppress the context. This improves debuggability across Python files.

Applied to files:

  • backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.py
  • backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py
  • backends/advanced/src/advanced_omi_backend/services/__init__.py
  • backends/advanced/init.py
  • extras/speaker-recognition/src/simple_speaker_recognition/__init__.py
  • backends/advanced/src/advanced_omi_backend/middleware/app_middleware.py
  • extras/openmemory-mcp/test_standalone.py
  • extras/local-omi-bt/connect-omi.py
  • backends/advanced/src/advanced_omi_backend/controllers/system_controller.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py
  • backends/advanced/src/advanced_omi_backend/app_config.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.py
  • backends/advanced/src/advanced_omi_backend/config.py
  • extras/havpe-relay/main.py
  • backends/advanced/tests/test_conversation_models.py
  • backends/advanced/src/advanced_omi_backend/chat_service.py
  • backends/advanced/src/advanced_omi_backend/services/memory/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.py
  • extras/speaker-recognition/init.py
  • backends/advanced/src/advanced_omi_backend/models/conversation.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/__init__.py
  • backends/advanced/src/advanced_omi_backend/database.py
  • backends/advanced/scripts/create_mycelia_api_key.py
  • backends/advanced/src/advanced_omi_backend/services/memory/config.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py
  • extras/asr-services/tests/test_parakeet_service.py
  • backends/advanced/src/advanced_omi_backend/models/__init__.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
  • backends/advanced/src/advanced_omi_backend/models/audio_file.py
  • backends/advanced/upload_files.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
  • extras/speaker-recognition/tests/test_speaker_service_integration.py
  • backends/advanced/src/advanced_omi_backend/routers/api_router.py
  • backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
  • backends/advanced/src/advanced_omi_backend/workers/conversation_jobs.py
  • backends/advanced/src/advanced_omi_backend/clients/__init__.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.py
  • backends/advanced/scripts/sync_friendlite_mycelia.py
  • backends/advanced/src/advanced_omi_backend/routers/modules/user_routes.py
  • backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py
  • scripts/generate-k8s-configs.py
  • backends/advanced/tests/test_integration.py
  • backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py
  • backends/advanced/src/advanced_omi_backend/app_factory.py
  • backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py
  • backends/advanced/src/advanced_omi_backend/auth.py
🧬 Code graph analysis (12)
run-test.sh (3)
backends/advanced/setup-https.sh (2)
  • print_info (15-17)
  • print_error (27-29)
extras/speaker-recognition/run-test.sh (2)
  • print_info (34-36)
  • print_error (46-48)
backends/advanced/run-test.sh (2)
  • print_info (16-18)
  • print_error (28-30)
backends/advanced/setup-https.sh (2)
backends/advanced/init.py (1)
  • print_header (36-45)
extras/speaker-recognition/init.py (1)
  • print_header (31-40)
backends/advanced/src/advanced_omi_backend/controllers/system_controller.py (1)
backends/advanced/src/advanced_omi_backend/routers/modules/system_routes.py (1)
  • get_memory_provider (134-136)
backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/tests/test_conversation_models.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (2)
  • MemoryProvider (29-34)
  • add_memory_version (261-289)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py (5)
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (1)
  • test_connection (479-504)
backends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.py (1)
  • test_connection (416-428)
backends/advanced/src/advanced_omi_backend/services/memory/providers/chronicle.py (1)
  • test_connection (334-346)
backends/advanced/src/advanced_omi_backend/services/memory/providers/vector_stores.py (1)
  • test_connection (299-309)
backends/advanced/src/advanced_omi_backend/services/memory/base.py (3)
  • test_connection (233-239)
  • test_connection (331-337)
  • test_connection (464-470)
backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py (2)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)
backends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (2)
backends/advanced/src/advanced_omi_backend/models/conversation.py (1)
  • MemoryProvider (29-34)
backends/advanced/src/advanced_omi_backend/services/memory/config.py (1)
  • MemoryProvider (35-39)
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.py (1)
backends/advanced/src/advanced_omi_backend/models/user.py (1)
  • user_id (71-73)
backends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.py (1)
backends/advanced/src/advanced_omi_backend/services/memory/providers/chronicle.py (1)
  • MemoryService (23-705)
🪛 dotenv-linter (4.0.0)
.env.template

[warning] 14-14: [UnorderedKey] The APPLICATION_NAMESPACE key should go before the INFRASTRUCTURE_NAMESPACE key

(UnorderedKey)


[warning] 108-108: [UnorderedKey] The MONGODB_K8S_URI key should go before the MONGODB_URI key

(UnorderedKey)


[warning] 128-128: [UnorderedKey] The OPENMEMORY_CLIENT_NAME key should go before the OPENMEMORY_MCP_URL key

(UnorderedKey)

🪛 LanguageTool
Docs/getting-started.md

[style] ~9-~9: For conciseness, consider replacing this expression with an adverb.
Context: ...ort "AI wearable" agents/functionality. At the moment, the basic functionalities are: - Audio...

(AT_THE_MOMENT)

CLAUDE.md

[grammar] ~7-~7: Use a hyphen to join words.
Context: ...at the very least audio capture, speaker specific transcription, memory extractio...

(QB_NEW_EN_HYPHEN)

backends/advanced/Docs/quickstart.md

[style] ~7-~7: For conciseness, consider replacing this expression with an adverb.
Context: ...ort "AI wearable" agents/functionality. At the moment, the basic functionalities are: - Audio...

(AT_THE_MOMENT)

🪛 Ruff (0.14.8)
backends/advanced/src/advanced_omi_backend/services/memory/config.py

156-156: Avoid specifying long messages outside the exception class

(TRY003)

backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py

266-266: Do not catch blind exception: Exception

(BLE001)


268-268: Use explicit conversion flag

Replace with conversion flag

(RUF010)

backends/advanced/scripts/sync_friendlite_mycelia.py

53-53: f-string without any placeholders

Remove extraneous f prefix

(F541)


163-163: f-string without any placeholders

Remove extraneous f prefix

(F541)


190-190: f-string without any placeholders

Remove extraneous f prefix

(F541)

scripts/generate-k8s-configs.py

33-33: f-string without any placeholders

Remove extraneous f prefix

(F541)


53-53: f-string without any placeholders

Remove extraneous f prefix

(F541)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build

Comment on lines +102 to +104
# Memory Provider: "chronicle" (default), "openmemory_mcp", or "mycelia"
#
# Friend-Lite (default): In-house memory system with full control
# Chronicle (default): In-house memory system with full control
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify memory provider implementation supports "chronicle" value

echo "=== Checking MemoryProvider enum/class definition ==="
ast-grep --pattern 'class MemoryProvider'
ast-grep --pattern 'CHRONICLE = $_'

echo ""
echo "=== Checking for provider string validation ==="
rg -n "chronicle|friend_lite" --type py backends/advanced/src/advanced_omi_backend/services/memory/ -C 2

echo ""
echo "=== Checking test files for provider references ==="
rg -n "MemoryProvider\.(CHRONICLE|FRIEND_LITE)" --type py backends/advanced/tests/ -C 1

Repository: chronicler-ai/chronicle

Length of output: 12868


Memory provider implementation correctly supports "chronicle" as the default value.

The memory provider implementation properly recognizes "chronicle" as a valid provider through both MemoryProvider enum definitions, validation logic, and service factory instantiation. Legacy "friend_lite" references are appropriately mapped to "chronicle" during configuration initialization with logging.

However, there is one minor inconsistency: backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py line 119 still hardcodes "source": "friend_lite" in metadata, while line 135 correctly uses "source": "chronicle". Update line 119 to be consistent with the provider change.

🤖 Prompt for AI Agents
In
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
around line 119-135, update the metadata entry at line 119 that currently
hardcodes "source": "friend_lite" to instead use "source": "chronicle" (to match
the provider mapping and the correct usage at line 135); ensure the string is
changed and any related comment/log nearby is consistent with the chronicle
provider name.

set -e

# Initialize Friend-Lite Advanced Backend with HTTPS proxy
# Initialize Chronicle Advanced Backend with HTTPS proxy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the file to confirm the changes
echo "=== Checking file: backends/advanced/init-https.sh ==="
if [ -f "backends/advanced/init-https.sh" ]; then
    wc -l "backends/advanced/init-https.sh"
    echo -e "\n--- Lines 1-10 ---"
    head -10 "backends/advanced/init-https.sh"
    echo -e "\n--- Lines 20-30 ---"
    sed -n '20,30p' "backends/advanced/init-https.sh"
    echo -e "\n--- Lines 95-105 ---"
    sed -n '95,105p' "backends/advanced/init-https.sh"
else
    echo "File not found!"
fi

echo -e "\n=== Searching for remaining 'Friend-Lite' references ==="
# Case-insensitive search for "friend-lite" or "friendlite" in the codebase
rg -i 'friend-?lite' --type sh --type yaml --type md --type js --type ts --type py --type json 2>/dev/null | head -50 || echo "No 'Friend-Lite' references found"

Repository: chronicler-ai/chronicle

Length of output: 5351


⚠️ Approve init-https.sh changes, but comprehensive rebranding remains incomplete.

The updates to init-https.sh (lines 4, 26, 101) correctly rebrand from "Friend-Lite" to "Chronicle" with no functional changes. However, verification discovered extensive remaining "Friend-Lite" references throughout the codebase requiring attention:

Remaining references found in:

  • Documentation: quickstart.md, README-K8S.md, backends/advanced/SETUP_SCRIPTS.md, backends/advanced/README.md
  • App config: app/app.json, app/package.json, app/package-lock.json
  • App source code: TypeScript imports of friend-lite-react-native library
  • Backend Python code: Controllers, database config (default MONGODB_DATABASE: "friend-lite"), config files, models, routers—including conditional checks for ("friend-lite", "friend_lite")

Consider a comprehensive rebranding pass across all affected subsystems rather than file-by-file updates.

🤖 Prompt for AI Agents
In backends/advanced/init-https.sh around lines 4, 26 and 101 you rebranded
Friend-Lite to Chronicle but many occurrences remain elsewhere; perform a
project-wide search for "Friend-Lite", "friend-lite", and "friend_lite" and
replace them consistently with the new branding ("Chronicle" or "chronicle" as
appropriate), update docs (quickstart.md, README-K8S.md,
backends/advanced/SETUP_SCRIPTS.md, backends/advanced/README.md), app
config/package files (app/app.json, app/package.json, app/package-lock.json), TS
imports (replace or alias friend-lite-react-native to the new package name or
add compatibility aliases), backend Python defaults/configs (change
MONGODB_DATABASE default and any hardcoded strings), and adjust conditional
checks that look for ("friend-lite", "friend_lite") to include or migrate to
"chronicle"/"chronicle_db" as needed; run tests, linting, and a full search
again to ensure no residual references remain and update any deployment scripts
or README mentions accordingly.

"clsx": "^2.0.0",
"d3": "^7.8.5",
"frappe-gantt": "^0.6.1",
"frappe-gantt": "^1.0.4",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find backends/advanced/webui/src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \) -exec grep -l "gantt\|Gantt" {} \; 2>/dev/null || echo "No results found"

Repository: chronicler-ai/chronicle

Length of output: 237


🏁 Script executed:

cd backends/advanced/webui && grep -r "frappe-gantt" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" src/ 2>/dev/null || echo "No frappe-gantt imports found"

Repository: chronicler-ai/chronicle

Length of output: 133


🏁 Script executed:

cd backends/advanced/webui && grep -r "import.*gantt\|require.*gantt" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" src/ 2>/dev/null || echo "No gantt imports found"

Repository: chronicler-ai/chronicle

Length of output: 133


🏁 Script executed:

cat -n backends/advanced/webui/src/pages/FrappeGanttTimeline.tsx

Repository: chronicler-ai/chronicle

Length of output: 30842


🏁 Script executed:

cat -n backends/advanced/webui/src/pages/TimelineRouter.tsx

Repository: chronicler-ai/chronicle

Length of output: 3145


🏁 Script executed:

wc -l backends/advanced/webui/src/pages/FrappeGanttTimeline.tsx

Repository: chronicler-ai/chronicle

Length of output: 128


Verify frappe-gantt upgrade compatibility before release.

The frappe-gantt dependency has been upgraded from ^0.6.1 to ^1.0.4, which is a complete rewrite of the framework with many enhancements, bug fixes, and a fresh UI. This is not a routine patch update. The API has been overhauled—users previously couldn't change the Gantt chart easily after rendering, but now there is a complete API for all needs.

The FrappeGanttTimeline component actively uses Gantt features that may be affected by this migration:

  • Dynamic view mode changes (line 353 dependency in FrappeGanttTimeline.tsx)
  • Custom popup HTML rendering (lines 263-292)
  • Scroll and wheel event handling (lines 356-441)
  • DOM manipulation on chart elements (lines 297-341)

Reported issues include jittery scroll behavior in v1.0.0 compared to v0.6.1, and grid computation errors ("Cannot destructure property 'x'") in recent versions.

Before release:

  1. Test all Gantt chart interactions (view mode changes, scrolling, zooming)
  2. Verify the custom popup HTML still renders correctly
  3. Test in the UI with both demo and real data to ensure no visual regressions

Comment on lines +13 to +14
from chronicle.bluetooth import listen_to_omi, print_devices
from chronicle.decoder import OmiOpusDecoder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find chronicle and friend_lite directories/modules
fd -t d "chronicle" | head -20
fd -t d "friend_lite" | head -20

# List files related to these packages
fd -t f "(chronicle|friend_lite)" | grep -E "\.(py|txt)$" | head -20

# Check if they're in a specific location
git ls-files | grep -E "(chronicle|friend_lite)" | head -30

Repository: chronicler-ai/chronicle

Length of output: 230


🏁 Script executed:

#!/bin/bash

# Find the connect-omi.py file
fd -t f "connect-omi.py"

# Find chronicle package structure
fd -t f "chronicle" | grep -E "__init__|bluetooth|decoder" | head -20

# List all Python files in extras directory
find extras -type f -name "*.py" 2>/dev/null | head -30

Repository: chronicler-ai/chronicle

Length of output: 1879


🏁 Script executed:

#!/bin/bash

# Read the target file
cat -n extras/local-omi-bt/connect-omi.py

# Search for chronicle module in the codebase
fd -t d "chronicle" -type d

# Look for chronicle package files
fd -t f "chronicle" | grep -E "\.py$|__pycache__" | grep -v ".pyc" | head -30

# Check if chronicle is a local package
ls -la 2>/dev/null | grep -i chronicle
find . -maxdepth 3 -type d -name "chronicle" 2>/dev/null

Repository: chronicler-ai/chronicle

Length of output: 7241


🏁 Script executed:

#!/bin/bash

# Find the chronicle package - search more broadly
find . -type f -name "__init__.py" | xargs grep -l "listen_to_omi\|OmiOpusDecoder" 2>/dev/null

# Search for bluetooth and decoder modules
find . -type f \( -name "bluetooth.py" -o -name "decoder.py" \) 2>/dev/null | grep chronicle

# Look for chronicle directory
find . -type d -name "chronicle" 2>/dev/null

# Search for these functions/classes in all Python files
rg "def listen_to_omi|class OmiOpusDecoder|def print_devices" --type py | head -20

Repository: chronicler-ai/chronicle

Length of output: 49


🏁 Script executed:

#!/bin/bash

# Check if chronicle is an external package dependency
find . -type f \( -name "requirements.txt" -o -name "pyproject.toml" -o -name "setup.py" -o -name "poetry.lock" -o -name "Pipfile" \) | head -10

# List contents if found
for file in $(find . -type f \( -name "requirements.txt" -o -name "pyproject.toml" -o -name "setup.py" \) 2>/dev/null | head -5); do
    echo "=== $file ==="
    cat "$file" | head -50
done

# Search for any chronicle imports in the codebase
rg "from chronicle|import chronicle" --type py | head -30

# Check sys.path modifications in the file
grep -n "sys.path" extras/local-omi-bt/connect-omi.py

Repository: chronicler-ai/chronicle

Length of output: 4331


🏁 Script executed:

#!/bin/bash

# Check the requirements.txt for the local-omi-bt directory
cat extras/local-omi-bt/requirements.txt

# Look for any chronicle-related packages
rg "chronicle" --type py extras/

# Check if chronicle is defined locally in the extras/local-omi-bt directory
ls -la extras/local-omi-bt/

# Search for Python path setup or local imports
find extras/local-omi-bt -type f -name "*.py" | xargs head -30

Repository: chronicler-ai/chronicle

Length of output: 2751


🏁 Script executed:

#!/bin/bash

# Search for friend_lite module or friend-lite-sdk references
rg "friend.lite\|friend_lite" --type py | head -30

# Look for any Python package that might expose chronicle
rg "from friend_lite|import friend_lite" --type py | head -30

# Check if there's a chronicle directory at the root or in a common location
find . -maxdepth 4 -type d -name "chronicle" 2>/dev/null

# Look for setup files that might define chronicle as a local package
find . -type f -name "setup.py" -o -name "pyproject.toml" | xargs grep -l "chronicle" 2>/dev/null

# Check the main root pyproject.toml or setup.py
ls -la | grep -E "pyproject|setup"
cat pyproject.toml 2>/dev/null | head -80

Repository: chronicler-ai/chronicle

Length of output: 266


🏁 Script executed:

#!/bin/bash

# This is interesting - found friend_lite.decoder import in websocket_controller.py
# Let's check if friend_lite is a local package or external

# Search for friend_lite module definition
find . -type d -name "friend_lite" 2>/dev/null

# Search for where friend_lite is imported from
rg "from friend_lite|import friend_lite" --type py -A 2 -B 2 | head -50

# Check all uses of friend_lite in the codebase
rg "friend_lite\." --type py | head -30

# Look for chronicle module definition - more comprehensive search
rg "from chronicle\.|import chronicle" --type py

# Check if chronicle is being aliased or re-exported
rg "chronicle\s*=" --type py | head -20

# Look in the entire codebase for where chronicle module might be
find . -type f -name "*.py" -exec grep -l "chronicle.bluetooth\|chronicle.decoder" {} \;

Repository: chronicler-ai/chronicle

Length of output: 960


🏁 Script executed:

#!/bin/bash

# Check the websocket_controller to see what it's doing with OmiOpusDecoder
cat -n backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py | head -40

# See if there's any __init__.py that might be defining chronicle as an alias
find . -type f -name "__init__.py" | xargs grep -l "friend_lite\|chronicle" 2>/dev/null

# Check if there's any module aliasing happening
rg "as chronicle|import.*friend_lite.*as chronicle" --type py

# Look at the root level structure
ls -la

# Check if there's a chronicle module or package definition anywhere
find . -name "chronicle.py" -o -path "*/chronicle/__init__.py" 2>/dev/null

# Check pyproject.toml at root if it exists
cat pyproject.toml 2>/dev/null || echo "No root pyproject.toml"

# Check for any setup.cfg or other config
ls -la setup.* pyproject.* 2>/dev/null || echo "No setup/pyproject files at root"

Repository: chronicler-ai/chronicle

Length of output: 4214


🏁 Script executed:

#!/bin/bash

# Critical finding: the requirements.txt has friend-lite-sdk but the code imports from chronicle
# Let's verify this discrepancy

# Check if friend-lite-sdk provides a chronicle module or if chronicle is an alias
rg "friend.lite\|friend_lite" --type py -l | head -10

# Let's look at what the actual backend is using
cat -n backends/advanced/src/advanced_omi_backend/controllers/websocket_controller.py | sed -n '1,50p'

# Check the decoder usage in the backend
rg "OmiOpusDecoder" --type py -B 3 -A 5 | head -50

# Verify all imports from friend_lite or chronicle in the codebase
rg "^from (friend_lite|chronicle)" --type py

# See if there's any __init__.py in extras/local-omi-bt that might set up imports
ls -la extras/local-omi-bt/
cat extras/local-omi-bt/__init__.py 2>/dev/null || echo "No __init__.py"

# Check if there's a conftest.py or any pytest configuration that might alias modules
find . -name "conftest.py" -o -name "pytest.ini" | xargs cat 2>/dev/null | head -30

Repository: chronicler-ai/chronicle

Length of output: 5783


🏁 Script executed:

#!/bin/bash

# Critical issue found! Let's verify the import discrepancy
# The file imports from 'chronicle' but requirements.txt lists 'friend-lite-sdk'

# Check what friend-lite-sdk actually provides
rg "friend.lite" --type py | grep -E "(import|from)" | sort -u

# Check all decoder imports in the codebase
rg "\.decoder import|from.*decoder" --type py -o | sort -u

# Specifically check what OmiOpusDecoder is available from
rg "OmiOpusDecoder" --type py -B 2 | grep -E "^[^-]*:.*from|^[^-]*:.*import" | sort -u

# Check if there's a chronicle alias somewhere
rg "chronicle\s*=" --type py

# Look at the pyproject.toml in the advanced backend
cat backends/advanced/pyproject.toml | grep -A 30 "dependencies"

# Check if friend-lite-sdk might provide chronicle as an alias
python3 -c "import sys; sys.path.append('.'); from friend_lite import decoder; print(decoder.__file__)" 2>/dev/null || echo "friend_lite not available"

Repository: chronicler-ai/chronicle

Length of output: 2978


🏁 Script executed:

#!/bin/bash

# Let's verify if the functions listen_to_omi and print_devices exist anywhere
rg "def listen_to_omi|def print_devices" --type py

# Check what friend_lite actually exports
rg "friend_lite" --type py -B 3 -A 3 | head -60

# Look at the omi.decoder and friend_lite.decoder usage
rg "\.decode_packet\(|OmiOpusDecoder" --type py -B 2 -A 2 | head -80

# Check if there's any module aliasing in __init__ files
find . -name "__init__.py" -exec grep -H "chronicle\|friend_lite" {} \; 2>/dev/null

# Final check: does chronicle module exist in the repo?
find . -path "*/chronicle/__init__.py" -o -path "*/chronicle/bluetooth.py" -o -path "*/chronicle/decoder.py" 2>/dev/null

Repository: chronicler-ai/chronicle

Length of output: 10953


🏁 Script executed:

#!/bin/bash

# Final verification - check if listen_to_omi exists in omi or friend_lite modules
rg "def listen_to_omi" --type py

# Check omi.bluetooth references
rg "from omi.bluetooth|import omi.bluetooth" --type py

# Check if the functions are defined at all
rg "listen_to_omi|print_devices" --type py | grep "def " | head -20

# Verify the requirements for connect-omi.py match other backends
echo "=== connect-omi.py requirements ===" 
cat extras/local-omi-bt/requirements.txt

echo "=== simple backend pyproject.toml ===" 
grep "omi-sdk\|friend-lite" backends/simple/pyproject.toml || echo "Not found in simple"

echo "=== example-satellite pyproject.toml ===" 
cat backends/other-backends/example-satellite/pyproject.toml | grep -A 20 "dependencies"

Repository: chronicler-ai/chronicle

Length of output: 772


🏁 Script executed:

#!/bin/bash

# Check if print_devices exists or needs to be defined
rg "print_devices" --type py -B 3 -A 5

# Confirm omi.bluetooth exports
rg "from omi.bluetooth|import.*omi.bluetooth" --type py -A 2

# Check the full signature of listen_to_omi in omi
rg "def listen_to_omi" --type py -A 10

# Final confirmation: does chronicle module exist anywhere?
find . -path "*/chronicle*" -type f 2>/dev/null

Repository: chronicler-ai/chronicle

Length of output: 1057


Fix import statements to use correct SDK modules.

The imports on lines 13-14 reference non-existent chronicle.bluetooth and chronicle.decoder modules. The codebase does not contain these modules. Change imports to use the appropriate SDK:

  • from omi.bluetooth import listen_to_omi (available in omi-sdk)
  • from omi.decoder import OmiOpusDecoder (available in omi-sdk)

Alternatively, if using friend-lite-sdk (as listed in requirements.txt), use from friend_lite.decoder import OmiOpusDecoder. The print_devices function does not exist in any SDK and is not used in this file—remove this import.

For the comment on line 52 regarding list_devices(), the locally-defined function can remain, but clarify whether it should be added to omi-sdk or friend-lite-sdk rather than a non-existent chronicle SDK.

🤖 Prompt for AI Agents
In extras/local-omi-bt/connect-omi.py around lines 13-14 (and note the comment
at line 52), the current imports reference non-existent chronicle packages;
replace them with the correct SDK modules: import listen_to_omi from
omi.bluetooth and OmiOpusDecoder from omi.decoder (or if this project uses
friend-lite-sdk, import OmiOpusDecoder from friend_lite.decoder); remove the
unused print_devices import entirely; keep the locally-defined list_devices()
function as-is but update the comment at line 52 to state that list_devices is
local or should be added to the omi-sdk/friend-lite-sdk rather than referencing
a non-existent chronicle SDK.

@thestumonkey
Copy link
Contributor Author

Merging as requested changes implemented.

@AnkushMalaker
Copy link
Collaborator

Kindly dont merge if there's anything unreviewed, even new changes need review.

@thestumonkey thestumonkey merged commit ab506dc into SimpleOpenSoftware:main Dec 16, 2025
0 of 6 checks passed
@AnkushMalaker
Copy link
Collaborator

?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants