Conversation
…6423) Move 20+ models from the 570-line models/conversation.py into 6 focused files while maintaining full backward compatibility via re-exports: - conversation_enums.py: CategoryEnum, ConversationSource, ConversationStatus, ConversationVisibility, PostProcessingStatus, PostProcessingModel, ExternalIntegrationConversationSource - structured.py: ActionItem, Event, ActionItemsExtraction, Structured - geolocation.py: Geolocation - audio_file.py: AudioFile - conversation_photo.py: ConversationPhoto - calendar_context.py: MeetingParticipant, CalendarMeetingContext All 50+ existing importers continue working unchanged via re-exports in conversation.py. No Firestore schema changes, no API changes. Closes #6423 Co-Authored-By: Claude Opus 4.6 <[email protected]>
Greptile SummaryThis PR splits Confidence Score: 5/5Safe to merge — pure structural refactoring with no behaviour, schema, or API changes. All moved symbols are re-exported via No files require special attention.
|
| Filename | Overview |
|---|---|
| backend/models/conversation.py | Slimmed to core models only; imports all moved symbols and re-exports them via __all__ for full backward compatibility — no functional changes. |
| backend/models/conversation_enums.py | New module containing all 7 enums extracted verbatim from the original file; no logic changes, ConversationSource._missing_ hook preserved. |
| backend/models/structured.py | New module with ActionItem, Event, ActionItemsExtraction, Structured; imports CategoryEnum from conversation_enums — no circular dependency risk. |
| backend/models/audio_file.py | Straightforward extraction of AudioFile with stdlib-only imports; no changes to fields or behaviour. |
| backend/models/calendar_context.py | New module with MeetingParticipant and CalendarMeetingContext; clean extraction with no cross-module dependencies beyond stdlib. |
| backend/models/conversation_photo.py | Clean extraction of ConversationPhoto including its photos_as_string static method; no behaviour changes. |
| backend/models/geolocation.py | Minimal Geolocation model extracted cleanly with no dependencies beyond Pydantic. |
| backend/tests/unit/test_conversation_model_split.py | 20 unit tests covering backward-compatible imports, direct new-module imports, serialisation round-trips, and helper methods; correctly registered in test.sh. |
| backend/test.sh | New test file added at line 45 per the CLAUDE.md requirement that every new test file be explicitly listed in test.sh. |
Class Diagram
%%{init: {'theme': 'neutral'}}%%
classDiagram
class conversation_enums {
CategoryEnum
ConversationSource
ConversationStatus
ConversationVisibility
PostProcessingStatus
PostProcessingModel
ExternalIntegrationConversationSource
}
class structured {
ActionItem
Event
ActionItemsExtraction
Structured
}
class geolocation {
Geolocation
}
class audio_file {
AudioFile
}
class conversation_photo {
ConversationPhoto
}
class calendar_context {
MeetingParticipant
CalendarMeetingContext
}
class conversation {
Conversation
CreateConversation
ExternalIntegrationCreateConversation
ConversationPostProcessing
PluginResult
AppResult
__all__ (re-exports all)
}
structured --> conversation_enums : imports CategoryEnum
conversation --> conversation_enums : imports + re-exports
conversation --> structured : imports + re-exports
conversation --> geolocation : imports + re-exports
conversation --> audio_file : imports + re-exports
conversation --> conversation_photo : imports + re-exports
conversation --> calendar_context : imports + re-exports
Reviews (1): Last reviewed commit: "Phase 1: Split conversation god object i..." | Re-trigger Greptile
… __all__ Codex review caught that __all__ excluded passthrough imports that star-import consumers (postprocess_conversation.py, process_conversation.py) depend on. Added TranscriptSegment, Message, Person to __all__ and a regression test. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Codex review round 2 found that __all__ also excluded typing symbols (List, Optional) that postprocess_conversation.py gets via star import. Rather than enumerate every leaked name, remove __all__ entirely — the explicit re-imports at module level already handle named imports. Phase 3 will clean up the star imports and add __all__ back. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…desc photos Addresses tester findings: - Add include_timestamps=True branches for ActionItem and ConversationPhoto - Add events_to_string([]) empty case - Add photos with no description case - Remove brittle len(CategoryEnum)==33 assertion - Document why real-consumer smoke import is not feasible (GCP creds) Co-Authored-By: Claude Opus 4.6 <[email protected]>
…orts (#6423) Phase 2: New ConversationSummary lightweight view model for consumers that only need title/overview/transcript (LLM utils, vector_db, notifications). Phase 3: Migrate all 34 production + test callers from `from models.conversation import X` to import from canonical modules: - conversation_enums: CategoryEnum, ConversationSource, ConversationStatus, etc. - structured: Structured, ActionItem, Event, ActionItemsExtraction - geolocation: Geolocation - audio_file: AudioFile - conversation_photo: ConversationPhoto - calendar_context: CalendarMeetingContext, MeetingParticipant Replace wildcard imports in process_conversation.py and postprocess_conversation.py with explicit imports. Add __all__ to conversation.py to control star-import surface. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ates, summary transcript Co-Authored-By: Claude Opus 4.6 <[email protected]>
Live Test Evidence (L1 + L2)L1 — Backend standaloneBuild & startup: Endpoint tests (curl):
WebSocket (routers/transcribe.py): Exercises: L2 — Integrated service + appThis PR is a pure import refactor — zero API contract changes, zero schema changes, zero behavioral changes. The conversation endpoints return identical JSON. L2 verified by:
by AI for @beastoin |
Live Test Evidence — Updated (L1 Backend + L1 Pusher + E2E)L1 Backend —
|
| Module | Import | Where exercised |
|---|---|---|
conversation_enums |
ConversationSource, ConversationStatus |
transcribe.py, pusher.py, process_conversation.py |
structured |
Structured |
transcribe.py, conversation_processing.py |
geolocation |
Geolocation |
pusher.py, location.py |
conversation_photo |
ConversationPhoto |
transcribe.py, conversation_processing.py |
calendar_context |
CalendarMeetingContext |
conversation_processing.py |
audio_file |
AudioFile |
database/conversations.py |
by AI for @beastoin
|
lgtm |
Deploy Monitor Checkpoint (T+20m)Deploy: PR #6425 merged at 03:56 UTC, commit
Health Status:
5xx Analysis:
Verdict: ✅ PASS — zero regressions from model split refactor. All import paths working correctly. Next checkpoint: T+1h (~05:00 UTC) by AI for @beastoin |
Summary
Decouples
backend/models/conversation.py— the highest-coupling file in the backend (570 lines, 20+ models, 312 edges, 29+ importers) — into domain-specific modules. All 3 phases in one PR.Phase 1 — Split the file (7 new modules)
conversation_enums.py— 7 enums (CategoryEnum, ConversationSource, ConversationStatus, etc.)structured.py— Structured, ActionItem, Event, ActionItemsExtractiongeolocation.py— Geolocationaudio_file.py— AudioFileconversation_photo.py— ConversationPhotocalendar_context.py— CalendarMeetingContext, MeetingParticipantconversation.pysimplified from 570→320 lines (keeps Conversation + CRUD/request/response models)Phase 2 — ConversationSummary lightweight view
conversation_summary.pywith read-only view (id, title, overview, category, transcript_text, created_at, person_ids)from_conversation()classmethod for easy conversionPhase 3 — Migrate all callers to narrow imports
from models.conversation import Xto canonical modulesprocess_conversation.pyandpostprocess_conversation.py__all__added toconversation.pyto control star-import surfaceChanges
Test plan
uvicorn main:app— 318 routes, curl tested conversation endpoints (200s)uvicorn pusher.main:app— healthy, WS/v1/trigger/listenconnected/v4/listen— full pipeline ran, zero import errorsDeployment plan
Deploy order: Cloud Run backend first, then GKE pusher. Pure import refactor — main failure mode is a missed import, which would surface immediately as ImportError / 500s.
Step 1 — Deploy Backend to Cloud Run (prod)
gh workflow run "Deploy Backend to Cloud RUN" --repo BasedHardware/omi -f environment=prod -f branch=mainWait ~8-10 min, then verify:
Step 2 — Deploy Pusher to GKE (prod)
gh workflow run "Deploy Backend Pusher to GKE" --repo BasedHardware/omi --ref main -f environment=prodWait ~5-7 min, then verify:
Step 3 — Post-deploy verification
Rollback (if needed)
Closes #6423
🤖 Generated with Claude Code