Skip to content

fix(desktop): stop create-agent form clobbering provider config on keystroke - #3220

Closed
IceRhymers wants to merge 1 commit into
block:mainfrom
IceRhymers:fix/provider-on-draft-change
Closed

fix(desktop): stop create-agent form clobbering provider config on keystroke#3220
IceRhymers wants to merge 1 commit into
block:mainfrom
IceRhymers:fix/provider-on-draft-change

Conversation

@IceRhymers

@IceRhymers IceRhymers commented Jul 27, 2026

Copy link
Copy Markdown

What

Fixes the create-agent form resetting provider config_schema fields to their schema defaults (or wiping them) on every keystroke, which made non-default values impossible to enter from the UI.

Fixes #3216.

Root cause

In desktop/src/features/agents/ui/WhereToRunSection.tsx, the provider-probe useEffect listed the entire draft in its dependency array. Every keystroke in ProviderConfigFields calls onDraftChange({ ...draft, providerConfig }), producing a new draft → the effect re-fires → the probe re-runs → on resolve it overwrites providerConfig with defaults rebuilt from config_schema. Against a fast local provider binary the probe is near-instant, so the field appears to reset on the keystroke itself.

Fields with a default snapped back to it; fields without one were wiped to empty. It's also a churn bug — one provider probe per keystroke.

Fix

  • Early-return guard if (draft.probedProvider) return; so the probe runs once per selection instead of on every draft change. Switching providers still re-probes correctly, because the "Run on" <select> resets the draft to emptyWhereToRunDraft (probedProvider: null).
  • On probe resolve, seed providerConfig: { ...defaults, ...draft.providerConfig } so a late-resolving probe can never erase values the user already typed (defense-in-depth).

Testing

  • just desktop-typecheck — pass
  • just desktop-test — pass
  • just desktop-check (Biome) — no findings on changed source

Testing against custom provider

Evidence of the fix, vs the video in #3216

Screen.Recording.2026-07-27.at.3.39.10.PM.mov

Notes

Discovered while building an out-of-tree backend provider (Databricks sandbox / Lakebox) that advertises a defaulted inference_auth field which couldn't be switched away from its default via the UI. No provider-side workaround exists — the reset is entirely client-side.

@IceRhymers
IceRhymers marked this pull request as ready for review July 27, 2026 22:43
@IceRhymers
IceRhymers requested a review from a team as a code owner July 27, 2026 22:43
…ystroke

The provider-probe effect in WhereToRunSection listed the whole `draft` in
its dependency array, so every keystroke in ProviderConfigFields produced a
new draft, re-ran the probe, and overwrote `providerConfig` with schema
defaults on resolve. Any config_schema field with a `default` snapped back to
it (fields without one were wiped), making non-default values impossible to
enter from the UI.

Guard against re-probing once a provider has been probed (a provider switch
still resets the draft to emptyWhereToRunDraft, so a fresh probe fires then),
and seed defaults without overwriting values the user already typed so a
late-resolving probe can't erase input.

Fixes block#3216

Signed-off-by: Tanner <84605639+IceRhymers@users.noreply.github.com>
@ashik112

ashik112 commented Aug 2, 2026

Copy link
Copy Markdown

Confirmed this exact failure with the out-of-tree buzz-backend-ssh provider from #3449 on macOS Desktop: the provider is discovered and its config_schema renders, but typing the required ssh_host value immediately resets the field. That isolates the failure to the client-side probe/draft loop fixed here and currently blocks creating an SSH remote agent through the released Desktop UI.

The successful provider discovery also confirms this is not an installation or provider-schema issue.

@IceRhymers

Copy link
Copy Markdown
Author

Superseded by #4411, which independently landed the broader tested fix for this issue.

@IceRhymers IceRhymers closed this Aug 4, 2026
heintonny pushed a commit to heintonny/buzz that referenced this pull request Aug 6, 2026
`WhereToRunSection` and `whereToRunIntent` are your components -- 126 and 46
lines on main. This commit grows them along the seam they already left: the
section keeps owning "where", and every field the answer scopes now reads from
it instead of assuming this computer.

The create dialog asked "where" last, or not at all. That ordering is wrong
once a host can be somewhere else, because every question below it is scoped by
the answer. The harness list comes from the chosen machine's catalog, and the
model list comes from that harness -- so asking at the end means answering the
dependent questions against the wrong computer and silently re-scoping them.
"Where to run" moves to the top of the form and the rest of the dialog becomes
a function of it:

- `createRuntimeGate` holds the local catalog's authority. A remote create must
  not require a locally installed harness (that would make every remote-only
  harness unsubmittable) and must not disable an "unavailable" option --
  availability describes the wrong machine.
- `useRemoteAwareModelDiscovery` routes discovery to whichever machine will run
  the agent. A picked remote harness REPLACES local discovery rather than
  merging with it; the local catalog answers for a computer the agent is never
  going to run on.
- `createGateHarnessId` decides whose credential contract applies. The deploy
  writes env on the host keyed off the remote command, so the local runtime id
  names the wrong contract.
- `createRunSection` becomes a render prop so the host's model probe can carry
  this dialog's unsaved credential env, which the global layer does not have yet.

`agentAiConfigurationPolicy` makes a typed model that the catalog does not know
block Save instead of silently resolving to the adapter's default at runtime.

This also fixes block#3220 more strongly than the fix proposed there: the `draftRef`
spread in `WhereToRunSection` keeps the section's draft authoritative across the
remount, so a rapid edit cannot be clobbered by an in-flight probe. Cited rather
than absorbed -- close block#3220 or land both, your call.

Extracting `AgentLlmProviderField` and `AgentDefinitionIdentityFields` keeps
`AgentDefinitionDialog` under its size cap; `shouldRenderModelControl` moves
beside `modelFieldStatus`, since both answer what the model catalog's state
means for the model control.

Signed-off-by: Troy Hoffman <troy.hoffman@icloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-ready Appropriate for agentic review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create-agent form resets provider config_schema fields to defaults on every keystroke

4 participants