feat(pool): 引入 pro_first 调度预设、Pool 候选持久化跳过与诊断信息优化

- 新增 pro_first 调度预设(Pro 优先),更新 plus_first 仅针对 Plus 计划,移除 free_team_first
- Pool 内部候选(pool_key_index 不为空)跳过 DB 持久化(available/skipped/unused 均适用)
- LRU 排序新增 catalog_lru_score 回退:runtime 无记录时使用 last_used_at_unix_secs
- 执行路径 miss 诊断消息细化为中文,按 reason 分类输出可读说明
- build_local_request_candidate_status_record 补充 extra_data 和 created_at_unix_ms 字段
- OpenAI CLI 计划构建流程补充候选评估进度跟踪与 terminal reason 设置
- 前端 PoolSchedulingDialog 增加 pro_first 预设展示,修复 LRU 默认预设检测逻辑
This commit is contained in:
fawney19
2026-04-24 13:29:05 +08:00
parent f29649e3a8
commit f3c9835759
27 changed files with 950 additions and 153 deletions

View File

@@ -321,8 +321,17 @@ const FALLBACK_PRESET_DEFS: PoolPresetMeta[] = [
{
name: 'plus_first',
label: 'Plus 优先',
description: '优先消耗 Plus/Pro 账号(依赖 plan_type',
evidence_hint: '依据 plan_typePlus/Pro 账号优先调度)',
description: '优先消耗 Plus 账号(依赖 plan_type',
evidence_hint: '依据 plan_typePlus 账号优先调度)',
providers: ['codex', 'kiro'],
modes: null,
default_mode: null,
},
{
name: 'pro_first',
label: 'Pro 优先',
description: '优先消耗 Pro 账号(依赖 plan_type',
evidence_hint: '依据 plan_typePro 账号优先调度)',
providers: ['codex', 'kiro'],
modes: null,
default_mode: null,
@@ -608,7 +617,7 @@ function loadFromConfig(cfg: PoolAdvancedConfig | null): PresetListItem[] {
const rawPresets = cfg.scheduling_presets
if (!Array.isArray(rawPresets) || rawPresets.length === 0) {
if (cfg.scheduling_mode === 'lru' || (!cfg.scheduling_mode && cfg.lru_enabled !== false)) {
if (cfg.scheduling_mode === 'lru' || cfg.lru_enabled === true) {
return defaults.map(item => ({
...item,
enabled: item.preset === 'lru',

View File

@@ -309,6 +309,7 @@ import {
} from '@/api/endpoints'
import { parseApiError } from '@/utils/errorParser'
import { parseNumberInput } from '@/utils/form'
import { dateTimeLocalToRfc3339, formatDateTimeLocalInput } from '@/utils/date'
const props = defineProps<{
modelValue: boolean
@@ -403,10 +404,8 @@ function loadProviderData() {
billing_type: (props.provider.billing_type as 'monthly_quota' | 'pay_as_you_go' | 'free_tier') || 'pay_as_you_go',
monthly_quota_usd: props.provider.monthly_quota_usd || undefined,
quota_reset_day: props.provider.quota_reset_day || 30,
quota_last_reset_at: props.provider.quota_last_reset_at ?
new Date(props.provider.quota_last_reset_at).toISOString().slice(0, 16) : '',
quota_expires_at: props.provider.quota_expires_at ?
new Date(props.provider.quota_expires_at).toISOString().slice(0, 16) : '',
quota_last_reset_at: formatDateTimeLocalInput(props.provider.quota_last_reset_at),
quota_expires_at: formatDateTimeLocalInput(props.provider.quota_expires_at),
provider_priority: props.provider.provider_priority || 999,
keep_priority_on_conversion: props.provider.keep_priority_on_conversion ?? false,
is_active: props.provider.is_active,
@@ -452,6 +451,17 @@ const handleSubmit = async () => {
return
}
const quotaLastResetAt = dateTimeLocalToRfc3339(form.value.quota_last_reset_at)
if (form.value.billing_type === 'monthly_quota' && !quotaLastResetAt) {
showError('周期开始时间必须是合法时间', '验证失败')
return
}
const quotaExpiresAt = dateTimeLocalToRfc3339(form.value.quota_expires_at)
if (form.value.quota_expires_at && !quotaExpiresAt) {
showError('过期时间必须是合法时间', '验证失败')
return
}
loading.value = true
try {
const currentPoolAdvanced = normalizePoolAdvancedConfig(props.provider?.pool_advanced)
@@ -463,8 +473,8 @@ const handleSubmit = async () => {
billing_type: form.value.billing_type,
monthly_quota_usd: form.value.monthly_quota_usd,
quota_reset_day: form.value.quota_reset_day,
quota_last_reset_at: form.value.quota_last_reset_at || undefined,
quota_expires_at: form.value.quota_expires_at || undefined,
quota_last_reset_at: quotaLastResetAt,
quota_expires_at: quotaExpiresAt,
keep_priority_on_conversion: form.value.keep_priority_on_conversion,
is_active: form.value.is_active,
// 请求配置