Skip to content

FIX: Fix per-subagent model configs#1682

Merged
3clyp50 merged 2 commits into
agent0ai:readyfrom
louisjg:subagent-model-fixes
Jun 1, 2026
Merged

FIX: Fix per-subagent model configs#1682
3clyp50 merged 2 commits into
agent0ai:readyfrom
louisjg:subagent-model-fixes

Conversation

@louisjg
Copy link
Copy Markdown
Contributor

@louisjg louisjg commented May 31, 2026

When per-subagent model assignments are made, they are not saved and the UI doesn't reflect them. This fix was made with AI assistance and human reviewed.

The problems stemmed from how the frontend's reactivity system (Alpine.js) handled the dynamic loading of settings when a user changed the "Project" and "Agent Profile" dropdowns:

The "Unsaved Changes" Popup: When the user switched the Agent Profile to "Developer", the application fetched the correct settings and created a snapshot to monitor for unsaved changes. However, an initialization script ran a moment later to insert empty default properties (like _kwargs_text) if they were missing. Since this modification happened after the snapshot was taken, the UI falsely believed the user had manually changed something.

Changes Reverting to Default Model: The UI elements where the user typed the new model name were tied to a local variable populated only once when the modal first opened (using the Global configuration). When the user switched the scope to "Developer", the main configuration object was updated under the hood, but the UI fields remained permanently tethered to the old "Global" object.

When the user typed his new model name, they were modifying the orphaned object.

When the user clicked "Save", the system submitted the newly loaded (but completely unmodified) "subagent" object. Because it was empty/unmodified, it saved the fallback default model to disk.

This resulted in the engine ignoring user changes (since the default was saved) and the dialogs showing the default model when reopened.

Fixes:
Modified the Alpine components in _model_config:

Reactive Getters (config.html): Changed model: config[section.key] to a reactive getter get model() { return config[section.key]; }. This ensures the UI fields always point to and mutate the currently active configuration scope, regardless of how many times the user switches the dropdowns.

Lifecycle Syncing (config.html): Migrated the initConfigFields logic from a one-time x-init call into an x-effect that watches for scope changes. When a new scope is loaded, it initializes the fields and immediately updates the settingsSnapshotJson to prevent the false "Unsaved Changes" warning.

Dynamic Store Hooks (model-config-store.js): Updated the installSettingsHooks method to read context.settings dynamically upon save, rather than locking into the stale object from initialization.

@3clyp50 3clyp50 changed the base branch from main to ready June 1, 2026 22:19
@3clyp50
Copy link
Copy Markdown
Contributor

3clyp50 commented Jun 1, 2026

Thanks for the PR, Louis. I pushed a small follow-up commit that keeps the scoped model config fields reactive, but only refreshes the clean settings snapshot when the loaded config was already considered clean. That preserves the fix for false unsaved-change warnings while keeping reset/default changes visible as unsaved until Save. I also added a tiny regression assertion for that guard.

@3clyp50 3clyp50 merged commit 8d0b79d into agent0ai:ready Jun 1, 2026
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