wutongyuonce f17ca3777a
feat(extensions): add in-place upgrade that keeps private config (#5347)
* feat(extensions): add in-place upgrade that keeps private config

Replace a managed local snapshot or re-pin an already-installed
requirement without going through remove, which dropped plugins[].config.

* fix(extensions): keep snapshot, enabled, and git re-pin on upgrade

Rollback keys off staging_root so a failed snapshot rename cannot
rmtree the live tree. Upgrade preserves plugins[].enabled. Re-pin
identification uses tool.uv.sources so git upgrades adopt the
existing plugin record instead of failing closed after uv already
switched the revision.

* test(extensions): cover requirement re-pin identification on upgrade

Re-pinning deerflow-extension-demo==2.0.0 to ==3.0.0 leaves added_names
empty, so identification must take the added_specs fallback. Assert
private config/required/enabled survive and the lock records 3.0.0.

* fix(extensions): reject upgrade of an uninstalled git source

Bare git+ URLs are not named Requirements, so the pre-uv-add installed
check was skipped and upgrade acted as install. Resolve them against
[tool.uv.sources] in the extensions group before uv add.
2026-09-12 15:59:41 +08:00
..