优化: run_command 实时流式 + 审批浮窗修复 + 文档探索闭环(fetch_url+obscura引导+model_fetch兼容+prompt策略+厂商预设)

This commit is contained in:
lxy
2026-08-01 17:58:47 +08:00
parent 0e0c6862ba
commit d664bdc309
25 changed files with 1693 additions and 44 deletions
+37
View File
@@ -68,6 +68,16 @@
<label class="form-label">{{ $t('settings.labelName') }}</label>
<input v-model="providerForm.name" class="setting-input" :placeholder="$t('settings.phProviderName')" />
</div>
<!-- 项 D:厂商预设下拉 — 选中自动填充 providerType/baseUrl/defaultModel(用户可改覆盖)。
新建态独立"快捷选择";编辑态回填后切预设仍可覆盖(等价快捷填充),不阻塞手改。
"自定义" 不预填任何字段。 -->
<div class="form-field">
<label class="form-label">{{ $t('settings.labelPreset') }}</label>
<select v-model="providerForm.presetId" class="setting-select" @change="onPresetChange">
<option value="__custom">{{ $t('settings.presetCustom') }}</option>
<option v-for="p in PROVIDER_PRESETS" :key="p.id" :value="p.id">{{ p.name }}</option>
</select>
</div>
<div class="form-field">
<label class="form-label">{{ $t('settings.labelProviderType') }}</label>
<select v-model="providerForm.providerType" class="setting-select">
@@ -136,6 +146,7 @@ import { reactive, ref, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { aiApi } from '@/api'
import type { AiProviderConfig, ModelConfig } from '@/api/types'
import { PROVIDER_PRESETS, CUSTOM_PRESET_ID, findPreset } from './providerPresets'
// ============================================================
// AI 提供商域 — 真实后端 CRUD + F-04c 负载均衡池(enabled / weight)
@@ -174,6 +185,10 @@ const providerForm = reactive({
baseUrl: '',
apiKey: '',
defaultModel: '',
// 项 D:厂商预设下拉当前值(__custom=自定义;命中预设 id 时仅作展示与回填源头,
// 实际字段值由 onPresetChange 写入;用户手改任一字段后 presetId 不自动复位,
// 避免编辑态抖动,提交时也不读 presetId —— 以表单实际字段值为准)。
presetId: CUSTOM_PRESET_ID,
saving: false,
// F-01 阶段6:模型拉取 + 列表
fetching: false,
@@ -205,6 +220,9 @@ function openProviderForm(p?: AiProviderConfig) {
providerForm.apiKey = '' // 编辑不回填 api_key(list 返回 mask,留空=不改,FR-S1)
providerForm.defaultModel = p.default_model
providerForm.providerType = p.provider_type || 'openai_compat'
// 项 D:编辑态不反推预设(避免用户已手改 baseUrl/model 却被下拉误标成某预设误导);
// 统一标"自定义",下拉仅作新建快捷填充入口。
providerForm.presetId = CUSTOM_PRESET_ID
// F-01 阶段6:回填已保存的 model_configs(深拷贝避免双向绑定污染列表源)
providerForm.models = (p.model_configs ?? []).map(m => ({ ...m, modalities: [...m.modalities], capabilities: [...m.capabilities] }))
} else {
@@ -214,6 +232,7 @@ function openProviderForm(p?: AiProviderConfig) {
providerForm.baseUrl = ''
providerForm.apiKey = ''
providerForm.defaultModel = ''
providerForm.presetId = CUSTOM_PRESET_ID
providerForm.models = []
}
providerForm.fetching = false
@@ -221,6 +240,24 @@ function openProviderForm(p?: AiProviderConfig) {
providerForm.visible = true
}
/**
* 项 D:厂商预设下拉变更 — 命中预设则覆盖填充 providerType/baseUrl/defaultModel。
*
* 设计取舍:
* - 覆盖而非合并:选预设=用户明确意图用某厂商端点,全量填入最省心;用户随后仍可手改任一字段。
* - 不动 name/apiKey:name 用户应自取别名(避免重名"DeepSeek"×N);apiKey 是密钥预设无可填。
* - 选"自定义"不动作(仅清字段是粗暴的;用户可能误点,留原值更安全)。
* - 不复位 presetId:用户手改 baseUrl 等后下拉仍标原预设——这无副作用(提交不读 presetId),
* 强行复位反而要监听每个字段 input,过度工程。
*/
function onPresetChange() {
const preset = findPreset(providerForm.presetId)
if (!preset) return // __custom 或未知 id:不动作
providerForm.providerType = preset.providerType
providerForm.baseUrl = preset.baseUrl
providerForm.defaultModel = preset.defaultModel
}
/**
* 测试连接按钮可用条件(P0-1):
* - baseUrl 必填(无论新建/编辑,表单值都要有)