Skip to content

Conversation

@anish-work
Copy link
Contributor

@anish-work anish-work commented Nov 27, 2025

Q/A checklist

  • I have tested my UI changes on mobile and they look acceptable
  • I have tested changes to the workflows in both the API and the UI
  • I have done a code review of my changes and looked at each line of the diff + the references of each function I have changed
  • My changes have not increased the import time of the server
How to check import time?

time python -c 'import server'

You can visualize this using tuna:

python3 -X importtime -c 'import server' 2> out.log && tuna out.log

To measure import time for a specific library:

$ time python -c 'import pandas'

________________________________________________________
Executed in    1.15 secs    fish           external
   usr time    2.22 secs   86.00 micros    2.22 secs
   sys time    0.72 secs  613.00 micros    0.72 secs

To reduce import times, import libraries that take a long time inside the functions that use them instead of at the top of the file:

def my_function():
    import pandas as pd
    ...

Legal Boilerplate

Look, I get it. The entity doing business as “Gooey.AI” and/or “Dara.network” was incorporated in the State of Delaware in 2020 as Dara Network Inc. and is gonna need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Dara Network Inc can use, modify, copy, and redistribute my contributions, under its choice of terms.


@anish-work anish-work requested a review from devxpy November 27, 2025 11:24
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

📝 Walkthrough

Walkthrough

This pull request adds version awareness to the BasePage and breadcrumbs functionality. The changes extend the app_url method to accept a version_id parameter and introduce an is_published_run_version() method to detect version-specific views. The _render_header logic is updated to fetch and display version-specific metadata (title, notes, photo_url) from published run versions when a version_id is present. Version row rendering is enhanced with styled version cards including version preview, a "FIRST VERSION" badge, and change notes display. Breadcrumbs title resolution is updated to prioritize version titles when a PublishedRunVersion parameter is provided.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Version parameter threading: Verify that version_id is correctly propagated through URL construction and query parameter handling
  • Version metadata override logic: Review the conditional logic in _render_header that loads and applies version-specific title, notes, and photo_url to ensure proper fallbacks
  • Publish form detection update: Confirm that is_published_run_version() check is correctly integrated with existing change detection logic
  • Breadcrumbs version handling: Validate that PublishedRunVersion parameter correctly prioritizes version title over fallback options across different code paths

Possibly related PRs

Suggested reviewers

  • devxpy

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix pr version title notes' accurately describes the main changes, which involve fixing how PR version titles and notes are displayed and propagated through the codebase.
Description check ✅ Passed PR description includes all required sections from the template with Q/A checklist items marked complete, import time guidance provided, and legal boilerplate preserved.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix_pr_version_title_notes

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.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
daras_ai_v2/base.py (1)

955-962: Consider adding a comment explaining the version_id logic.

The intent of or version_id is that viewing any specific version should allow publishing, but this isn't immediately obvious to readers.

         version_id = self.request.query_params.get("version_id", None)
         return (
             published_run.title != title
             or published_run.notes != notes
             or published_run.saved_run != saved_run
             or published_run.photo_url != photo_url
+            # Always allow saving when viewing a specific version
             or version_id
         )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26b3d2c and 2fa39e0.

📒 Files selected for processing (2)
  • daras_ai_v2/base.py (5 hunks)
  • daras_ai_v2/breadcrumbs.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/base.py
  • daras_ai_v2/breadcrumbs.py
🧬 Code graph analysis (1)
daras_ai_v2/breadcrumbs.py (3)
bots/models/published_run.py (1)
  • is_root (282-283)
bots/models/saved_run.py (1)
  • get_app_url (172-178)
handles/models.py (1)
  • get_app_url (172-173)
🪛 Ruff (0.14.6)
daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


508-508: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

daras_ai_v2/breadcrumbs.py

59-59: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)


117-117: Undefined name pr_version

(F821)


119-119: Undefined name pr_version

(F821)


120-120: Undefined name pr_version

(F821)

⏰ 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: test (3.10.12, 1.8.3)
🔇 Additional comments (1)
daras_ai_v2/base.py (1)

1292-1297: LGTM!

The version row correctly propagates version_id via query parameters and conditionally renders the version title.

example_id: str | None = None,
run_id: str | None = None,
uid: str | None = None,
version_id: str | None = None,
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused version_id parameter should be removed or implemented.

The version_id parameter is declared but never used in the method body. Looking at line 1292, version_id is already being passed via query_params, making this parameter redundant.

     uid: str | None = None,
-    version_id: str | None = None,
     query_params: dict[str, str] | None = None,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
version_id: str | None = None,
uid: str | None = None,
query_params: dict[str, str] | None = None,
🧰 Tools
🪛 Ruff (0.14.6)

240-240: Unused class method argument: version_id

(ARG003)

🤖 Prompt for AI Agents
In daras_ai_v2/base.py at line 240, the parameter "version_id: str | None =
None" is declared but unused (it's redundant because version_id is already
injected into query_params at line 1292); remove the unused parameter from the
method signature and update any callers or tests that pass it, or if the
original intent was to accept an explicit version_id, instead wire this
parameter into the existing query_params construction (set
query_params["version_id"] = version_id when provided) and remove the redundant
hard-coded passing; ensure function docstring/type hints and all call sites are
adjusted accordingly.

Comment on lines +434 to +443
version_id = self.request.query_params.get("version_id", None)
pr_version = None
if version_id:
pr_version = pr.versions.get(version_id=version_id)

if pr_version and self.current_pr:
self.current_pr.title = pr_version.title
self.current_pr.notes = pr_version.notes
self.current_pr.photo_url = pr_version.photo_url

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing exception handling for invalid version_id.

If version_id is provided but doesn't exist, pr.versions.get(version_id=version_id) will raise PublishedRunVersion.DoesNotExist, causing an unhandled 500 error.

     version_id = self.request.query_params.get("version_id", None)
     pr_version = None
     if version_id:
-        pr_version = pr.versions.get(version_id=version_id)
-
-        if pr_version and self.current_pr:
-            self.current_pr.title = pr_version.title
-            self.current_pr.notes = pr_version.notes
-            self.current_pr.photo_url = pr_version.photo_url
+        try:
+            pr_version = pr.versions.get(version_id=version_id)
+        except PublishedRunVersion.DoesNotExist:
+            pr_version = None
+        else:
+            self.current_pr.title = pr_version.title
+            self.current_pr.notes = pr_version.notes
+            self.current_pr.photo_url = pr_version.photo_url

Note: PublishedRunVersion needs to be imported from bots.models.

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

🤖 Prompt for AI Agents
In daras_ai_v2/base.py around lines 434 to 443, calling
pr.versions.get(version_id=version_id) can raise
PublishedRunVersion.DoesNotExist for an invalid version_id; wrap the lookup in a
try/except catching PublishedRunVersion.DoesNotExist, set pr_version = None (or
handle gracefully by logging/returning an appropriate response) instead of
letting the exception bubble up, and add the import PublishedRunVersion from
bots.models at the top of the file.

)

if self.tab == RecipeTabs.run and is_example:
if self.tab == RecipeTabs.run and is_example or pr_version:
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Ambiguous operator precedence - add parentheses for clarity.

The expression self.tab == RecipeTabs.run and is_example or pr_version has unclear precedence. Python evaluates this as (self.tab == RecipeTabs.run and is_example) or pr_version.

-        if self.tab == RecipeTabs.run and is_example or pr_version:
+        if (self.tab == RecipeTabs.run and is_example) or pr_version:
🧰 Tools
🪛 Ruff (0.14.6)

508-508: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

🤖 Prompt for AI Agents
In daras_ai_v2/base.py around line 508, the conditional "self.tab ==
RecipeTabs.run and is_example or pr_version" has ambiguous operator precedence;
modify it to make the intended grouping explicit by adding parentheses so the
comparison to RecipeTabs.run is grouped and the is_example/pr_version operands
are grouped together, e.g. treat it as "(self.tab == RecipeTabs.run) and
(is_example or pr_version)".


is_root = pr and pr.saved_run == sr and pr.is_root()
is_example = not is_root and pr and pr.saved_run == sr
is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Ambiguous operator precedence - add parentheses.

The expression evaluates as (not is_root and pr and pr.saved_run == sr) or sr.parent_version due to operator precedence. If sr.parent_version exists, is_example will be truthy (the version object itself), not a boolean.

-    is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
+    is_example = (not is_root and pr and pr.saved_run == sr) or bool(sr.parent_version)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
is_example = (not is_root and pr and pr.saved_run == sr) or bool(sr.parent_version)
🧰 Tools
🪛 Ruff (0.14.6)

59-59: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

🤖 Prompt for AI Agents
In daras_ai_v2/breadcrumbs.py around line 59, the expression `is_example = not
is_root and pr and pr.saved_run == sr or sr.parent_version` has ambiguous
precedence and can yield a non-boolean when sr.parent_version is truthy; add
parentheses to make the intended grouping explicit (e.g. `(not is_root and pr
and pr.saved_run == sr)`) and ensure the result is boolean by wrapping the whole
expression with bool(...) or by explicitly comparing `sr.parent_version` (e.g.
`sr.parent_version is not None`) so `is_example` is always a boolean.

@anish-work anish-work force-pushed the fix_pr_version_title_notes branch from 2fa39e0 to d64baa1 Compare November 27, 2025 11:51
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (5)
daras_ai_v2/breadcrumbs.py (2)

59-59: Ambiguous operator precedence - add parentheses.

The expression evaluates as (not is_root and pr and pr.saved_run == sr) or sr.parent_version. When sr.parent_version is truthy, is_example becomes the version object rather than a boolean.

-    is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
+    is_example = (not is_root and pr and pr.saved_run == sr) or bool(sr.parent_version)

113-122: Critical: pr_version is undefined - will cause NameError at runtime.

The variable pr_version is referenced on lines 113, 115, and 116 but is never defined in this function. This will crash at runtime when execution reaches this branch.

Based on the AI summary mentioning that base.py introduces pr_version handling, this variable likely needs to be passed as a parameter to get_title_breadcrumbs.

Option 1 - Pass pr_version as parameter (recommended):

 def get_title_breadcrumbs(
     page_cls: typing.Union["BasePage", typing.Type["BasePage"]],
     sr: SavedRun,
     pr: PublishedRun | None,
     tab: typing.Optional["RecipeTabs"] = None,
+    pr_version: "PublishedRunVersion | None" = None,
 ) -> TitleBreadCrumbs:

Option 2 - Derive from sr.parent_version if that's the intended source:

-                if pr_version:
+                if sr.parent_version:
                     h1_title = TitleUrl(
-                        title=pr_version.title,
-                        url=pr_version.saved_run.get_app_url(),
+                        title=sr.parent_version.title,
+                        url=sr.parent_version.saved_run.get_app_url(),
                     )

Verify whether pr_version should be passed from the caller or derived from sr.parent_version:

#!/bin/bash
# Check how get_title_breadcrumbs is called in base.py
rg -n -A5 'get_title_breadcrumbs' --type=py
daras_ai_v2/base.py (3)

240-240: Unused version_id parameter—remove it or wire it into query_params.

The version_id parameter is declared but never used in the method body. At line 1292, version_id is passed via the query_params dictionary, making this parameter redundant.

Remove the unused parameter:

     uid: str | None = None,
-    version_id: str | None = None,
     query_params: dict[str, str] | None = None,

Or, if you intend to support an explicit version_id parameter, wire it into query_params:

     query_params: dict[str, str] | None = None,
     path_params: dict | None = None,
 ) -> str:
     if not tab:
         tab = RecipeTabs.run
     if query_params is None:
         query_params = {}
+    if version_id:
+        query_params["version_id"] = version_id

434-443: Missing exception handling for invalid version_id.

If version_id is provided but doesn't exist, pr.versions.get(version_id=version_id) will raise PublishedRunVersion.DoesNotExist, causing an unhandled 500 error.

Wrap the lookup in a try/except block:

     version_id = self.request.query_params.get("version_id", None)
     pr_version = None
     if version_id:
-        pr_version = pr.versions.get(version_id=version_id)
-
-        if pr_version and self.current_pr:
-            self.current_pr.title = pr_version.title
-            self.current_pr.notes = pr_version.notes
-            self.current_pr.photo_url = pr_version.photo_url
+        try:
+            pr_version = pr.versions.get(version_id=version_id)
+        except PublishedRunVersion.DoesNotExist:
+            pr_version = None
+        else:
+            self.current_pr.title = pr_version.title
+            self.current_pr.notes = pr_version.notes
+            self.current_pr.photo_url = pr_version.photo_url

508-508: Add parentheses to clarify operator precedence.

The expression self.tab == RecipeTabs.run and is_example or pr_version has ambiguous precedence. Python evaluates this as (self.tab == RecipeTabs.run and is_example) or pr_version.

Make the precedence explicit:

-        if self.tab == RecipeTabs.run and is_example or pr_version:
+        if (self.tab == RecipeTabs.run and is_example) or pr_version:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fa39e0 and d64baa1.

📒 Files selected for processing (2)
  • daras_ai_v2/base.py (5 hunks)
  • daras_ai_v2/breadcrumbs.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/breadcrumbs.py
  • daras_ai_v2/base.py
🧬 Code graph analysis (1)
daras_ai_v2/breadcrumbs.py (8)
bots/models/published_run.py (1)
  • is_root (282-283)
bots/models/saved_run.py (1)
  • get_app_url (172-178)
handles/models.py (1)
  • get_app_url (172-173)
bots/models/workflow.py (1)
  • page_cls (242-245)
daras_ai_v2/base.py (1)
  • get_run_title (1170-1171)
recipes/VideoBots.py (1)
  • get_run_title (818-831)
recipes/asr_page.py (1)
  • get_run_title (100-113)
recipes/ModelTrainer.py (1)
  • get_run_title (249-253)
🪛 Ruff (0.14.6)
daras_ai_v2/breadcrumbs.py

59-59: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)


113-113: Undefined name pr_version

(F821)


115-115: Undefined name pr_version

(F821)


116-116: Undefined name pr_version

(F821)

daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


508-508: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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). (2)
  • GitHub Check: Analyze (python)
  • GitHub Check: test (3.10.12, 1.8.3)
🔇 Additional comments (1)
daras_ai_v2/base.py (1)

1288-1297: LGTM!

The version row correctly propagates version_id via query_params and conditionally renders the version title when available.

Comment on lines 955 to 962
version_id = self.request.query_params.get("version_id", None)
return (
published_run.title != title
or published_run.notes != notes
or published_run.saved_run != saved_run
or published_run.photo_url != photo_url
or version_id
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Questionable change detection logic—version_id presence always returns True.

The method returns True whenever version_id is present in query params, regardless of whether anything actually changed. This means viewing any historical version will trigger the "Unpublished changes" indicator (line 490-491), which may confuse users.

Consider whether viewing a historical version should be treated as "changed":

  • If the intent is to indicate "you're viewing an old version," consider a separate indicator rather than conflating it with "unpublished changes."
  • If version_id should only trigger True when it differs from the current published version, add that check:
     version_id = self.request.query_params.get("version_id", None)
     return (
         published_run.title != title
         or published_run.notes != notes
         or published_run.saved_run != saved_run
         or published_run.photo_url != photo_url
-        or version_id
+        or (version_id and version_id != str(published_run.versions.latest().version_id))
     )

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

🤖 Prompt for AI Agents
In daras_ai_v2/base.py around lines 955 to 962, the current change-detection
returns True whenever a version_id query param exists, which always marks the
run as "changed"; instead, only treat it as changed if the requested version_id
actually differs from the published run's version identifier (e.g., compare
version_id to published_run.version_id or published_run.version if that field
exists), or remove version_id from this boolean expression and surface a
separate "viewing historical version" flag/indicator if the intent is to notify
users they are viewing an older revision; update the conditional accordingly so
version_id alone does not force a True result.

@anish-work anish-work force-pushed the fix_pr_version_title_notes branch from d64baa1 to 3e78a74 Compare November 27, 2025 12:42
- remove print statements
- remove unsused pr_version code
@anish-work anish-work force-pushed the fix_pr_version_title_notes branch from 3e78a74 to 83e1ec7 Compare November 27, 2025 12:43
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
daras_ai_v2/breadcrumbs.py (1)

58-61: Clarify is_example precedence and force a boolean result

is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version mixes and/or without parentheses and returns a sr.parent_version object rather than a strict bool when present. That’s harder to read and potentially surprising.

Consider parenthesizing and wrapping the parent_version leg in bool:

-    is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
+    is_example = (not is_root and pr and pr.saved_run == sr) or bool(sr.parent_version)

This keeps the current semantics (example when it’s the published run or when there’s a parent_version) while making intent and type explicit.

daras_ai_v2/base.py (4)

233-272: app_url’s version_id parameter is unused—either wire it in or drop it

version_id is accepted in the app_url signature but never affects the generated URL, while callers currently pass version_id through query_params instead. This is confusing and flagged by Ruff as an unused argument.

Either remove version_id from the signature, or (preferably) integrate it into query_params so callers can use the dedicated parameter:

     def app_url(
         cls,
@@
         example_id: str | None = None,
         run_id: str | None = None,
         uid: str | None = None,
-        version_id: str | None = None,
+        version_id: str | None = None,
         query_params: dict[str, str] | None = None,
         path_params: dict | None = None,
     ) -> str:
         if not tab:
             tab = RecipeTabs.run
         if query_params is None:
             query_params = {}
+
+        if version_id is not None:
+            query_params |= {"version_id": str(version_id)}

You can then gradually update call sites like _render_version_row to pass version_id=version.version_id instead of building a one-off query_params dict.


508-513: Disambiguate and/or precedence in notes visibility condition

if self.tab == RecipeTabs.run and is_example or pr_version: is evaluated as (self.tab == RecipeTabs.run and is_example) or pr_version, but that’s not obvious at a glance and is flagged by Ruff.

Add parentheses to make the grouping explicit and keep the current behavior:

-        if self.tab == RecipeTabs.run and is_example or pr_version:
+        if (self.tab == RecipeTabs.run and is_example) or pr_version:

This still shows notes when you’re on the run tab with an example, or whenever a pr_version is selected, but removes the ambiguity for readers and linters.


955-962: Confirm whether version_id should always imply “published run changed”

_has_published_run_changed now returns True whenever a version_id query param is present:

version_id = self.request.query_params.get("version_id", None)
return (
    published_run.title != title
    or published_run.notes != notes
    or published_run.saved_run != saved_run
    or published_run.photo_url != photo_url
    or version_id
)

This means that viewing a historical version (with no actual field diffs) is always treated as “changed”. If the intent is:

  • to always allow saving when editing from a historical version (effectively “revert to this version”), this behavior is fine but should probably be documented; or
  • to indicate changes only when there’s a real diff from the current published run,

then version_id should either be removed from this expression or compared against the latest version’s identifier instead.

Please double‑check the intended UX here and adjust the predicate (and/or add a brief comment) so future readers don’t misinterpret this as a bug.


432-443: Handle invalid version_id when resolving pr_version in _render_header

pr_version = pr.versions.get(version_id=version_id) will raise PublishedRunVersion.DoesNotExist for an invalid or stale version_id, resulting in a 500 instead of a graceful fallback.

Wrap this lookup in a try/except and only apply overrides when a version is actually found:

-        sr, pr = self.current_sr_pr
-        is_example = pr.saved_run == sr
-        version_id = self.request.query_params.get("version_id", None)
-        pr_version = None
-        if version_id:
-            pr_version = pr.versions.get(version_id=version_id)
-
-            if pr_version and self.current_pr:
-                self.current_pr.title = pr_version.title
-                self.current_pr.notes = pr_version.notes
-                self.current_pr.photo_url = pr_version.photo_url
+        sr, pr = self.current_sr_pr
+        is_example = pr.saved_run == sr
+        version_id = self.request.query_params.get("version_id")
+        pr_version: PublishedRunVersion | None = None
+        if version_id:
+            try:
+                pr_version = pr.versions.get(version_id=version_id)
+            except PublishedRunVersion.DoesNotExist:
+                pr_version = None
+            else:
+                if self.current_pr:
+                    self.current_pr.title = pr_version.title
+                    self.current_pr.notes = pr_version.notes
+                    self.current_pr.photo_url = pr_version.photo_url

This keeps the per-version header behavior but avoids crashing on bad input.

🧹 Nitpick comments (1)
daras_ai_v2/base.py (1)

1288-1297: Version history links and titles look correct; consider using the version_id parameter

The version history row now:

  • Links to a specific saved run and version_id via query_params=dict(version_id=version.version_id), and
  • Renders version.title when present.

This matches the per-version UX being introduced and looks good.

Once app_url’s version_id parameter is wired up, you might simplify this call to:

-        url = self.app_url(
-            example_id=version.published_run.published_run_id,
-            run_id=version.saved_run.run_id,
-            uid=version.saved_run.uid,
-            query_params=dict(version_id=version.version_id),
-        )
+        url = self.app_url(
+            example_id=version.published_run.published_run_id,
+            run_id=version.saved_run.run_id,
+            uid=version.saved_run.uid,
+            version_id=version.version_id,
+        )

Purely a readability/consistency tweak; existing behavior is fine.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d64baa1 and 83e1ec7.

📒 Files selected for processing (2)
  • daras_ai_v2/base.py (5 hunks)
  • daras_ai_v2/breadcrumbs.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/base.py
  • daras_ai_v2/breadcrumbs.py
🧬 Code graph analysis (1)
daras_ai_v2/breadcrumbs.py (1)
bots/models/published_run.py (1)
  • is_root (282-283)
🪛 Ruff (0.14.6)
daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


508-508: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

daras_ai_v2/breadcrumbs.py

59-59: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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: test (3.10.12, 1.8.3)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
daras_ai_v2/base.py (3)

240-240: Unused version_id parameter.

This parameter is declared but never used in the method body. The version_id is already being passed via query_params at line 1300, making this parameter redundant.


434-442: Missing exception handling for invalid version_id.

If version_id is provided but doesn't exist, pr.versions.get(version_id=version_id) will raise PublishedRunVersion.DoesNotExist, causing an unhandled 500 error.


512-512: Ambiguous operator precedence.

The expression self.tab == RecipeTabs.run and is_example or pr_version has unclear precedence. Add parentheses for clarity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d73cd7 and f0b14c2.

📒 Files selected for processing (1)
  • daras_ai_v2/base.py (7 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/base.py
🧠 Learnings (2)
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_examples_tab()` method QuerySet at line 2164 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to optimize database queries for published run rendering.

Applied to files:

  • daras_ai_v2/base.py
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_saved_tab()` method QuerySet at line 2199 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to avoid N+1 queries when rendering published runs.

Applied to files:

  • daras_ai_v2/base.py
🧬 Code graph analysis (1)
daras_ai_v2/base.py (1)
routers/root.py (1)
  • RecipeTabs (893-937)
🪛 Ruff (0.14.6)
daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


512-512: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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). (2)
  • GitHub Check: Analyze (python)
  • GitHub Check: test (3.10.12, 1.8.3)
🔇 Additional comments (3)
daras_ai_v2/base.py (3)

490-494: LGTM!

The condition correctly incorporates the version check using self.is_published_run_version() to display the unpublished changes indicator when viewing a historical version.


953-954: LGTM!

Clean helper method that encapsulates the version ID query parameter check.


1300-1335: Well-structured version row rendering.

The implementation properly:

  • Passes version_id through query params for deep linking
  • Adds hover styling for better UX
  • Uses html.escape for change notes (good XSS prevention)
  • Shows contextual information (FIRST VERSION badge, change notes, or rename info)

Comment on lines +882 to +885
if (
not self._has_published_run_changed(published_run=pr, **updates)
and self.is_published_run_version
):
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical bug: Method not called - missing parentheses.

self.is_published_run_version is a method reference, not a method call. Without (), it evaluates to the method object itself (always truthy), causing the condition to incorrectly block publishing even when not viewing a version.

             if (
                 not self._has_published_run_changed(published_run=pr, **updates)
-                and self.is_published_run_version
+                and self.is_published_run_version()
             ):
🤖 Prompt for AI Agents
In daras_ai_v2/base.py around lines 882 to 885, the condition uses
self.is_published_run_version as a method reference instead of calling it, so it
always evaluates truthy and blocks publishing; change it to call the method
(self.is_published_run_version()) so the boolean result is used, and optionally
wrap with bool(...) if explicit casting is desired.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (4)
daras_ai_v2/base.py (4)

240-240: Unused version_id parameter.

The version_id parameter is declared but never used in the method body. It's already passed via query_params at the call site in _render_version_row (line 1300).


434-442: Missing exception handling for invalid version_id.

If an invalid version_id is provided, pr.versions.get(version_id=version_id) will raise PublishedRunVersion.DoesNotExist, causing an unhandled 500 error.

     version_id = self.request.query_params.get("version_id", None)
     pr_version = None
     if version_id:
-        pr_version = pr.versions.get(version_id=version_id)
-
-        if pr_version and self.current_pr:
+        try:
+            pr_version = pr.versions.get(version_id=version_id)
+        except PublishedRunVersion.DoesNotExist:
+            pr_version = None
+        else:
             self.current_pr.title = pr_version.title
             self.current_pr.notes = pr_version.notes
             self.current_pr.photo_url = pr_version.photo_url

512-512: Ambiguous operator precedence - add parentheses for clarity.

Python evaluates self.tab == RecipeTabs.run and is_example or pr_version as (self.tab == RecipeTabs.run and is_example) or pr_version. Add explicit parentheses to clarify intent:

-        if self.tab == RecipeTabs.run and is_example or pr_version:
+        if (self.tab == RecipeTabs.run and is_example) or pr_version:

882-885: Critical bug: Method not called - missing parentheses.

self.is_published_run_version is a method reference, not a method call. Without (), it evaluates to the method object itself (always truthy), causing the condition to incorrectly trigger "No changes to publish" error even when not viewing a version.

             if (
                 not self._has_published_run_changed(published_run=pr, **updates)
-                and self.is_published_run_version
+                and self.is_published_run_version()
             ):
🧹 Nitpick comments (1)
widgets/saved_workflow.py (1)

38-42: Mutating published_run in-place may cause unexpected side effects.

This function modifies the passed published_run object directly. If the caller retains a reference to this object (e.g., version.published_run in _render_version_row), subsequent code may see the mutated values unexpectedly.

Consider working with a shallow copy or documenting this side effect explicitly:

+    # Note: This function mutates published_run fields when version is provided
     if version:
         published_run.title = version.title
         published_run.notes = version.notes
         published_run.photo_url = version.photo_url
         published_run.last_edited_by = version.changed_by

Alternatively, if isolation is needed:

if version:
    published_run = copy(published_run)
    published_run.title = version.title
    # ...
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0b14c2 and d7d5dac.

📒 Files selected for processing (2)
  • daras_ai_v2/base.py (7 hunks)
  • widgets/saved_workflow.py (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • widgets/saved_workflow.py
  • daras_ai_v2/base.py
🧠 Learnings (3)
📚 Learning: 2025-09-24T07:23:39.522Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:23:39.522Z
Learning: In `widgets/workflow_search.py`, the `render_search_results()` function QuerySet at line 375 needs `.select_related("workspace", "saved_run", "last_edited_by").prefetch_related("tags", "versions")` to avoid N+1 queries when rendering search results with published run previews. Note: `created_by` should not be included as it's not used in workflow rendering.

Applied to files:

  • widgets/saved_workflow.py
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_saved_tab()` method QuerySet at line 2199 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to avoid N+1 queries when rendering published runs.

Applied to files:

  • daras_ai_v2/base.py
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_examples_tab()` method QuerySet at line 2164 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to optimize database queries for published run rendering.

Applied to files:

  • daras_ai_v2/base.py
🧬 Code graph analysis (2)
widgets/saved_workflow.py (3)
bots/models/published_run.py (2)
  • PublishedRunVersion (349-392)
  • PublishedRun (118-346)
widgets/demo_button.py (1)
  • get_demo_bots (41-50)
bots/models/bot_integration.py (4)
  • Platform (28-75)
  • get_icon (36-51)
  • get_title (53-60)
  • get_demo_button_color (62-75)
daras_ai_v2/base.py (1)
widgets/saved_workflow.py (1)
  • render_saved_workflow_preview (25-102)
🪛 Ruff (0.14.6)
daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


512-512: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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: test (3.10.12, 1.8.3)
🔇 Additional comments (4)
widgets/saved_workflow.py (1)

105-139: LGTM!

The hide_demo_pills parameter is cleanly threaded through to conditionally skip demo pill rendering. The styling and pill construction logic is well-structured.

daras_ai_v2/base.py (3)

490-494: LGTM!

The unpublished changes indicator logic correctly uses self.is_published_run_version() with parentheses.


953-954: LGTM!

The is_published_run_version() method correctly checks for presence of version_id in query params.


1296-1332: LGTM!

The version row rendering is well-structured:

  • Properly passes version_id via query_params
  • Uses the new version parameter in render_saved_workflow_preview
  • Clean version card styling with hover effect
  • Appropriate "FIRST VERSION" badge and change notes display

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
daras_ai_v2/breadcrumbs.py (1)

77-83: Empty H1 title when version.title is blank—add fallback to page_cls.get_recipe_title().

Lines 80–83: PublishedRunVersion.title defaults to an empty string and can legitimately be left blank. The current logic:

version.title if version else page_cls.get_recipe_title(),

will render an empty H1 even though a recipe title exists. The title_with_prefix() method (lines 29–31) explicitly guards against empty titles, confirming this is a UI bug.

Apply the fallback pattern already used in the is_example case (lines 91–94):

(version.title or page_cls.get_recipe_title()) if version else page_cls.get_recipe_title(),

This ensures version-specific titles display when provided, but always guarantees a non-empty H1.

♻️ Duplicate comments (1)
daras_ai_v2/breadcrumbs.py (1)

60-62: Fix ambiguous is_example expression and ensure it is boolean.

As Ruff noted and a previous review mentioned, the current expression:

is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version

relies on and/or precedence and can assign is_example to a non-boolean value (e.g., sr.parent_version or pr). This is harder to read and may confuse future changes.

You can keep the existing truthiness while making the intent explicit and forcing a boolean:

-    is_example = not is_root and pr and pr.saved_run == sr or sr.parent_version
+    is_example = (not is_root and pr and pr.saved_run == sr) or bool(sr.parent_version)

This preserves the logic (“example if a non-root PR for this sr, or if sr.parent_version exists”) while making is_example always a bool and clarifying precedence.

🧹 Nitpick comments (1)
daras_ai_v2/breadcrumbs.py (1)

51-57: Confirm intended usage surface for the new version parameter.

The version: PublishedRunVersion | None = None parameter is currently only used in the root (is_root) branch for the h1 title, and not in the example/run branches. If the goal is strictly to override the root breadcrumb title when a version is active, this is fine; if you also expect version-specific titles when viewing non-root runs, you may want to thread version into the is_example/is_run branches as well.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7d5dac and 4d196c8.

📒 Files selected for processing (2)
  • daras_ai_v2/breadcrumbs.py (4 hunks)
  • widgets/saved_workflow.py (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • widgets/saved_workflow.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/breadcrumbs.py
🧠 Learnings (2)
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_saved_tab()` method QuerySet at line 2199 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to avoid N+1 queries when rendering published runs.

Applied to files:

  • daras_ai_v2/breadcrumbs.py
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_examples_tab()` method QuerySet at line 2164 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to optimize database queries for published run rendering.

Applied to files:

  • daras_ai_v2/breadcrumbs.py
🧬 Code graph analysis (1)
daras_ai_v2/breadcrumbs.py (3)
bots/models/published_run.py (2)
  • PublishedRunVersion (349-392)
  • is_root (282-283)
routers/root.py (1)
  • RecipeTabs (893-937)
daras_ai_v2/base.py (1)
  • get_recipe_title (1182-1183)
🪛 Ruff (0.14.6)
daras_ai_v2/breadcrumbs.py

61-61: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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: test (3.10.12, 1.8.3)
🔇 Additional comments (2)
daras_ai_v2/breadcrumbs.py (2)

5-5: Import of PublishedRunVersion is appropriate and consistent.

The explicit import matches the new version: PublishedRunVersion | None parameter type and keeps the dependency clear; no further changes needed here.


107-109: Spacing change is harmless.

The added blank line after prompt_title = ... is purely cosmetic and does not affect behavior; no change needed.

@anish-work anish-work force-pushed the fix_pr_version_title_notes branch from 4d196c8 to 9e57851 Compare November 27, 2025 14:54
@anish-work anish-work force-pushed the fix_pr_version_title_notes branch from 452c08a to 7116a44 Compare November 27, 2025 17:13
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (4)
daras_ai_v2/base.py (4)

232-242: Unused version_id arg in app_url and missing propagation from current_app_url.

version_id is accepted by app_url but never used, and current_app_url does not carry version_id from self.request.query_params, so version-aware views lose context in generated URLs and static analysis flags the arg as unused.

You can wire this through and satisfy Ruff like this:

@@
     def current_app_url(
         self,
         tab: RecipeTabs = RecipeTabs.run,
         *,
         query_params: dict[str, str] | None = None,
         path_params: dict | None = None,
     ) -> str:
         if query_params is None:
             query_params = {}
-        example_id, run_id, uid = extract_query_params(self.request.query_params)
+        example_id, run_id, uid = extract_query_params(self.request.query_params)
+        version_id = self.request.query_params.get("version_id")
+        if version_id is not None:
+            query_params.setdefault("version_id", version_id)
         return self.app_url(
             tab=tab,
             example_id=example_id,
             run_id=run_id,
             uid=uid,
+            version_id=version_id,
             query_params=query_params,
             path_params=path_params,
         )
@@
     def app_url(
         cls,
@@
-        version_id: str | None = None,
+        version_id: str | None = None,
         query_params: dict[str, str] | None = None,
         path_params: dict | None = None,
     ) -> str:
@@
-        if query_params is None:
-            query_params = {}
+        if query_params is None:
+            query_params = {}
+
+        if version_id is not None:
+            query_params.setdefault("version_id", str(version_id))

490-495: Clarify header conditions for “Unpublished changes” and notes display.

Two small issues here:

  1. is_published_run_version() makes the “Unpublished changes” pill show for any historical version, even when nothing actually changed; if that’s meant as “you’re viewing an old version”, consider a separate indicator instead of overloading this pill.
  2. if self.tab == RecipeTabs.run and is_example or pr_version: is hard to read; the and/or precedence is non-obvious and Ruff flags it.

Minimal, behavior-preserving tweak:

@@
-                                if (
-                                    request_changed
-                                    or (can_save and not is_example)
-                                    or self.is_published_run_version()
-                                ):
+                                if (
+                                    request_changed
+                                    or (can_save and not is_example)
+                                    or self.is_published_run_version()
+                                ):
@@
-        if self.tab == RecipeTabs.run and is_example or pr_version:
+        if (self.tab == RecipeTabs.run and is_example) or pr_version:
             with gui.div(className="container-margin-reset"):
                 if self.current_pr and self.current_pr.notes:
                     gui.write(self.current_pr.notes, line_clamp=3)

(If the intent is “only show notes on the Run tab”, you may instead want if self.tab == RecipeTabs.run and (is_example or pr_version):.)

Also applies to: 512-515


432-443: Protect pr.versions.get(version_id=...) from invalid/unknown version_id.

A bad or stale version_id in the URL will raise PublishedRunVersion.DoesNotExist (or ValueError on bad types) and 500 the page.

Consider making the lookup tolerant and only overriding current_pr when a version is actually found:

@@
-        sr, pr = self.current_sr_pr
-        is_example = pr.saved_run == sr
-        version_id = self.request.query_params.get("version_id", None)
-        pr_version = None
-        if version_id:
-            pr_version = pr.versions.get(version_id=version_id)
-
-            if pr_version and self.current_pr:
-                self.current_pr.title = pr_version.title
-                self.current_pr.notes = pr_version.notes
-                self.current_pr.photo_url = pr_version.photo_url
+        sr, pr = self.current_sr_pr
+        is_example = pr.saved_run == sr
+        version_id = self.request.query_params.get("version_id")
+        pr_version: PublishedRunVersion | None = None
+        if version_id:
+            try:
+                pr_version = pr.versions.get(version_id=version_id)
+            except (PublishedRunVersion.DoesNotExist, ValueError):
+                pr_version = None
+
+        if pr_version and self.current_pr:
+            self.current_pr.title = pr_version.title
+            self.current_pr.notes = pr_version.notes
+            self.current_pr.photo_url = pr_version.photo_url

882-885: is_published_run_version used as a method reference, not called.

In the publish form, this condition currently always uses a truthy method object, so it reduces to just “no changes to publish”, regardless of whether you’re viewing a historical version:

if (
    not self._has_published_run_changed(published_run=pr, **updates)
    and self.is_published_run_version
):

If the goal is to gate this branch only when viewing a version-specific URL, you need to call the method:

@@
-            if (
-                not self._has_published_run_changed(published_run=pr, **updates)
-                and self.is_published_run_version
-            ):
+            if (
+                not self._has_published_run_changed(published_run=pr, **updates)
+                and self.is_published_run_version()
+            ):
                 gui.error("No changes to publish", icon="⚠️")
                 return
@@
-    def is_published_run_version(self) -> bool:
-        return self.request.query_params.get("version_id", None) is not None
+    def is_published_run_version(self) -> bool:
+        return self.request.query_params.get("version_id") is not None

Also applies to: 953-955

🧹 Nitpick comments (2)
daras_ai_v2/base.py (2)

1283-1290: Version history rendering looks good; consider prefetching changed_by for performance.

The new card UI for versions is a nice UX improvement. However, _render_version_history fetches self.current_pr.versions.all() and _render_version_row accesses version.changed_by, which can cause N+1 queries on large histories.

You can cheaply avoid that:

@@
     def _render_version_history(self):
-        versions = self.current_pr.versions.all()
+        versions = self.current_pr.versions.select_related("changed_by").all()
         first_version = versions[0]
         for version, older_version in pairwise(versions):
             first_version = older_version
             self._render_version_row(version, older_version)
         self._render_version_row(first_version, None)

Also applies to: 1291-1339


2257-2277: Add select_related/prefetch_related on examples/saved tabs to avoid N+1 queries.

Both _examples_tab and _saved_tab render PublishedRun cards (via render_saved_workflow_preview) but build qs without any select_related / prefetch_related, which can be expensive when you hit related saved_run, workspace, tags, or versions.

Based on prior perf learnings for this file, something like this would help:

@@
     def _examples_tab(self):
-        qs = PublishedRun.objects.filter(
-            PublishedRun.approved_example_q(),
-            workflow=self.workflow,
-        )
+        qs = (
+            PublishedRun.objects.filter(
+                PublishedRun.approved_example_q(),
+                workflow=self.workflow,
+            )
+            .select_related("saved_run", "workspace", "last_edited_by")
+            .prefetch_related("tags", "versions")
+        )
@@
     def _saved_tab(self):
@@
-        qs = PublishedRun.objects.filter(Q(workflow=self.workflow) & pr_filter)
+        qs = (
+            PublishedRun.objects.filter(Q(workflow=self.workflow) & pr_filter)
+            .select_related("saved_run", "workspace", "last_edited_by")
+            .prefetch_related("tags", "versions")
+        )

Based on learnings, this should eliminate N+1s when rendering these lists.

Also applies to: 2282-2298

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e57851 and 6cf9d30.

📒 Files selected for processing (1)
  • daras_ai_v2/base.py (7 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{py,js,ts,tsx,java,cs,cpp,c,go,rb,php}

📄 CodeRabbit inference engine (.cursor/rules/devs-rules.mdc)

Format code in reverse topological order: place the main() function at the top and dependencies below it

Files:

  • daras_ai_v2/base.py
🧠 Learnings (2)
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_saved_tab()` method QuerySet at line 2199 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to avoid N+1 queries when rendering published runs.

Applied to files:

  • daras_ai_v2/base.py
📚 Learning: 2025-09-24T07:06:56.185Z
Learnt from: nikochiko
Repo: GooeyAI/gooey-server PR: 792
File: widgets/saved_workflow.py:0-0
Timestamp: 2025-09-24T07:06:56.185Z
Learning: In `daras_ai_v2/base.py`, the `_examples_tab()` method QuerySet at line 2164 needs `.select_related('saved_run', 'workspace', 'last_edited_by').prefetch_related('tags', 'versions')` to optimize database queries for published run rendering.

Applied to files:

  • daras_ai_v2/base.py
🪛 Ruff (0.14.6)
daras_ai_v2/base.py

240-240: Unused class method argument: version_id

(ARG003)


512-512: Parenthesize a and b expressions when chaining and and or together, to make the precedence clear

Parenthesize the and subexpression

(RUF021)

⏰ 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). (2)
  • GitHub Check: test (3.10.12, 1.8.3)
  • GitHub Check: test (3.10.12, 1.8.3)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants