-
Notifications
You must be signed in to change notification settings - Fork 24
name change to chronicle #174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
name change to chronicle #174
Conversation
Tweaks to get all memory providers working
33efa1a to
dc5ec6f
Compare
There was a problem hiding this 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_URLandMYCELIA_DBpointing tomycelia-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 themyceliaprofile is explicitly enabled.Recommended fixes:
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.myceliaor a separate compose override file.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_testThen run:
docker-compose -f docker-compose-test.yml -f docker-compose-test.mycelia.yml upwhen Mycelia is needed.Also applies to: 151-152
extras/havpe-relay/main.py (2)
333-333: Moveimport timeto 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 randomThen 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 bareexceptwith explicit exception handling.The bare
except: passsilently 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 messageThis makes the caught exception explicit. Alternatively, if you want to be more specific about network errors, catch
httpx.ResponseErrororjson.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.
datetimeis 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.
asynciois 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 pathThe 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 underbackends/advanced/src/..., so the bullet../../backends/advanced-backend/may not match the actual directory name. If the real path isbackends/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: Uselogging.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 eFor 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 withraise ... from eto 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: Uselogging.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 withraise ... 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 eApply 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 withraise ... from eto 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
_initializedon 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 keynamelabel updated; verify no callers depend on old literalChanging
"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 timebackends/advanced/src/advanced_omi_backend/auth.py (1)
123-132: Avoid duplicated JWT lifetime and reuse a single timestampThe Chronicle payload shape looks fine, but you’re now hard‑coding the 24‑hour lifetime separately from
JWT_LIFETIME_SECONDSand callingdatetime.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"andaud="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 actualMemoryProvideroptionsDocstring step 3 now mentions “chronicle or openmemory_mcp”, but the
MemoryProviderenum also includesMYCELIA. 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 toCHRONICLEis correct; avoid silently swallowing provider detection errorsThe new default of
conversation_model.MemoryProvider.CHRONICLEmatches the rebranded enum and the config default, so the functional change looks good. However, the surroundingtry/except Exception: passcompletely hides any issues inget_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()inexceptblocks. 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 -sbackends/advanced/Docs/auth.md (1)
5-6: Auth docs branding + Mongo DB name are correct; update remaining service namesThe overview now correctly describes Chronicle’s auth system, and the Mongo shell command targeting the
chronicledatabase aligns with the backend rename.However, the surrounding debug commands still reference the old
friend-backendservice name:
- Line 263:
docker compose logs friend-backend | grep -i admin- Line 275:
docker compose logs friend-backend | grep -i authIf the service was renamed to
chronicle-backendindocker-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 authAlso applies to: 260-279
extras/local-omi-bt/connect-omi.py (1)
52-60: Consider upstreaminglist_deviceshelper or clarifying the TODOThe
list_deviceshelper plus the# Add this to chronicle sdkcomment 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 SDKThis module imports
OmiOpusDecoderfromfriend_lite.decoderwhile other parts of the repo (e.g.,extras/local-omi-bt/connect-omi.py) import it fromchronicle.decoder. Aligning to thechronicle.decodersource maintains consistency across the codebase:-from friend_lite.decoder import OmiOpusDecoder +from chronicle.decoder import OmiOpusDecoderextras/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 remainingfriend-backendmentionTitle and intro now clearly reference Chronicle, which fits the PR’s goal. Elsewhere in this file,
docker compose logs friend-backendis 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 namingRenaming 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-backendservice—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: Bareexceptclause 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 Falsebackends/charts/advanced-backend/Chart.yaml (1)
3-12: Consider aligning Helm chart metadata URLs with Chronicle repoThe description/keywords are updated to Chronicle, but
sources/homestill point to the BasedHardware/Friend repo. If this chart is now primarily maintained inchronicler-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 commentThe path update to
chronicle-react-nativeis appropriate for the rebrand, assuming it exportsOmiConnectionandOmiDevicewith 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: Preferlogger.exceptionin exception handlers for better diagnosticsIn the DB and connection exception handlers you currently log with
logger.error, which loses stack traces. For easier debugging, consider switching tologger.exceptioninside 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 layoutThe README still references
friend-backendin Docker Compose commands and mentions awebui-reactdirectory for manual builds, while other parts of the repo now use Chronicle/advanced-backend terminology andbackends/advanced/webui. Please verify that:
- The service name in
docker-composematches these docs (e.g.,friend-backendvsadvanced-backend/chronicle-backend), and- The manual build path (
backends/advanced/webui-reactvsbackends/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 ConfigurationErrorblock you assigndatabase = client["chronicle"]and then immediatelyraise, so the fallback assignment is never actually used; either drop the assignment or remove the bareraise(and perhaps log a warning) depending on whether you intend to recover or fail-fast._beanie_initializedis set twice (before and afterinit_beanie); you can set it only once after successful initialization to avoid confusion.- The
except Exception as ebelow only useslogger.error(...); switching tologger.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, preferraise RuntimeError("...") from e.- Also consider moving the
import os,AsyncIOMotorClient,init_beanie, model imports, andConfigurationErrorto 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 labelThe 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 tochronicle-backendis wired correctlyThe docker-compose service has been cleanly renamed to
chronicle-backend, and alldepends_onentries (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 thefriend-networkat the bottom to something likechronicle-networkfor 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_dbshould be renamed.The variable
fl_dbappears to be a leftover abbreviation from "friend_lite_db". For consistency with the Chronicle rebranding, consider renaming it tochronicle_dbor simplydb.- # 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
fprefix 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 withraise ... 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 FalseBased 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 ChronicleMemoryServiceThe 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 creationThe generic
Exceptionhandler currently logs only the message and discards the original traceback when raisingRuntimeError, 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 eBased on learnings, this aligns with the project preference for
logging.exceptionplusraise ... from e.backends/advanced/Docs/HTTPS_SETUP.md (1)
1-3: Chronicle branding looks good; verify remainingfriend-backendservice referencesThe 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-backendin the profiles and troubleshooting sections. If the Docker service name is stillfriend-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 driftThe switch of the default provider to
"chronicle"and thememory_provider_supports_thresholdflag 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
MemoryProviderenum, 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; moveos/reimports to the top of the moduleThe 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
osandreimports 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 nameThe 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-backendIf 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 impactThe default
client_name="chronicle"increate_openmemory_configand the corresponding env-based defaultOPENMEMORY_CLIENT_NAME→"chronicle"keep the OpenMemory integration consistent with the new branding and the defaultMEMORY_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 parsingMEMORY_PROVIDERor 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 guidelinesThe 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_loaderis 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
⛔ Files ignored due to path filters (1)
backends/advanced/webui/package-lock.jsonis 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: Useuv run pythoncommand instead of directpythonorpython3for 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 defensivehasattr()checks in Python
Files:
backends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pybackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/src/advanced_omi_backend/app_factory.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/scripts/create_mycelia_api_key.pyextras/havpe-relay/main.pyextras/speaker-recognition/init.pyextras/openmemory-mcp/test_standalone.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pybackends/advanced/src/advanced_omi_backend/models/job.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/service_factory.pybackends/advanced/src/advanced_omi_backend/routers/modules/client_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/tests/test_integration.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/auth.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/init.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/scripts/sync_friendlite_mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/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.tsapp/app/index.tsxapp/app/hooks/useDeviceConnection.tsapp/app/components/DeviceDetails.tsxapp/app/components/DeviceListItem.tsxapp/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__.pybackends/advanced/Docs/README.mdbackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/Docs/HTTPS_SETUP.mdbackends/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__.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pybackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/src/advanced_omi_backend/app_factory.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/scripts/create_mycelia_api_key.pyextras/havpe-relay/main.pyextras/speaker-recognition/init.pyextras/openmemory-mcp/test_standalone.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pybackends/advanced/src/advanced_omi_backend/models/job.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/service_factory.pybackends/advanced/src/advanced_omi_backend/routers/modules/client_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/tests/test_integration.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/auth.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/init.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/scripts/sync_friendlite_mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/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)
backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py
Outdated
Show resolved
Hide resolved
backends/advanced/src/advanced_omi_backend/services/memory/service_factory.py
Show resolved
Hide resolved
There was a problem hiding this 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 beNone).
_create_mycelia_api_keycan return(client_id, None)when an existing key is reused, but the annotations declareTuple[str, str]. That also flows throughsync_user_to_myceliaandsync_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: Preferlogger.exceptioninexceptblocks for full tracebacks.You already pass
exc_info=True;logger.exceptionis 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 NoneBased on learnings, this improves debuggability by always recording the full stack trace.
Also applies to: 216-218
195-211: Update CLI instructions to useuv run pythonper project guidelines.The log message shows
python create_mycelia_api_key.py, but repo guidelines preferuv run pythonfor 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.
MemoryProvidernow exposes onlyCHRONICLE,OPENMEMORY_MCP, andMYCELIA, withMemoryConfig.memory_providerdefaulting toCHRONICLE.build_memory_config_from_envlower‑casesMEMORY_PROVIDER, maps legacy"friend-lite"/"friend_lite"to"chronicle", validates againstMemoryProvider, and branches cleanly for OpenMemory MCP and Mycelia before falling through to the Chronicle config loader path.- The final log line correctly reports
Provider=Chroniclefor 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 ofget_config_loader.
from advanced_omi_backend.memory_config_loader import get_config_loaderlives insidebuild_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
⛔ Files ignored due to path filters (1)
backends/advanced/webui/package-lock.jsonis 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: Useuv run pythoncommand instead of directpythonorpython3for 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 defensivehasattr()checks in Python
Files:
backends/advanced/src/advanced_omi_backend/services/mycelia_sync.pybackends/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.pybackends/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.CHRONICLEis properly implemented and wired in the backend initialization code to ensure that settingMEMORY_PROVIDER=chroniclewill work as expected at runtime.
134-134: OPENMEMORY_CLIENT_NAME example updated for consistency.The commented example for
OPENMEMORY_CLIENT_NAMEhas 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‑specificnamediscriminator 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_dbwhen updating and reading theuserscollection 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_PROVIDERbefore 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 defaultclient_nameboth increate_openmemory_configand inOPENMEMORY_CLIENT_NAMEfallback keeps naming consistent and makes it easy to override via env vars.Also applies to: 160-175
| # 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}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this 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_healthThen 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 bareexceptclause.Bare
exceptblocks 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 bareexceptclause.Bare
exceptblocks 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_dotenvinside theload_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 testsThen 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: MoveResponseimport to the top of the file.Line 160 imports
Responseinside thedispatch()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 BaseHTTPMiddlewareThen 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: MoveResponseimport to the top of the file.Line 160 imports
Responseinside thedispatch()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 BaseHTTPMiddlewareThen 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-backendshould bechronicle-backend.This line still references
friend-backendwhich 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-backendreference.Another reference to
friend-backendthat should be updated tochronicle-backendfor consistency.-- ✅ friend-backend (port 8000) +- ✅ chronicle-backend (port 8000)backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py (2)
47-52: Moveosimport to top of file.Per coding guidelines, all imports must be at the top of the file. The
osmodule 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 httpxThen remove the inline import:
# Use custom CA certificate if available - import os ca_bundle = os.getenv('REQUESTS_CA_BUNDLE')
114-141: Dead code:payloadvariable is defined but never used.The
payloaddictionary at lines 114-124 is constructed but then ignored—the actual POST request at line 128 passes a new inlinejson=dict. Additionally, the unusedpayloadstill 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
payloadvariable 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-minishould begpt-4o-mini.Same issue as in CLAUDE.md—the default model is
gpt-5-minibut should begpt-4o-minito 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
sourcesandhomefields point tohttps://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/chroniclebackends/advanced/src/advanced_omi_backend/workers/memory_jobs.py (1)
149-155: Silent exception swallowing reduces debuggability.The bare
except Exception: passsilently 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_keyimport fromdotenvshould be at the top of the file alongside the existingset_keyimport 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_keyThen 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: Movereimport to top of file.The
remodule 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 reThen 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-configandchronicle-secretsreferences 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 referencescd 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. rebrandDefault
self.mongodb_databaseis still"friend-lite", while the rest of the file/PR is moving to Chronicle naming. If new deployments are expected to use achronicleDB 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 tochronicle—ensure ecosystem alignmentChanging the default
MEMORY_PROVIDERto"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
MemoryProviderenum/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 lifetimeThe JWT payload for
generate_jwt_for_usernow usesiss="chronicle"andaud="chronicle"with a 24‑hour expiry viatimedelta(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
expfromJWT_LIFETIME_SECONDSinstead of hard‑codinghours=24, but the current behavior is correct.extras/asr-services/tests/test_parakeet_service.py (1)
14-18: Consider making the examplecdpath repo-agnosticThe 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), orcd path/to/chronicle/extras/asr-servicesbackends/advanced/Docs/memories.md (1)
475-477: Optional: align CLI example with uv‑based workflowThe 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.pyAs 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 commentsThese 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 initializationRight now initialization failures log only the message and then raise a new
RuntimeError, losing the original traceback context. Consider switching tologging.exceptionand 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 eThis preserves the full stack trace and original exception while keeping logs clean. You may want to apply the same pattern to other broad
except Exceptionblocks 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 consistencyThe 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-networkThis 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_conversationcurrently performs:from advanced_omi_backend.models.conversation import Conversation from datetime import datetimeinside the function body, and
datetimeis 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
Conversationto the top import section.- Drop the inner
from datetime import datetimeentirely.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 timeIf 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_dbappears to be a holdover from "Friend-Lite" naming. Consider renaming it tochronicle_db_connor simplydbto 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: HardcodedconfigMapRefname may reduce deployment flexibility.The
configMapRefis hardcoded tochronicle-configwhilesecretRefon 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: Uselogging.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 usinglogging.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 legacyfriend_liteto 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 targetMemoryProvider.CHRONICLE; optionally also cover legacyFRIEND_LITE.Updating all usages to
MemoryProvider.CHRONICLEand 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 intest_provider_enumsto 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 compatibilityAlso applies to: 150-157, 201-202, 220-222, 230-231
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
backends/advanced/webui/package-lock.jsonis 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: Useuv run pythoncommand instead of directpythonorpython3for 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 defensivehasattr()checks in Python
Files:
extras/openmemory-mcp/test_standalone.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/src/advanced_omi_backend/auth.pyextras/speaker-recognition/init.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/advanced/scripts/create_mycelia_api_key.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pyextras/speaker-recognition/tests/test_speaker_service_integration.pybackends/advanced/init.pybackends/advanced/src/advanced_omi_backend/routers/modules/client_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/tests/test_integration.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pybackends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/upload_files.pybackends/advanced/src/advanced_omi_backend/app_factory.pyscripts/generate-k8s-configs.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/scripts/sync_friendlite_mycelia.pyextras/havpe-relay/main.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/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.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/src/advanced_omi_backend/auth.pyextras/speaker-recognition/init.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/advanced/scripts/create_mycelia_api_key.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pyextras/speaker-recognition/tests/test_speaker_service_integration.pybackends/advanced/init.pybackends/advanced/src/advanced_omi_backend/routers/modules/client_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/tests/test_integration.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pybackends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/upload_files.pybackends/advanced/src/advanced_omi_backend/app_factory.pyscripts/generate-k8s-configs.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/scripts/sync_friendlite_mycelia.pyextras/havpe-relay/main.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/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__.pybackends/advanced/Docs/README.mdbackends/advanced/Docs/HTTPS_SETUP.mdbackends/advanced/src/advanced_omi_backend/app_factory.pybackends/advanced/src/advanced_omi_backend/database.pybackends/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)
| {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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
# 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
AnkushMalaker
left a comment
There was a problem hiding this 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!
backends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.py
Show resolved
Hide resolved
# Conflicts: # README-K8S.md # quickstart.md
# 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
0bc569a to
d2ced7e
Compare
|
Caution Review failedThe pull request is closed. WalkthroughComprehensive 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring extra attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
Comment |
… 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
There was a problem hiding this 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
lifespanfunction 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_stateThen 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 eto preserve the original context. Additionally, uselogging.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 eBased 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 eFor 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.
jsonis 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.
openaiis 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
payloadvariable 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 namedsync_friendlite_mycelia.pyinbackends/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_liteor any new providers).backends/advanced/src/advanced_omi_backend/auth.py (1)
26-29: Critical bug:JWT_LIFETIME_SECONDSis 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 theJWT_LIFETIME_SECONDSenvironment 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_urlwhich may contain embedded credentials fromMONGODB_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-configConfigMap andchronicle-secretsSecret, but these resources are not defined in the Helm chart templates. This is the same issue flagged in the past review forbackends/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-configConfigMap andchronicle-secretsSecret. 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-configConfigMap andchronicle-secretsSecret. 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-configConfigMap andchronicle-secretsSecret. 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
chroniclebut the next command attempts tocd 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 disablingnoImplicitAnyfor better type safety.Setting
noImplicitAny: falsewhile keepingstrict: truecreates an inconsistent type checking configuration. This allows implicitanytypes, 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
anyannotations 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
configMapRefis hardcoded tochronicle-configwhile thesecretRefon 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
sourcesandhomeURLs still reference the oldBasedHardware/Friendrepository, while the PR is renaming the project to Chronicle. Based on the changes inREADME-K8S.md(line 270), the new repository URL appears to begithub.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/chroniclebackends/advanced/tests/test_conversation_models.py (1)
219-221: Consider adding a test for FRIEND_LITE backward compatibility.Since
FRIEND_LITEwas kept as a legacy enum value for backward compatibility with existing database records, consider adding a test to verify thatMemoryProvider.FRIEND_LITEstill 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
⛔ Files ignored due to path filters (1)
backends/advanced/webui/package-lock.jsonis 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: Useuv run pythoncommand instead of directpythonorpython3for 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 defensivehasattr()checks in Python
Files:
backends/advanced/src/advanced_omi_backend/routers/modules/client_routes.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pybackends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/init.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pyextras/openmemory-mcp/test_standalone.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/config.pyextras/havpe-relay/main.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pyextras/speaker-recognition/init.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/scripts/create_mycelia_api_key.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/upload_files.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pyextras/speaker-recognition/tests/test_speaker_service_integration.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/src/advanced_omi_backend/services/memory/service_factory.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/advanced/scripts/sync_friendlite_mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pyscripts/generate-k8s-configs.pybackends/advanced/tests/test_integration.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pybackends/advanced/src/advanced_omi_backend/app_factory.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/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.mdbackends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/src/advanced_omi_backend/config.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/Docs/HTTPS_SETUP.mdbackends/advanced/upload_files.pybackends/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.pybackends/advanced/src/advanced_omi_backend/controllers/websocket_controller.pybackends/advanced/src/advanced_omi_backend/services/__init__.pybackends/advanced/init.pyextras/speaker-recognition/src/simple_speaker_recognition/__init__.pybackends/advanced/src/advanced_omi_backend/middleware/app_middleware.pyextras/openmemory-mcp/test_standalone.pyextras/local-omi-bt/connect-omi.pybackends/advanced/src/advanced_omi_backend/controllers/system_controller.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/openmemory_mcp.pybackends/advanced/src/advanced_omi_backend/app_config.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/chat_routes.pybackends/advanced/src/advanced_omi_backend/config.pyextras/havpe-relay/main.pybackends/advanced/tests/test_conversation_models.pybackends/advanced/src/advanced_omi_backend/chat_service.pybackends/advanced/src/advanced_omi_backend/services/memory/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/memory_routes.pyextras/speaker-recognition/init.pybackends/advanced/src/advanced_omi_backend/models/conversation.pybackends/advanced/src/advanced_omi_backend/routers/modules/__init__.pybackends/advanced/src/advanced_omi_backend/database.pybackends/advanced/scripts/create_mycelia_api_key.pybackends/advanced/src/advanced_omi_backend/services/memory/config.pybackends/advanced/src/advanced_omi_backend/routers/modules/system_routes.pyextras/asr-services/tests/test_parakeet_service.pybackends/advanced/src/advanced_omi_backend/models/__init__.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/mcp_client.pybackends/advanced/src/advanced_omi_backend/models/audio_file.pybackends/advanced/upload_files.pybackends/advanced/src/advanced_omi_backend/routers/modules/health_routes.pyextras/speaker-recognition/tests/test_speaker_service_integration.pybackends/advanced/src/advanced_omi_backend/routers/api_router.pybackends/advanced/src/advanced_omi_backend/services/memory/service_factory.pybackends/advanced/src/advanced_omi_backend/workers/conversation_jobs.pybackends/advanced/src/advanced_omi_backend/clients/__init__.pybackends/advanced/src/advanced_omi_backend/routers/modules/conversation_routes.pybackends/advanced/src/advanced_omi_backend/routers/modules/websocket_routes.pybackends/advanced/scripts/sync_friendlite_mycelia.pybackends/advanced/src/advanced_omi_backend/routers/modules/user_routes.pybackends/advanced/src/advanced_omi_backend/workers/memory_jobs.pyscripts/generate-k8s-configs.pybackends/advanced/tests/test_integration.pybackends/advanced/src/advanced_omi_backend/services/mycelia_sync.pybackends/advanced/src/advanced_omi_backend/app_factory.pybackends/advanced/src/advanced_omi_backend/services/memory/providers/__init__.pybackends/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
| # 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 1Repository: 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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
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-nativelibrary - 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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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.tsxRepository: chronicler-ai/chronicle
Length of output: 30842
🏁 Script executed:
cat -n backends/advanced/webui/src/pages/TimelineRouter.tsxRepository: chronicler-ai/chronicle
Length of output: 3145
🏁 Script executed:
wc -l backends/advanced/webui/src/pages/FrappeGanttTimeline.tsxRepository: 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:
- Test all Gantt chart interactions (view mode changes, scrolling, zooming)
- Verify the custom popup HTML still renders correctly
- Test in the UI with both demo and real data to ensure no visual regressions
| from chronicle.bluetooth import listen_to_omi, print_devices | ||
| from chronicle.decoder import OmiOpusDecoder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -30Repository: 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 -30Repository: 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/nullRepository: 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 -20Repository: 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.pyRepository: 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 -30Repository: 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 -80Repository: 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 -30Repository: 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/nullRepository: 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/nullRepository: 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.
|
Merging as requested changes implemented. |
|
Kindly dont merge if there's anything unreviewed, even new changes need review. |
|
? |
Relies on Robot2 being merged first as well as memory service
Summary by CodeRabbit
New Features
Configuration
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.