Skip to content

fix(seer): Route coding agent handoff CTA through seer/settings/#117622

Merged
billyvg merged 12 commits into
masterfrom
billy/seer-cta-settings-endpoint
Jun 19, 2026
Merged

fix(seer): Route coding agent handoff CTA through seer/settings/#117622
billyvg merged 12 commits into
masterfrom
billy/seer-cta-settings-endpoint

Conversation

@billyvg

@billyvg billyvg commented Jun 15, 2026

Copy link
Copy Markdown
Member

Problem

The Cursor/Claude coding agent integration CTA (codingAgentIntegrationCta.tsx, used by CursorIntegrationCta and ClaudeCodeIntegrationCta on the project Seer settings page) wired its "Set Seer to hand off to …" button through the legacy POST .../seer/preferences/ endpoint via useUpdateProjectSeerPreferences.

That endpoint looks up repos by (provider, owner, name, external_id) and strips whitespace from owner/name. For GitLab orgs with spaces in repo names (e.g. "My Group / My Repo"), every handoff setup returned {"detail": "Invalid repository"} (HTTP 400) — even though the CTA isn't editing repos. It only re-sent the existing repositories to preserve them through the coupled legacy payload.

Fix

Switch the write to useUpdateSeerSettings (PUT .../seer/settings/), which accepts agent, integrationId, stoppingPoint, and autoCreatePr with no repository lookup, making it immune to the whitespace bug. The defensive repo re-send is dropped since the settings endpoint never touches repository associations.

Payload mapping for handoff setup:

{agent: config.target, integrationId, stoppingPoint: 'root_cause', autoCreatePr: false}

This matches the handoff mapping established in #117526 for ProjectSeerGeneralForm.

Scope

Only the CTA's handoff write changes. The useProjectSeerPreferences read (used for the isConfigured check) and the useUpdateProject automation-enable call are unchanged.

Tests

Updated cursorIntegrationCta.spec.tsx and claudeCodeIntegrationCta.spec.tsx so the handoff-setup tests assert PUT .../seer/settings/ with the new payload instead of POST .../seer/preferences/. The read-side preferences mocks are unchanged.

Stacking

Stacked on #117526 (which introduces useUpdateSeerSettings). Merge that first.

Refs #117489
Fixes https://linear.app/getsentry/issue/CW-1527/failed-to-launch-coding-agent-with-anthropic-api-key

@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Jun 15, 2026
@billyvg billyvg changed the base branch from billy/fix-seer-stopping-point-settings-endpoint to master June 16, 2026 16:32
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jun 17, 2026
@billyvg billyvg force-pushed the billy/seer-cta-settings-endpoint branch from 279bd43 to e003e15 Compare June 17, 2026 16:35
@billyvg billyvg removed the Scope: Backend Automatically applied to PRs that change backend components label Jun 17, 2026
@getsentry getsentry deleted a comment from github-actions Bot Jun 17, 2026
@billyvg billyvg changed the base branch from master to billy/fix-seer-stopping-point-settings-endpoint June 17, 2026 16:38
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

📊 Type Coverage Diff

Metric Before After Delta
Coverage 93.70% 93.70% ±0%
Typed 133,103 133,102 🔴 -1
Untyped 8,949 8,953 🔴 +4
🔍 4 new type safety issues introduced

Type assertions (as) (4 new)

File Line Detail
static/app/views/settings/projectSeer/index.tsx 278 as AutofixAgentSelectOption — ``${CodingAgentProvider.CURSOR_BACKGROUND_AGENT}::${cursorIntegration.id} as Au…
static/app/views/settings/projectSeer/index.tsx 295 as AutofixAgentSelectOption — ``${CodingAgentProvider.CLAUDE_CODE_AGENT}::${claudeIntegration.id} as AutofixA…
static/app/views/settings/projectSeer/index.tsx 323 as AutofixAgentSelectOption — ``${setting.agent}::${setting.integrationId} as AutofixAgentSelectOption
static/app/views/settings/projectSeer/index.tsx 336 as AutofixAgentSelectOption — ``${setting.agent}::${integrationId} as AutofixAgentSelectOption

This is informational only and does not block the PR.

@billyvg billyvg force-pushed the billy/seer-cta-settings-endpoint branch from e003e15 to 9fd4f88 Compare June 17, 2026 16:57
@billyvg billyvg force-pushed the billy/fix-seer-stopping-point-settings-endpoint branch from 1b2a373 to 92420b3 Compare June 17, 2026 16:57
@ryan953 ryan953 force-pushed the billy/fix-seer-stopping-point-settings-endpoint branch from 92420b3 to 04d8646 Compare June 17, 2026 20:58
Base automatically changed from billy/fix-seer-stopping-point-settings-endpoint to master June 17, 2026 23:04
@billyvg billyvg force-pushed the billy/seer-cta-settings-endpoint branch from 9fd4f88 to 54c2332 Compare June 17, 2026 23:23
@linear-code

linear-code Bot commented Jun 18, 2026

Copy link
Copy Markdown

CW-1527

billyvg and others added 6 commits June 18, 2026 11:38
…ings/

handleStoppingPointChange, handleAutoCreatePrChange, and
handleIntegrationChange in ProjectSeerGeneralForm all called
useUpdateProjectSeerPreferences, which POSTs to the legacy
preferences endpoint. That endpoint looks up repos by
provider/owner/name and strips whitespace — the same bug that breaks
GitLab repo names — so any time a user on a GitLab org changed their
stopping point or coding agent, the request would fail with
{"detail": "Invalid repository"} (HTTP 400).

Fix by introducing useUpdateSeerSettings, which writes to the dedicated
PUT .../seer/settings/ endpoint. That endpoint accepts agent,
integrationId, stoppingPoint, and autoCreatePr with no repository
involvement, so the whitespace bug cannot be triggered.

Payload mapping per handler:
- cursor_handoff / claude_handoff: agent + integrationId + stoppingPoint + autoCreatePr
- plain stopping point: agent='seer' + stoppingPoint
- auto-create PR toggle: agent + integrationId + autoCreatePr
- integration switch: agent + new integrationId + autoCreatePr

This is the companion fix to #117518, which wired the repo add/delete
write path through PUT .../seer/repos/.

Fixes #117489

---
[View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0AKG192UP3%3A1781237406.446129%22)

Co-Authored-By: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Co-Authored-By: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
…Seer

Replace the project-scoped useProjectSeerPreferences read and the
useUpdateSeerSettings mutation in the project Seer settings page with the
shared getInfiniteSeerProjectsSettingsQueryOptions and
getMutateSeerProjectSettingsOptions. This routes reads and writes through
the same query cache as the bulk/table views so optimistic updates stay
consistent, and removes the now-unused useUpdateSeerSettings hook.
Drop the useMemo that translated SeerProjectSettingResponse into the legacy
ProjectSeerPreferences shape and read the setting fields directly in the
projectSeer form. This removes a lossy id round-trip (Number then String) and
a fabricated preferences object, leaving a single source of truth.
The Cursor/Claude integration CTA's "Set Seer to hand off" button wrote
through the legacy `POST seer/preferences/` endpoint, which looks up repos
by `(provider, owner, name, external_id)` and strips whitespace during the
lookup. For GitLab orgs with spaces in repo names this returned
`{"detail": "Invalid repository"}` (HTTP 400) — even though the CTA only
sets up handoff and re-sent the existing repos purely to preserve them.

Switch the write to `useUpdateSeerSettings` (`PUT seer/settings/`), which
derives the handoff config server-side from agent + stopping point +
autoCreatePr and never touches repository associations. The defensive repo
re-send is dropped.

Follows the same pattern as #117518 and #117526.

Refs #117489
…hook

Replace the custom useUpdateSeerSettings hook with the shared
getMutateSeerProjectSettingsOptions from seerProjectSettings.ts,
following conventions established in #117526.

- Delete useUpdateSeerSettings.ts (duplicated logic with worse cache
  management: invalidated the legacy preferences query instead of the
  seer settings query, and had no optimistic updates)
- Add autoCreatePr?: boolean to SeerProjectSettingUpdatePayload so it
  flows through getMutateSeerProjectSettingsOptions's ...rest spread
- Update codingAgentIntegrationCta.tsx to use
  getMutateSeerProjectSettingsOptions + knownAgentIntegrationsQueryOptions
  (same endpoint as old query, just maps providers to CodingAgentProvider)
- Update index.tsx similarly; filter integrations from AgentIntegration[]
  directly instead of using organizationIntegrationsCodingAgents
- Use agentOption provider::id string format throughout
- Update test expectations: integrationId is now a string, and
  automationTuning: medium is added when stoppingPoint is set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@billyvg billyvg force-pushed the billy/seer-cta-settings-endpoint branch from 54c2332 to 4132f10 Compare June 18, 2026 15:38
@billyvg

billyvg commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

@sentry review

Comment thread static/app/components/events/autofix/codingAgentIntegrationCta.tsx
The coding-agent CTA now reads handoff state from seer/settings/ instead of
seer/preferences/. Only fetch the per-project setting once an integration
exists, since without one the CTA short-circuits to the install card — this
avoids a wasted request and keeps the install-stage tests mock-free.

Migrate the CTA and projectSeer specs to mock GET seer/settings/ (keyed on
`agent`) instead of the now-unused seer/preferences/ + automation_handoff.
@billyvg

billyvg commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

I'm not exactly sure how to test the cta but the settings works

…API states"

This reverts commit c69e7f9.

Co-Authored-By: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
@billyvg billyvg marked this pull request as ready for review June 18, 2026 20:01
@billyvg billyvg requested review from a team as code owners June 18, 2026 20:01
@billyvg billyvg requested a review from ryan953 June 18, 2026 20:01
organization,
project,
queryClient,
knownAgents: knownAgents ?? [],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this should take undefined afaik

Suggested change
knownAgents: knownAgents ?? [],
knownAgents: knownAgents,

Comment thread static/app/views/settings/projectSeer/index.tsx
…ts arg

Address review feedback on #117622.

Restore the isKnownAgentsPending flag in ProjectSeer settings so the
integration, auto-create-PR, and stopping-point fields stay disabled
until known agents have loaded. Without it, changing the stopping point
before the integrations resolve would let parseAgentOption fall back to
'seer' and silently reset the configured handoff agent.

Pass knownAgents through directly instead of defaulting to an empty
array, since getMutateSeerProjectSettingsOptions already accepts
undefined.

Refs #117489
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@billyvg billyvg merged commit 7a2b95c into master Jun 19, 2026
71 checks passed
@billyvg billyvg deleted the billy/seer-cta-settings-endpoint branch June 19, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants