# fix\(web\): keep unsaved edits to other ACP providers · PR \#23847 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23847)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: open

Source repository: Unavailable fork

Source branch: r13/b137-saving-one-acp-provider-keeps-unsaved-ed

Target branch: main

Head commit: 291b5f6a2603ebd73950a8b2b4a2ac99bdef5950

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23847)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23847/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23847/diffs?format=markdown)

## Description

---

## Problem

Editing more than one row under Settings → Providers → Agent providers can lose work. Saving or disabling the first provider refetches the provider list and rebuilds every draft. That replaces another row's unsaved URL with its saved URL and clears any headers the user has typed there.

The rows have separate Save buttons, so saving one row should leave the other row's pending edits available. Headers are write-only, which makes accidentally discarding them particularly frustrating.

To reproduce with an ACP agent that advertises two configurable providers:

1. List its providers and edit both rows.
2. Enter a different base URL and headers JSON in the second row.
3. Save or disable the first row.
4. When the provider list reload succeeds, the second row loses its URL edit and typed headers. (A reload sent immediately can fail while the agent's capability probe runs; that separate failure leaves drafts untouched.)

## Change

Pass the saved or disabled provider ID into the list reload. Reset that provider's draft from the returned configuration and clear its consumed headers. Preserve existing drafts for the other returned providers.

The merge reads the latest React state, so it also retains edits made while the refetch is pending. Providers newly returned by the agent get a draft from their configuration. The explicit Refresh action still rebuilds all drafts.

This stays within the existing component. It adds no draft store, dirty-state tracking, API changes, or settings.

## Scope and approval

This is a small, focused fix for an obvious loss of unsaved form data, under the focused-bug exception in CONTRIBUTING.md. It does not add a workflow or change provider configuration policy. No prior issue or discussion was found for this defect.

Prior PRs: No earlier PR or issue for this same fix was found. The current component and its existing permission tests are retained.

## Verification

- Against base `05696c636e`, the final regression test fails for both Save and Disable with the saved URL instead of the concurrently edited URL. The restored production source was checked byte for byte against the base.
- On `291b5f6a26`, `cd apps/web && pnpm exec vp test run --project browser src/components/settings/AcpSessionManagementSection.browser.test.tsx` passes all four tests. The new cases control the refetch with a deferred response and edit the other row again before resolving it. They also check that the acted-on row clears its headers and that Refresh resets the other row.
- `pnpm exec vp fmt --check` and `pnpm exec vp lint` on the two changed files pass. `pnpm --filter @t3tools/web typecheck` passes.
- Production web builds pass for base and candidate. Both were driven in Chrome 156 on Linux with separate app state and home directories. The unchanged production server bundle served each web build.
- The real-app flow used the repository's mock ACP agent, extended only in the evidence setup to advertise two providers and persist their non-secret routing configuration. Both builds used the same setup. Provider-list messages were forwarded unchanged after a 1.5-second delay so the server's background capability probe completed before the refetch. Save and Disable reset the second row on base and preserve it on the candidate. Explicit Refresh resets it on the candidate.

Not checked:

- Native desktop packaging, mobile clients, or other operating systems.
- Real provider accounts or production credentials.
- The separate transient capability-probe failure on an immediate refetch.
- The full repository test suite.

Both rows edited before saving the first row:

![Edited provider rows](https://gist.githubusercontent.com/only21mil/c0f26818e471a4f04b6c993f396f16bd/raw/962ad103698197be51d4ca42e29be43346f1db4d/edited-providers.png)

After Save, base loses the second row's edits; the candidate keeps them:

![Base and candidate after Save](https://gist.githubusercontent.com/only21mil/c0f26818e471a4f04b6c993f396f16bd/raw/962ad103698197be51d4ca42e29be43346f1db4d/save-comparison.png)

After Disable, base loses the second row's edits; the candidate keeps them:

![Base and candidate after Disable](https://gist.githubusercontent.com/only21mil/c0f26818e471a4f04b6c993f396f16bd/raw/962ad103698197be51d4ca42e29be43346f1db4d/disable-comparison.png)

The regression cases fail against base production source:

![Regression failures on base](https://gist.githubusercontent.com/only21mil/c0f26818e471a4f04b6c993f396f16bd/raw/962ad103698197be51d4ca42e29be43346f1db4d/base-regression.png)

The focused browser file passes on the candidate:

![Passing focused browser tests](https://gist.githubusercontent.com/only21mil/c0f26818e471a4f04b6c993f396f16bd/raw/962ad103698197be51d4ca42e29be43346f1db4d/candidate-regression.png)

Production fix, tests, PR description and images written with GPT-6.1 Sol in T3 Code Nightly.

🤖 Generated with GPT-6.1 Sol in T3 Code Nightly

