feat: Phase 10B — save YouTube transcript to DB#20
Conversation
- Add video_transcripts table (migration) with RLS - Add youtube/schemas.py, service.py, router.py, tool.py - Mount /api/v1/youtube REST endpoints in main.py - Add save_video_transcript handoff tool to supervisor - Wire save_transcript_node into orchestrator graph - Persist youtube_context in conversations.youtube_context - Load youtube_context at turn start so cross-turn save works - Emit tool_use SSE + Bookmark icon when saving
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
WalkthroughThis PR implements a complete YouTube transcript-saving feature. Users can now save video summaries generated by the YouTube agent; the supervisor prompts them to confirm, and when confirmed, a new ChangesYouTube Transcript Save Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/app/agents/supervisor.py`:
- Around line 122-136: The save rule is unsatisfiable because
conversation_service.load_history only restores "user" and "assistant" roles
(ToolMessage is not persisted) and the supervisor disables tools after
youtube_agent runs; change the prompt/check to look for the prior assistant
YouTube summary message in conversation history instead of requiring a
ToolMessage. Concretely, update the supervisor logic that enforces the YouTube
save rule so it searches recent assistant messages (the message content or a
marker produced by youtube_agent) to detect a YouTube summary, then allow
calling save_video_transcript() when the user explicitly confirms; keep
save_transcript_node reading state["youtube_context"] unchanged, and ensure the
supervisor pass that binds tools (where with_tools is set using memory_done)
will include save_video_transcript() when an assistant summary is present.
- Line 46: The local duplicate constant SAVE_TRANSCRIPT_TOOL_NAME in
supervisor.py must be removed and replaced by importing the canonical definition
from app/features/youtube/tool (where SAVE_TRANSCRIPT_TOOL_NAME is defined) so
both supervisor.py (used in the `@tool`(...) decorator in this file) and
orchestrator.py reference the same symbol; update supervisor.py to import
SAVE_TRANSCRIPT_TOOL_NAME from the youtube tool module and use that imported
constant in the `@tool`(...) decorator/registration to ensure a single source of
truth.
In `@backend/app/features/chat/service.py`:
- Around line 115-120: The code that reads youtube_context can crash if
event["data"]["output"] is None; update the guard in the astream_events handling
for kind == "on_chain_end" and node == "youtube_agent" to defensively coalesce
possible None values (e.g., use event.get("data") or {} and then .get("output")
or {} before accessing "youtube_context") so that pending_youtube_context is
only set when a string is present and the loop won't raise AttributeError.
In `@backend/app/features/youtube/router.py`:
- Around line 18-25: Add pagination to the list_transcripts_endpoint by
accepting limit and offset Query parameters (e.g., add Query import and params
to list_transcripts_endpoint signature) and pass them into
service.list_transcripts; then update service.list_transcripts to apply the
Supabase range call using range(offset, offset + limit - 1). Ensure
default/validation for limit/offset (reasonable default limit and non-negative
offset) and keep the same response model (list[VideoTranscriptOut]) while
returning only the requested page.
In `@backend/app/features/youtube/service.py`:
- Around line 110-124: list_transcripts currently returns an unbounded result
set which can cause full table scans; modify the function list_transcripts to
accept a limit (e.g. limit: int = 50) and optional keyset cursor (e.g.
before_created_at: str | None) and apply them to the Supabase query on table
"video_transcripts" (keep using _SELECT_COLS) by adding .limit(limit) and, for
keyset pagination, a .lt("created_at", before_created_at) when before_created_at
is provided and ensure the query still orders by created_at desc; update the
function signature and callers (router) to pass a default cap and optional
before cursor so the REST endpoint can page safely.
- Around line 168-189: The JSONB filter used in the memory_entries delete block
is incorrect: change the call that currently uses .eq("metadata->>video_id",
row.video_id) to use the supabase filter API — .filter("metadata->>video_id",
"eq", row.video_id) — so the JSONB arrow operator is handled correctly; update
the delete block in the delete_transcript section (the code using
client.table("memory_entries").delete(), mem_response, user_id and row.video_id)
and keep the surrounding try/except and logging intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: c1409910-a68a-4521-9d97-6d90a824f9cf
📒 Files selected for processing (12)
backend/app/agents/orchestrator.pybackend/app/agents/supervisor.pybackend/app/features/chat/conversation_service.pybackend/app/features/chat/service.pybackend/app/features/youtube/__init__.pybackend/app/features/youtube/router.pybackend/app/features/youtube/schemas.pybackend/app/features/youtube/service.pybackend/app/features/youtube/tool.pybackend/app/main.pyfrontend/features/chat/components/ChatWindow.tsxsupabase/migrations/20260510120000_create_video_transcripts.sql
- supervisor.py: remove duplicate SAVE_TRANSCRIPT_TOOL_NAME, import from tool.py - supervisor.py: reword save prompt to reference assistant summary (not ToolMessage) - chat/service.py: defensive None coalescing for on_chain_end output - youtube/service.py: add limit/offset pagination to list_transcripts - youtube/service.py: fix JSONB filter .eq() -> .filter() for metadata->>video_id - youtube/router.py: expose limit/offset Query params on list endpoint
Summary by CodeRabbit