Commit 8959522
authored
fix(config): replace subagent model settings atomically instead of merging (#234)
## Related Issue
No issue. Follow-up to the subagent model pin Settings work: the pin
could not be switched off and pool → default transitions kept the pool
table on disk.
## Problem
`POST /config` merged every domain one at a time. For `secondary_model`
that meant a change never dropped fields: switching the pin off kept
`force = true`, moving from a pool to a single default kept
`[secondary_model.models]`, and an invalid later domain left the earlier
domains already written. The web client also omitted `force` when it was
false, which hid the bug behind merge semantics.
## What changed
- `routes/config.ts` stages every domain from the persisted user layer
(`inspect().userValue`, never the effective value — env and default
values must not be written back), merges ordinary domains with the
registered section merge, replaces `secondary_model`, and commits
through one `replaceSections()` call. An invalid domain rejects the
whole request; nothing reaches disk.
- `rest-config.ts` types the `secondary_model` body
(`default_model`/`defaultModel`, `model`,
`default_effort`/`defaultEffort`, `models`, `force`, strict). `force:
false` normalizes to absence.
- `ConfigService.replace()` / `replaceSections()` now really replace on
disk: `applySectionToToml` has a `replace` mode that no longer re-adds
keys from the previous section value. Before this, only the in-memory
state was replaced and stale keys came back on reload.
- `SettingsDialog.vue` serializes `force: false` explicitly. This is a
compatibility defense for older gateways only; correctness does not
depend on it (test name says so).
- `dist-web` rebuilt from source.
Tests (all fail on `main`): force true → false drops `force`; pool →
default drops `models`; pool → force drops `models`; invalid
multi-domain request leaves every domain unchanged; providers patch
still merges; an env-bound section patch never writes env/default values
to the user layer; malformed and unknown-key `secondary_model` bodies
are rejected; core `replace`/`replaceSections` drop keys on disk and
survive `reload()`; Settings emits `force: false`.
## Checklist
- [x] I have read the
[CONTRIBUTING](https://github.com/PyModel/pythinker-code/blob/main/CONTRIBUTING.md)
document.
- [ ] I have linked a related issue (external PRs: the issue must have a
maintainer's `/approve`).
- [x] I have added tests that prove my feature works.
- [x] Ran `gen-changesets` skill, or this PR needs no changeset.
- [x] Ran `gen-docs` skill, or this PR needs no doc update.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed subagent model settings so disabled or changed options no longer
retain stale force, pool, or related values.
* Improved configuration replacement so removed fields and nested
settings stay removed after saving and reloading.
* Added stricter validation for legacy secondary-model configuration
updates.
* Ensured configuration updates are applied atomically, preventing
partial changes when invalid data is submitted.
* **Chores**
* Refreshed bundled web assets and diagram support without changing
existing rendering behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->1 parent 974da73 commit 8959522
103 files changed
Lines changed: 442 additions & 142 deletions
File tree
- .changeset
- apps
- pythinker-code/dist-web
- assets
- pythinker-web
- src/components/settings
- test
- packages
- agent-core-v2
- src/app/config
- test/app/config
- agent-gateway
- src
- protocol
- routes
- test
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments