Merge followup extraction provider preference fix

This commit is contained in:
2026-10-09 18:09:13 +08:00
2 changed files with 23 additions and 1 deletions
@@ -99,7 +99,11 @@ final class FollowupAudioProviderConfig
public static function readyModels(): array
{
$models = [];
foreach (['qwen', 'openai'] as $profile) {
$profiles = ['qwen', 'openai'];
$preferred = config('followup_audio.profile', 'qwen');
// Preference is presentation only: existing tasks retain their bound provider identity.
if (in_array($preferred, $profiles, true)) { $profiles = array_values(array_unique(array_merge([$preferred], $profiles))); }
foreach ($profiles as $profile) {
if (FollowupAudioGate::ready($profile)) { $models[] = ['value' => $profile, 'label' => self::resolve($profile)['label']]; }
}
return $models;
@@ -58,4 +58,22 @@ $expectError(static fn () => Provider::resolve('qwen', $changed, []), 'CONFIG_IN
$changed = $settings; $changed['providers']['qwen']['verified_fingerprint'] = '';
$expect(!Provider::verified('qwen', $changed, $legacy), 'old unbound flags do not enable audio');
$expect(Provider::status('invalid', $settings, $legacy)['code'] === 'INVALID_PROFILE', 'logical slot allowlist retained');
// The configured default controls new-upload choices without rebinding historical slots.
$ordering = $settings;
$ordering['verified_profiles'] = ['qwen', 'openai'];
$ordering['providers']['openai'] = $slot;
$ordering['providers']['openai']['label'] = 'GPT extraction';
$ordering['providers']['openai']['verified_fingerprint'] = Provider::resolve('openai', $ordering, [])['fingerprint'];
$ordering['profile'] = 'openai';
$config->set($ordering, 'followup_audio');
$expect(array_column(Provider::readyModels(), 'value') === ['openai', 'qwen'], 'configured GPT default comes first while historical Qwen remains ready');
$expect(Provider::resolve('qwen')['fingerprint'] === $resolved['fingerprint'], 'default selection does not rebind the historical provider identity');
$ordering['profile'] = 'qwen'; $config->set($ordering, 'followup_audio');
$expect(array_column(Provider::readyModels(), 'value') === ['qwen', 'openai'], 'configured Qwen priority remains supported');
$ordering['profile'] = 'unknown'; $config->set($ordering, 'followup_audio');
$expect(array_column(Provider::readyModels(), 'value') === ['qwen', 'openai'], 'invalid default never inserts an unrecognized profile');
$ordering['profile'] = 'openai'; $ordering['providers']['openai']['verified_fingerprint'] = '';
$config->set($ordering, 'followup_audio');
$expect(array_column(Provider::readyModels(), 'value') === ['qwen'], 'sorting does not manufacture readiness for an unverified profile');
$config->set($settings, 'followup_audio');
echo 'FOLLOWUP_AUDIO_PROVIDER_CONFIG assertions=' . $checks . ' PASS explicit_driver=1 model_configurable=1 exact_fingerprint=1 https_verified=1 secrets_hidden=1' . PHP_EOL;