Skip to content

fix(admin-ui): add Chainlit chat shortcut - #635

Merged
hedhoud merged 4 commits into
refactor/hexagonalfrom
codex/admin-ui-chainlit-link
Jul 8, 2026
Merged

fix(admin-ui): add Chainlit chat shortcut#635
hedhoud merged 4 commits into
refactor/hexagonalfrom
codex/admin-ui-chainlit-link

Conversation

@hedhoud

@hedhoud hedhoud commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a small Chat button in the Admin UI header so admins and users can jump from the console to the Chainlit chat experience without manually changing URLs.

The link uses the existing same-origin /chainlit/ route, so it works through the Admin UI nginx proxy and does not hardcode a server IP or backend port.

Validation

  • npm test -- --run src/components/layout/header.test.tsx
  • npm run lint
  • npm run build
  • Local compose visual check on http://localhost:8068/app/partitions

Notes

This is frontend-only. It does not change backend routing or authorization.

Summary by CodeRabbit

  • New Features
    • Added a new Chat button in the header for signed-in users when the chat experience is enabled; it opens in a new tab with proper security attributes.
    • Exposed a chainlit_enabled flag in admin/config and authenticated user info so the UI can conditionally show the button.
  • Tests
    • Added UI test coverage for the chat link’s presence and href behavior when enabled/disabled.
    • Extended integration tests to confirm chainlit_enabled is returned as a boolean.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@hedhoud, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 03421686-3894-4fed-830c-f2c5dcf1b2d7

📥 Commits

Reviewing files that changed from the base of the PR and between c75b8b4 and a88d141.

📒 Files selected for processing (2)
  • ui/src/components/layout/header.test.tsx
  • ui/src/components/layout/header.tsx
📝 Walkthrough

Walkthrough

Adds chainlit_enabled to backend admin/user responses, threads it through client types and mocks, and conditionally renders a Chat link in the header using the configured API base.

Changes

Chainlit availability flag

Layer / File(s) Summary
Runtime flags and backend responses
openrag/api/runtime_flags.py, openrag/api/main.py, openrag/api/routers/admin/users.py, tests/integration/api/test_users.py, ui/src/mocks/handlers.ts
Defines shared runtime flags, adds chainlit_enabled to /config and /users/info, documents the users response field, and updates integration and mock payloads.
API URL helper and header chat link
ui/src/lib/api/client.ts, ui/src/lib/api/account.ts, ui/src/components/layout/header.tsx
Adds apiUrl for request URL construction, extends MyInfo with chainlit_enabled, and renders the conditional Chat link in the header.
Header and API validation
ui/src/components/layout/header.test.tsx, ui/src/mocks/handlers.ts
Covers the enabled, base-URL, and disabled header cases and keeps mock /users/info and /config payloads aligned with the new flag.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • linagora/openrag#606: Both PRs touch openrag/api/main.py around WITH_CHAINLIT_UI handling and Chainlit-related backend wiring.
  • linagora/openrag#615: Both PRs modify the /config admin endpoint in openrag/api/main.py.
  • linagora/openrag#616: Both PRs change Chainlit enablement flow in the backend and related routing behavior.

Suggested labels: fix

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a Chainlit chat shortcut to the admin UI.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/admin-ui-chainlit-link

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ui/src/components/layout/header.test.tsx (1)

30-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider asserting the rel attribute too.

The test checks href and target but not rel="noopener noreferrer", which is the security-relevant attribute added alongside target="_blank".

✅ Suggested addition
     const chatLink = screen.getByRole("link", { name: /chat/i });
     expect(chatLink.getAttribute("href")).toBe("/chainlit/");
     expect(chatLink.getAttribute("target")).toBe("_blank");
+    expect(chatLink.getAttribute("rel")).toBe("noopener noreferrer");
🤖 Prompt for 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.

In `@ui/src/components/layout/header.test.tsx` around lines 30 - 32, The header
link test currently verifies href and target on chatLink but misses the
security-related rel attribute. Update the existing assertion block in
header.test.tsx to also check that the link rendered by the header component
includes rel="noopener noreferrer" alongside target="_blank", using the same
screen.getByRole("link", { name: /chat/i }) query.
🤖 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.

Nitpick comments:
In `@ui/src/components/layout/header.test.tsx`:
- Around line 30-32: The header link test currently verifies href and target on
chatLink but misses the security-related rel attribute. Update the existing
assertion block in header.test.tsx to also check that the link rendered by the
header component includes rel="noopener noreferrer" alongside target="_blank",
using the same screen.getByRole("link", { name: /chat/i }) query.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: db63cbff-ac95-4973-99fb-6a52a5bbddc5

📥 Commits

Reviewing files that changed from the base of the PR and between 96ba630 and d98ec2b.

📒 Files selected for processing (2)
  • ui/src/components/layout/header.test.tsx
  • ui/src/components/layout/header.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d98ec2b599

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/components/layout/header.tsx Outdated
@andyne13

andyne13 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Verified ✅ — same-origin /chainlit/ link works through the nginx proxy (no hardcoded host/port), target="_blank" is correctly paired with rel="noopener noreferrer", and the behavior is covered by header.test.tsx. CI green, no concerns. Good to merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
openrag/api/routers/admin/users.py (1)

30-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider reusing the module-level WITH_CHAINLIT_UI constant from main.py instead of re-parsing the env var.

_chainlit_enabled() duplicates the exact same os.getenv("WITH_CHAINLIT_UI", "true").lower() == "true" logic already defined at module level in openrag/api/main.py (line 95). While functionally equivalent, this creates two sources of truth for the same flag. If the parsing logic ever changes (e.g., accepting "1" or "yes"), one location may be missed.

If importing from main.py would create a circular dependency, consider extracting the constant to a shared config/settings module that both files can import.

Also applies to: 89-93

🤖 Prompt for 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.

In `@openrag/api/routers/admin/users.py` around lines 30 - 33, The
`_chainlit_enabled()` helper is duplicating the `WITH_CHAINLIT_UI` parsing logic
already defined at module level in `main.py`, creating two sources of truth.
Update the admin users router to reuse the shared `WITH_CHAINLIT_UI` value
instead of calling `os.getenv` again, and if importing from `main.py` would
introduce a circular dependency, move the flag into a shared config/settings
module that both `_chainlit_enabled()` and the `main.py` module-level constant
can import.
🤖 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.

Nitpick comments:
In `@openrag/api/routers/admin/users.py`:
- Around line 30-33: The `_chainlit_enabled()` helper is duplicating the
`WITH_CHAINLIT_UI` parsing logic already defined at module level in `main.py`,
creating two sources of truth. Update the admin users router to reuse the shared
`WITH_CHAINLIT_UI` value instead of calling `os.getenv` again, and if importing
from `main.py` would introduce a circular dependency, move the flag into a
shared config/settings module that both `_chainlit_enabled()` and the `main.py`
module-level constant can import.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6e38b2d2-ab35-4131-8bf3-b2ca2481d0c3

📥 Commits

Reviewing files that changed from the base of the PR and between d98ec2b and bf3409e.

📒 Files selected for processing (7)
  • openrag/api/main.py
  • openrag/api/routers/admin/users.py
  • tests/integration/api/test_users.py
  • ui/src/components/layout/header.test.tsx
  • ui/src/components/layout/header.tsx
  • ui/src/lib/api/account.ts
  • ui/src/mocks/handlers.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/src/components/layout/header.test.tsx
  • ui/src/components/layout/header.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf3409e6d8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/src/components/layout/header.tsx Outdated
@Ahmath-Gadji

Copy link
Copy Markdown
Collaborator

On the token-mode UX gap for the new Chat shortcut: accepting the current behavior for this PR.

In token mode the shortcut opens Chainlit's login form (a one-time sign-in per Chainlit session), while OIDC mode is already seamless via the openrag_session cookie. It's a papercut, not a blocker — the same login anyone visiting /chainlit/ directly hits today — so we ship as-is and handle the seamless token-mode path post-release.

Tracked in #638.

@Ahmath-Gadji

Copy link
Copy Markdown
Collaborator

Bot review comments — disposition

All automated review comments are now addressed, so this is ready to validate:

Comment Source Status
Hide chat shortcut when Chainlit is disabled Codex (P2) ✅ Fixed in bf3409e6 — gated on chainlit_enabled (from WITH_CHAINLIT_UI), rendered only when user.chainlit_enabled === true
Assert rel="noopener noreferrer" in the header test CodeRabbit (nitpick) ✅ Already asserted in the final ui/src/components/layout/header.test.tsx
Respect the configured API origin for Chat Codex (P2) ➡️ By design — same-origin /chainlit/ matches the /auth/login SSO pattern; pointing it at VITE_API_BASE_URL would break Chainlit's front-door origin + OIDC cookie (details in thread)
Reuse WITH_CHAINLIT_UI instead of re-parsing the env in _chainlit_enabled() CodeRabbit (nitpick) ➡️ Intentional — importing it from api.main would be circular (main imports this router); the two reads are byte-identical env parses, so a shared module is disproportionate for one boolean

Follow-up (token-mode chat opens Chainlit's login instead of seamless SSO) is tracked separately in #638 and is out of scope here.

CI is green and the change is frontend-scoped.

@Ahmath-Gadji Ahmath-Gadji left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. Works fine

@hedhoud
hedhoud merged commit 8a4aa6a into refactor/hexagonal Jul 8, 2026
6 checks passed
@hedhoud
hedhoud deleted the codex/admin-ui-chainlit-link branch July 8, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Fix issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants