Skip to content

fix(desktop): treat baked build env vars as satisfying required agent config#1580

Merged
wpfleger96 merged 3 commits into
mainfrom
wpfleger/baked-env-required-badge
Jul 7, 2026
Merged

fix(desktop): treat baked build env vars as satisfying required agent config#1580
wpfleger96 merged 3 commits into
mainfrom
wpfleger/baked-env-required-badge

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Problem

Internal Block builds bake provider credentials (e.g. DATABRICKS_HOST) into the binary at compile time via BUZZ_BUILD_AGENT_ENVBUZZ_DESKTOP_BUILD_AGENT_ENVbaked_build_env(). The backend readiness gate already honors this via resolve_effective_agent_env() Layer 1: an agent with provider databricks_v2 and no agent-local DATABRICKS_HOST IS ready on Block builds.

But the frontend requirement computation knew nothing about baked env. The result:

  • Edit/Create Agent dialogs showed a spurious amber Required badge on DATABRICKS_HOST for databricks_v2 agents on Block builds.
  • Since the EditAgentDialog refactor in refactor(desktop): unify EditAgentDialog styling with PersonaDialog #1540, missing required keys block Save — so Block users couldn't save a databricks_v2 agent without redundantly entering a DATABRICKS_HOST that's already baked in.

Mechanism

New Tauri command get_baked_build_env_keys in commands/agent_config.rs calls baked_build_env() and returns the key names only — never the values — so the frontend can evaluate satisfaction without exposing secrets. OSS builds return [] (empty baked env → no change).

New query useBakedBuildEnvKeysQuery() in hooks.ts (mirroring useRuntimeFileConfigQuery): staleTime: Infinity (compile-time constant), fails soft in web-dev/E2E contexts.

New pure function getBakedSatisfiedEnvKeys() in personaDialogPickers.tsx: a required key is baked-satisfied iff the agent has no local value for it AND bakedEnvKeys contains it.

Updated gate computeLocalModeGate() gains an optional bakedEnvKeys?: readonly string[] param. Baked-satisfied keys are removed from missingEnvKeys and produce no amber row or info row. Existing call sites are unaffected when the param is absent.

Three dialog consumers wired:

  • useRequiredCredentialState.ts — Edit dialog: baked keys excluded from requiredEnvKeys and requiredEnvKeyMissing (which drives Save blocking).
  • CreateAgentDialog.tsx — inline memos: baked keys excluded from amber rows.
  • PersonaDialog.tsxcomputeLocalModeGate call: bakedEnvKeys passed through.

If the user sets an agent-local value for a baked key it behaves like any normal env var and wins at spawn time — the backend already layers user env over baked env.

Related: #1448 (global agent variables touches computeLocalModeGate and will need a trivial rebase over this change — intended precedence when both land: baked < global < file for silencing, agent-local value always wins for display).

Related: #1582, #1583 (companion fixes for managed-agent configuration reliability).

… config

Internal (Block) builds bake provider credentials like DATABRICKS_HOST into
the binary via BUZZ_BUILD_AGENT_ENV. The backend readiness gate already
honors this via resolve_effective_agent_env() Layer 1, but the frontend
requirement computation was unaware, surfacing a spurious amber Required
badge on DATABRICKS_HOST and (since the EditAgentDialog refactor in #1540)
blocking Save in the Edit dialog.

New get_baked_build_env_keys Tauri command exposes key names only (never
values) from baked_build_env(). Frontend useBakedBuildEnvKeysQuery() +
getBakedSatisfiedEnvKeys() filter baked-satisfied keys out of requiredEnvKeys
and missingEnvKeys across all three dialog consumers (useRequiredCredentialState,
CreateAgentDialog, PersonaDialog), mirroring the existing file-config
satisfaction pattern. OSS builds return [] so OSS behavior is unchanged.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Architecture is right and nearly everything here is ready (review by Brain, posted via Wes's account): keys-only Tauri command so no secret values cross the bridge, staleTime: Infinity for a compile-time constant, getBakedSatisfiedEnvKeys requiring the agent-local value be empty (matching backend layer precedence), OSS no-op. CreateAgentDialog and useRequiredCredentialState wiring both correct — they filter !baked && !fileSatisfied, leaving filled keys in the amber locked row. The 8 new gate unit tests cover the baked branches.

One defect before merge — the requiredEnvKeys filter in PersonaDialog.tsx (~line 452):

.filter(
  (key) =>
    localModeGate.missingEnvKeys.includes(key) ||
    localModeGate.fileSatisfiedEnvKeys.includes(key),
)

This contradicts its own comment ("not baked-satisfied and not file-satisfied") and diverges from the other two consumers. Two consequences:

  1. File-satisfied keys render twice in EnvVarsEditor — in requiredKeys (amber row with a spurious empty-value "Required" badge) and in fileSatisfiedKeys ("Set in goose config" row). The old code excluded them from required for exactly this reason — this PR fixes the spurious badge for baked keys but introduces one for file-satisfied keys.
  2. Filled required keys fall out of the amber locked row. Previously a key with a typed value stayed in requiredEnvKeys (locked, masked input). Now a filled key is in neither missing nor fileSatisfied, so it drops into the normal editable rows — and the transition happens mid-typing: first character → key leaves missingEnvKeysskipKeys changes → EnvVarsEditor rebuilds rows → the input being typed into is replaced. Focus loss / row jump.

Fix is to mirror the other call sites:

const allKeys = requiredCredentialEnvKeys(runtime, trimmedProvider);
const bakedSatisfied = getBakedSatisfiedEnvKeys(allKeys, envVars, bakedEnvKeys);
const requiredEnvKeys = allKeys.filter(
  (key) =>
    !bakedSatisfied.includes(key) &&
    !localModeGate.fileSatisfiedEnvKeys.includes(key),
);

That preserves the pre-PR semantics exactly, minus baked keys — the stated intent. Everything else is good to go.

…and on baked-keys settle

Three bugs introduced in the initial baked-env PR:

1. PersonaDialog.tsx used allowlist semantics for requiredEnvKeys
   (include if in missingEnvKeys OR fileSatisfiedEnvKeys), which caused
   file-satisfied keys to render twice in EnvVarsEditor — once as an amber
   locked row and once as an info row — and caused filled required keys to
   drop out of the amber locked row on first character typed (focus loss).
   Fixed to exclusion semantics matching the other consumers: all required
   keys except baked-satisfied and file-satisfied ones.

2. useRequiredCredentialState auto-expanded the Advanced section before the
   baked-keys query settled, causing a first-open flicker: bakedEnvKeys was
   undefined, baked-covered keys transiently appeared missing, Advanced
   expanded, then the requirement disappeared when the query resolved.
   Fixed by gating the auto-expand on isFetched from the query.

3. useBakedBuildEnvKeysQuery lacked retry: false, causing 3 silent retries
   in web/E2E contexts where the Tauri command doesn't exist.

Also extends getBakedSatisfiedEnvKeys JSDoc with the UX asymmetry rationale
and the #1448 precedence insertion point note, and adds the missing
"Queued to split." trailer to the tauri.ts file-size override comment.
… path for baked env

Four new pure-function tests:

- requiredEnvKeys_exclusionSemantics_filledKeyStaysInAmberRow: regression
  guard for the allowlist bug — a filled required key must stay in the amber
  locked row list (all-minus-excluded, not missing-only).
- requiredEnvKeys_exclusionSemantics_bakedKeyDropsFromAmberRow: a baked-
  satisfied key must be excluded from the amber row list.
- saveBlock_bakedSatisfiedKey_notMissing: hasMissingRequiredEnvKey returns
  false after filtering out baked-satisfied keys, pinning the hook path in
  useRequiredCredentialState without React rendering machinery.
- saveBlock_noFilterNoBaked_stillMissing: control case — same key is required
  and missing when baked env is empty (OSS build baseline).
@wpfleger96

Copy link
Copy Markdown
Collaborator Author

🤖 reply from Will's agent

hey @wesbillman — good catch on the PersonaDialog filter. Fixed in 8b14773: swapped the allowlist for the exclusion semantics you suggested, mirroring the other consumers — so filled keys stay in the amber locked row (no more mid-typing row rebuild) and file-satisfied keys no longer double-render with the spurious badge. Also pinned it with pure-function tests covering the exclusion behavior and the save-block path.

@wpfleger96 wpfleger96 merged commit b90e804 into main Jul 7, 2026
25 checks passed
@wpfleger96 wpfleger96 deleted the wpfleger/baked-env-required-badge branch July 7, 2026 16:30
tellaho added a commit that referenced this pull request Jul 7, 2026
…ivity

* origin/main:
  fix(desktop): hydrate reactions for Inbox context messages (#1596)
  fix: cleanup old screenshots that my agents committed (#1598)
  chore(release): release Buzz Desktop version 0.3.46 (#1585)
  fix(desktop): preserve agent model/provider when persona snapshot fields are blank (#1583)
  feat(acp,desktop): identify and reap stale agent harness processes (#1582)
  feat(desktop): active-draft badge, send-from-drafts confirm dialog, thread-deleted state (#1581)
  fix(desktop): treat baked build env vars as satisfying required agent config (#1580)
  feat(desktop): add "Copy image" to image right-click context menu (#1579)
  fix(nest): use buzz-dev symlink name for dev builds (#1587)
  fix(composer): address image-editor follow-up nits on #1491 (#1565)
  fix(desktop): render black static boot screen (#1570)
  feat(agents): group activity tool bursts (#1571)
  feat(desktop): aggregated overview rail, commit detail page, and full breadcrumbs (#1573)
  fix(desktop): fetch profiles for reaction actors and thread-reply authors (#1550)
  refactor(desktop): unify EditAgentDialog styling with PersonaDialog (#1540)
  feat(desktop): add 10-minute message grouping window (#1578)
  feat(desktop): unify sidebar section actions into a per-section ⋮ menu (#1577)
  feat(desktop): emoji avatar picker for agents + reliable picker scroll (#1576)

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
tlongwell-block pushed a commit that referenced this pull request Jul 7, 2026
* origin/main:
  docs(readme): add Getting started section routing install paths (#1606)
  fix(desktop): restrict shared-agent sync to dev data dirs (#1597)
  feat(desktop): restart-required badge from spawn-time config hash (#1602)
  feat(desktop): boot-time reconcile of managed agents to relay events (#1601)
  feat(desktop): canonical <PubKey> component — hover to view/copy full keys, owner "you" labels (#1589)
  fix(desktop): hydrate reactions for Inbox context messages (#1596)
  fix: cleanup old screenshots that my agents committed (#1598)
  chore(release): release Buzz Desktop version 0.3.46 (#1585)
  fix(desktop): preserve agent model/provider when persona snapshot fields are blank (#1583)
  feat(acp,desktop): identify and reap stale agent harness processes (#1582)
  feat(desktop): active-draft badge, send-from-drafts confirm dialog, thread-deleted state (#1581)
  fix(desktop): treat baked build env vars as satisfying required agent config (#1580)
  feat(desktop): add "Copy image" to image right-click context menu (#1579)
  fix(nest): use buzz-dev symlink name for dev builds (#1587)
  fix(composer): address image-editor follow-up nits on #1491 (#1565)
  fix(desktop): render black static boot screen (#1570)
  feat(agents): group activity tool bursts (#1571)
  feat(desktop): aggregated overview rail, commit detail page, and full breadcrumbs (#1573)
  fix(desktop): fetch profiles for reaction actors and thread-reply authors (#1550)
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.

2 participants