feat(desktop): harness-agnostic config bridge#887
Draft
wpfleger96 wants to merge 1 commit into
Draft
Conversation
66de98f to
60f95a2
Compare
de81ed1 to
0c44d4e
Compare
44cc07f to
678b871
Compare
0c44d4e to
ba28ea0
Compare
Four-tier config bridge that reads agent configuration from config files (goose YAML, claude JSON, codex TOML), ACP session data, env vars, and Sprout-explicit overrides — surfacing a unified normalized config surface to the desktop UI regardless of runtime. Key changes: - Config bridge module with per-runtime file readers - ACP session config caching for post-spawn config visibility - AgentConfigPanel component with origin badges and tier provenance - Serde internally-tagged enums matching TypeScript discriminated unions - TOCTOU-safe write path with single lock scope
678b871 to
c392c34
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a harness-agnostic config bridge that reads agent configuration from all available sources and exposes it to the frontend with full provenance — where each value came from and how it can be written back.
Agent config was fragmented across four uncoordinated mechanisms with no single surface to see what a running agent would actually use. The silent failure mode was concrete: Wes's goose personas failed because
active_providerin~/.config/goose/config.yamlwas invisible to Sprout and overrode our injected model. The bridge surfaces that ambient config, establishes a clear precedence order, and routes writes to the cheapest live mechanism.config_bridgemodule with per-runtime config file readers: YAML for goose (~/.config/goose/config.yaml), JSON for Claude Code (~/.claude/settings.json+~/.claude.json), TOML for Codex (~/.codex/config.toml). 25 unit tests covering all formats, malformed files, and missing files.configOptionsfromsession/new> env vars > config file on disk. Pre-spawn surfaces tier 2 only; post-spawn adds ACP tiers.session_config_capturedobserver event emitted aftersession/new;put_agent_session_configTauri command populatesSessionConfigCacheinAppState.parse_modelshandles both the object shape ({currentModelId, availableModels}) and legacy array shape fromsession/new.get_agent_config_surfaceandwrite_agent_config_fieldTauri commands. Write mechanism is chosen per runtime and field:session/set_config_option(live, no restart) before env-var respawn. Single lock scope on the write path closes a TOCTOU race.AgentConfigPanelcomponent with origin badges (Sprout/ACP/ConfigFile/Env), collapsible advanced section, and sources footer showing all four tier statuses. Wired intoManagedAgentRowexpanded section below the log panel.ModelPickershows provenance label when config surface data is available post-spawn (best-effort, non-blocking).codex.provider_lockedtofalse— Codex supports[model_providers.<id>]custom provider tables. Fixes serde enum tagging onConfigWriteMechanism,ConfigFieldType, andWriteConfigTargetto use#[serde(tag = "type")]matching the TypeScript discriminated union shapes (default external tagging made all write operations and TS type guards silently broken).Stack: #794 → this PR