feat(client): honor ?project= deep links so shared eval URLs land on the right project - #3643
Conversation
…the right project Eval/suite/run URLs carry no project segment, so a shared link rendered whatever project the viewer's picker was parked on — an empty state for everyone but the author. Now: - client: a ?project=<id> param switches the active project on load (switching organization first for cross-org links), then strips the param; unknown/no-access ids strip with a toast. The param also suppresses the first-run onboarding redirect (same clobber hazard as ?template). - server: the v1 agent endpoint appends ?project= to the suite deep links it returns in createdResources. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a2f12d99-72d9-47a9-acdb-9a298bfaf233) |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughThe client now supports Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
mcpjam-inspector/client/src/App.tsxOops! Something went wrong! :( ESLint: 8.57.1 Error: ESLint configuration in --config is invalid:
mcpjam-inspector/client/src/lib/__tests__/project-deep-link.test.tsOops! Something went wrong! :( ESLint: 8.57.1 Error: ESLint configuration in --config is invalid:
mcpjam-inspector/client/src/lib/project-deep-link.tsOops! Something went wrong! :( ESLint: 8.57.1 Error: ESLint configuration in --config is invalid:
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: 2
🤖 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 `@mcpjam-inspector/client/src/App.tsx`:
- Around line 892-897: Add a rejection handler to the promise chain in the
“switch-project” branch around handleSwitchProject so failures are surfaced
before clearProjectDeepLinkFromUrl still runs in finally. Reuse the surrounding
app’s established error-reporting or user-notification mechanism, while
preserving the existing handledRef update and successful project-switch
behavior.
In `@mcpjam-inspector/client/src/lib/project-deep-link.ts`:
- Around line 56-88: Update resolveProjectDeepLinkAction so a matching project
without organizationId returns { kind: "not-found" } unless it was already
handled by the active project checks. Preserve switch-organization for matches
with a different organizationId and wait only for projects belonging to the
active organization whose filtered visibility has not caught up.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a7e81bef-fe29-46d7-b7c6-85ffa9d71dd0
📒 Files selected for processing (5)
mcpjam-inspector/client/src/App.tsxmcpjam-inspector/client/src/lib/__tests__/project-deep-link.test.tsmcpjam-inspector/client/src/lib/project-deep-link.tsmcpjam-inspector/server/routes/v1/__tests__/agent.test.tsmcpjam-inspector/server/routes/v1/agent.ts
…s projects - switch-project now .catch()es before .finally(): a rejected handleSwitchProject was an unhandled rejection with the user silently left on the wrong project after the param was stripped. - an org-less matched project returns not-found under an active org filter (it can never enter the filtered set, so 'wait' hung forever); with no org filter it still waits for the unfiltered set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Review triage — both CodeRabbit findings verified as real and fixed in 36398e4:
13/13 lib tests, client typecheck clean. Cubic reported no issues. |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_204ec1b2-3258-4cb3-8e24-34d34b5ae4ff) |
Problem
Eval/suite/run URLs (
/evals/suite/:suiteId/runs/:runId) carry no project information — the page renders whatever project the viewer's client-side picker happens to be on. Any shared link (Slack bot messages, PR descriptions, pasted URLs) silently shows an empty state for anyone parked on a different project. Found while dogfooding the Slack bot (#3629): clicking a run link landed on an empty evals list because the picker was on another project.Fix
Client — new
client/src/lib/project-deep-link.ts+ auseProjectDeepLinkSwitchhook inApp.tsx:?project=<id>param switches the active project via the samehandleSwitchProjectpath the picker uses (membership-guarded, disconnects servers, persists), then strips the param viareplaceState— following the existing?plan=/?template=deep-link patterns.projects:getMyProjectsresult (same Convex query, deduped) resolves the project's organization; the hook switches org first, then the project on a later render.?template: onboarding would navigate away and drop the param before it's consumed). Unlike?template, membership can't be checked synchronously — but the handler always strips the param once data settles, including the no-access case, so suppression is transient by construction.handleSidebarSwitchProject: that variant navigates to a tab target, which would clobber the deep-linked path.Server — the v1 agent endpoint (
server/routes/v1/agent.ts) now appends?project=<projectId>to the suite URLs it returns increatedResources, so every link the Slack bot posts is self-describing.The decision logic is a pure function (
resolveProjectDeepLinkAction) so the ordering rules (clear / switch / switch-org / wait / not-found) are unit-tested without mounting App.Testing
client/src/lib/__tests__/project-deep-link.test.ts(11 tests: param parsing/shape rejection + all five action branches).agent.test.tsupdated to assert the?project=suffix on created-resource URLs (22 pass).typecheck:clientclean; server tsc has no errors in touched files.Out of scope
Path-based routing (
/projects/:projectId/...) is the structural fix but a full-app migration; this param approach is additive and doesn't block it.🤖 Generated with Claude Code
Note
Medium Risk
Changes active project and organization on initial load via membership-guarded switching; mistakes could leave users on the wrong project or show incorrect toasts, but it reuses the standard switch path and does not bypass auth.
Overview
Shared eval/suite/run URLs have no project in the path, so recipients often saw an empty list when their picker was on another project. This PR adds
?project=<id>handling so links can name the intended project.Client: New
project-deep-linkhelpers validate Convex-shaped ids, decide switch vs wait vs not-found (including cross-org org-switch-first), and strip the query param viareplaceState.useProjectDeepLinkSwitchinApp.tsxruns that logic through existinghandleSwitchProject(not sidebar navigation, so the deep-linked path is preserved). A valid?project=also blocks first-run onboarding from clobbering the URL before the handler runs.Server: The v1 agent’s suite URLs in
createdResourcesnow include?project=<projectId>so Slack-bot links are self-describing.Unit tests cover param parsing and all
resolveProjectDeepLinkActionbranches;agent.test.tsasserts the new URL shape.Reviewed by Cursor Bugbot for commit 36398e4. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Honor
?project=<id>deep links so shared eval/suite/run URLs open on the correct project. The client switches project/org on load and cleans the URL; the v1 agent appends the param to suite links it returns.New Features
?project=<id>, switches viahandleSwitchProject, then strips the param.resolveProjectDeepLinkActionwith unit tests.Bug Fixes
not-foundunder an active org filter;waitwhen no org filter is active.Written for commit 36398e4. Summary will update on new commits.