feat(sidecars): surface storage location and cover excluded models in migration

After migrating to centralized sidecar storage users had no indication
where their files went, and portable-mode installs silently placed the
sidecar root inside the plugin folder where a reinstall or git clean
would delete it.

- Migration now also covers models excluded from the library view and
  returns the resolved sidecar root in its result payload
- get_settings exposes the resolved sidecar root, whether it is the
  default, and whether it lives inside the installation folder
- New POST /api/lm/sidecars/open-location endpoint opens (or copies)
  the sidecar storage folder
- Settings UI always shows the effective storage path with an
  open-folder button, and warns when the root is inside the
  installation folder (portable-mode hazard)
- Migration confirmation shows the destination; on completion a result
  dialog summarizes moved/skipped/conflict counts with the storage
  location and an open-folder action
- Ignore /sidecars/ at the repository root so portable-mode sidecars
  are never committed

Refs #1045
This commit is contained in:
Will Miao
2026-09-26 23:08:29 +08:00
parent 62c144d80a
commit 7aee964448
25 changed files with 817 additions and 34 deletions
@@ -359,6 +359,23 @@
</div>
</div>
</div>
<div class="setting-row">
<div class="setting-info">
<div class="input-help sidecar-storage-location">
{{ t('settings.sidecarStorage.effectivePathLabel') }}
<code id="sidecarStorageResolvedPath" class="backup-location-path"></code>
</div>
<div class="input-help sidecar-storage-repo-warning" id="sidecarStorageRepoWarning" style="display: none;">
<i class="fas fa-exclamation-triangle"></i>
{{ t('settings.sidecarStorage.repoWarning') }}
</div>
</div>
<div class="setting-control">
<button type="button" class="secondary-btn" id="sidecarStorageOpenBtn" onclick="settingsManager.openSidecarStorageLocation()">
{{ t('settings.sidecarStorage.openFolderButton') }}
</button>
</div>
</div>
</div>
<div class="setting-item">