Skip to content

feat: Add a panel to invoke and talk with Seer#318

Open
ryan953 wants to merge 2 commits intomainfrom
ryan953/seer-panel
Open

feat: Add a panel to invoke and talk with Seer#318
ryan953 wants to merge 2 commits intomainfrom
ryan953/seer-panel

Conversation

@ryan953
Copy link
Member

@ryan953 ryan953 commented Jan 24, 2026

This is a first-draft to get Seer Explorer output into the toolbar.

SCR-20260124-nfqd

@ryan953 ryan953 requested a review from a team as a code owner January 24, 2026 22:56
@github-actions
Copy link

github-actions bot commented Jan 24, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • Add a panel to invoke and talk with Seer by ryan953 in #318

Bug Fixes 🐛

  • (auth) When login doesnt connect fully, allow logout by ryan953 in #316

Internal Changes 🔧

Release

  • Fix changelog-preview permissions by BYK in #315
  • Switch from action-prepare-release to Craft by BYK in #312

Other

  • Add some config/setup for claude by ryan953 in #317
  • Use pull_request_target for changelog preview by BYK in #313

🤖 This preview updates automatically when you update the PR.

headers: {
...init.headers,
...bearer,
...csrf,
Copy link

Choose a reason for hiding this comment

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

Undefined variable csrf causes runtime error

High Severity

The variable csrf is referenced in the headers object on line 101 (...csrf), but its declaration on line 94 is commented out. This causes a ReferenceError: csrf is not defined when fetchProxy is invoked, breaking all API calls made through the toolbar's fetch proxy.

Additional Locations (1)

Fix in Cursor Fix in Web

isSubmitting,
}: PendingUserInputProps) {
const [selectedAnswers, setSelectedAnswers] = useState<Record<string, string>>({});
const [selectedPatches, setSelectedPatches] = useState<number[]>([]);
Copy link

Choose a reason for hiding this comment

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

Stale selection state persists across different pending inputs

Medium Severity

The selectedPatches and selectedAnswers state in PendingUserInput is initialized once and never resets when the pendingInput prop changes. Since no key prop is provided when rendering the component, React reuses the same instance. This causes stale selections to carry over between different pending inputs — the "Approve Selected" button may display an incorrect count, and invalid patch indices may be submitted to the server.

Additional Locations (1)

Fix in Cursor Fix in Web

const [{organizationSlug}] = useConfigContext();
const {fetchFn} = useSentryApi<SeerExplorerSessionResponse>();
const pollingStartTimeRef = useRef<number | null>(null);
const pollCountRef = useRef<number>(0);
Copy link

Choose a reason for hiding this comment

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

Polling timeout refs persist incorrectly across session changes

Medium Severity

The pollingStartTimeRef and pollCountRef refs in useSeerExplorerSession persist across runId changes. When a user switches from one actively-polling session to another, the 5-minute timeout continues from where the previous session left off rather than resetting. This can cause polling to stop prematurely for the new session, leaving users with stale data.

Fix in Cursor Fix in Web

queryClient.invalidateQueries({
queryKey: [`/organizations/${organizationSlug}/seer/explorer-chat/`],
});
},
Copy link

Choose a reason for hiding this comment

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

Session query not invalidated when continuing existing chat

Medium Severity

The onSuccess handler in useSeerExplorerChat invalidates queries with key ['/organizations/.../seer/explorer-chat/'], but when continuing an existing chat, the session query uses key ['/organizations/.../seer/explorer-chat/${runId}/']. These keys don't match, so the session query isn't invalidated. When a user sends a message to an existing session, the UI won't update immediately — the sent message only appears after polling kicks in, causing a noticeable delay.

Fix in Cursor Fix in Web

Add access control for the Seer Explorer panel based on organization
feature flags. The panel is only shown when the organization has both
`seer-explorer` and either `seer-billing` or `seat-based-seer-enabled`.

- Add useSeerExplorerAccess hook to check feature flag access
- Hide nav button when user lacks access
- Add RequireSeerExplorer route guard to prevent direct URL access
{query: inputValue, runId: currentRunId},
{
onSuccess: data => {
const newRunId = data.json.run_id;
Copy link

Choose a reason for hiding this comment

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

Bug: The onSuccess callback accesses data.json.run_id without checking if data.json is defined, which can be undefined if the API response body fails to parse.
Severity: MEDIUM

Suggested Fix

Add a check in the onSuccess callback to ensure data.json is not undefined before accessing its properties. Optional chaining (data.json?.run_id) can be used for a concise and safe access pattern.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/lib/components/panels/seerExplorer/SeerExplorerPanel.tsx#L58

Potential issue: The `onSuccess` callback for the `sendMessage` mutation in
`SeerExplorerPanel.tsx` directly accesses `data.json.run_id`. The underlying
`useSentryApi` hook uses `tryJsonParse`, which returns `undefined` if the API response
body is not valid JSON. However, the hook does not throw an error for JSON parsing
failures on successful HTTP status codes (e.g., 200 OK). If the API returns a 200 OK
response with a malformed or non-JSON body, `data.json` will be `undefined`, causing a
`TypeError` when the code attempts to access `data.json.run_id`.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment on lines +22 to +23
const [selectedAnswers, setSelectedAnswers] = useState<Record<string, string>>({});
const [selectedPatches, setSelectedPatches] = useState<number[]>([]);
Copy link

Choose a reason for hiding this comment

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

Bug: The PendingUserInput component lacks a key prop. Its internal state will persist across different user prompts, potentially causing stale data to be submitted.
Severity: MEDIUM

Suggested Fix

In SeerExplorerPanel.tsx, add a unique key prop to the PendingUserInput component, using the ID of the pending input. For example: <PendingUserInput key={session.pending_user_input.id} ... />. This will ensure React remounts the component with fresh state whenever the pending input changes.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: src/lib/components/panels/seerExplorer/PendingUserInput.tsx#L22-L23

Potential issue: The `PendingUserInput` component is rendered without a unique `key`
prop. When the `session.pending_user_input` data is updated after a user submission,
React will reuse the existing component instance instead of mounting a new one. This
causes the component's internal state (e.g., `selectedAnswers`) to persist from the
previous prompt. If a user is presented with a sequence of questions, the state from the
first question could be incorrectly submitted as part of the response to the second
question, leading to incorrect behavior or data corruption.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

queryClient.invalidateQueries({
queryKey: [`/organizations/${organizationSlug}/seer/explorer-chat/`],
});
},
Copy link

Choose a reason for hiding this comment

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

Runs list not invalidated after creating new session

Low Severity

The onSuccess callback in useSeerExplorerChat only invalidates session queries (/seer/explorer-chat/) but not the runs query (/seer/explorer-runs/). When a user creates a new session and then opens the History panel, the newly created session won't appear in the list until a refetch is triggered by window focus or navigation.

Fix in Cursor Fix in Web

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.

1 participant