Advanced paste: Tweak Foundry Local Displayed Model and start server if server is turned on when using AP (#43529)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
1. Foundry local model name should not prefixed by fl://
2. If foundry service is shutdown, we should not just fail it, we should
start it then call FL to make availability better.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Verified locally:
1. Manually disable foundry local service, then run AP with foundry
local, it can return result instead of direct failure.
2. 
<img width="659" height="294" alt="image"
src="https://github.com/user-attachments/assets/113da451-7131-4ce7-ae82-0ccf772ad8aa"
/>
<img width="988" height="192" alt="image"
src="https://github.com/user-attachments/assets/aa3650ba-668a-40c4-ad8a-303e09000dd4"
/>
![Uploading image.png…]()
This commit is contained in:
Kai Tao
2025-11-13 17:28:23 +08:00
committed by GitHub
parent a983a773f3
commit 2f001e8150
6 changed files with 34 additions and 171 deletions

View File

@@ -27,7 +27,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public sealed partial class AdvancedPastePage : NavigablePage, IRefreshablePage, IDisposable
{
private readonly ObservableCollection<ModelDetails> _foundryCachedModels = new();
private readonly ObservableCollection<FoundryDownloadableModel> _foundryDownloadableModels = new();
private CancellationTokenSource _foundryModelLoadCts;
private bool _suppressFoundrySelectionChanged;
private bool _isFoundryLocalAvailable;
@@ -57,7 +56,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
if (FoundryLocalPicker is not null)
{
FoundryLocalPicker.CachedModels = _foundryCachedModels;
FoundryLocalPicker.DownloadableModels = _foundryDownloadableModels;
FoundryLocalPicker.SelectionChanged += FoundryLocalPicker_SelectionChanged;
FoundryLocalPicker.LoadRequested += FoundryLocalPicker_LoadRequested;
}
@@ -469,7 +467,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
var cachedModels = cachedModelsEnumerable?.ToList() ?? new List<ModelDetails>();
UpdateFoundryCollections(cachedModels, []);
UpdateFoundryCollections(cachedModels);
ShowFoundryAvailableState();
RestoreFoundrySelection(cachedModels);
}
@@ -538,7 +536,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
UpdateFoundrySaveButtonState();
}
private void UpdateFoundryCollections(IReadOnlyCollection<ModelDetails> cachedModels, IReadOnlyCollection<ModelDetails> catalogModels)
private void UpdateFoundryCollections(IReadOnlyCollection<ModelDetails> cachedModels)
{
_foundryCachedModels.Clear();
@@ -547,20 +545,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
_foundryCachedModels.Add(model);
}
var cachedReferences = new HashSet<string>(_foundryCachedModels.Select(m => NormalizeFoundryModelReference(m.Url ?? m.Name)), StringComparer.OrdinalIgnoreCase);
_foundryDownloadableModels.Clear();
foreach (var model in catalogModels.OrderBy(m => m.Name, StringComparer.OrdinalIgnoreCase))
{
var reference = NormalizeFoundryModelReference(model.Url ?? model.Name);
if (cachedReferences.Contains(reference))
{
continue;
}
_foundryDownloadableModels.Add(new FoundryDownloadableModel(model));
}
var cachedReferences = new HashSet<string>(_foundryCachedModels.Select(m => m.Name), StringComparer.OrdinalIgnoreCase);
}
private void RestoreFoundrySelection(IReadOnlyCollection<ModelDetails> cachedModels)
@@ -576,9 +561,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views
if (!string.IsNullOrWhiteSpace(currentModelReference))
{
var normalizedReference = NormalizeFoundryModelReference(currentModelReference);
matchingModel = cachedModels.FirstOrDefault(model =>
string.Equals(NormalizeFoundryModelReference(model.Url ?? model.Name), normalizedReference, StringComparison.OrdinalIgnoreCase));
string.Equals(model.Name, currentModelReference, StringComparison.OrdinalIgnoreCase));
}
if (FoundryLocalPicker is null)
@@ -608,7 +592,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
if (ViewModel?.PasteAIProviderDraft is not null)
{
ViewModel.PasteAIProviderDraft.ModelName = NormalizeFoundryModelReference(matchingModel.Url ?? matchingModel.Name);
ViewModel.PasteAIProviderDraft.ModelName = matchingModel.Name;
}
if (FoundryLocalPicker is not null)
@@ -620,19 +604,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
UpdateFoundrySaveButtonState();
}
private static string NormalizeFoundryModelReference(string modelReference)
{
if (string.IsNullOrWhiteSpace(modelReference))
{
return string.Empty;
}
var prefix = FoundryLocalModelProvider.Instance.UrlPrefix;
return modelReference.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)
? modelReference
: $"{prefix}{modelReference}";
}
private void UpdateFoundrySaveButtonState()
{
if (PasteAIProviderConfigurationDialog is null)
@@ -656,7 +627,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
return;
}
if (!_isFoundryLocalAvailable || _foundryDownloadableModels.Any(model => model.IsDownloading))
if (!_isFoundryLocalAvailable)
{
PasteAIProviderConfigurationDialog.IsPrimaryButtonEnabled = false;
return;
@@ -677,7 +648,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
if (ViewModel?.PasteAIProviderDraft is not null)
{
ViewModel.PasteAIProviderDraft.ModelName = NormalizeFoundryModelReference(selectedModel.Url ?? selectedModel.Name);
ViewModel.PasteAIProviderDraft.ModelName = selectedModel.Name;
}
if (FoundryLocalPicker is not null)