feat(config): 添加 agent 运行器类型及相关配置支持

This commit is contained in:
Soulter
2025-10-21 00:47:04 +08:00
parent a0f8f3ae32
commit ef99f64291
2 changed files with 122 additions and 57 deletions
+67 -2
View File
@@ -71,6 +71,9 @@ DEFAULT_CONFIG = {
"streaming_response": False,
"show_tool_use_status": False,
"streaming_segmented": False,
"agent_runner_type": "local",
"dify_runner_provider_id": "",
"coze_runner_provider_id": "",
"max_agent_step": 30,
"tool_call_timeout": 60,
},
@@ -1931,12 +1934,19 @@ CONFIG_METADATA_2 = {
"streaming_segmented": {
"type": "bool",
},
"agent_runner_type": {
"type": "string",
},
"dify_runner_provider_id": {
"type": "string",
},
"coze_runner_provider_id": {
"type": "string",
},
"max_agent_step": {
"description": "工具调用轮数上限",
"type": "int",
},
"tool_call_timeout": {
"description": "工具调用超时时间(秒)",
"type": "int",
},
},
@@ -2070,6 +2080,46 @@ CONFIG_METADATA_3 = {
"ai_group": {
"name": "AI 配置",
"metadata": {
"agent_runner": {
"description": "Agent",
"type": "object",
"items": {
"provider_settings.agent_runner_type": {
"description": "执行器",
"type": "string",
"options": ["local", "dify", "coze"],
"labels": ["内置 Agent", "Dify", "Coze"],
},
},
},
"dify_runner": {
"description": "Dify",
"type": "object",
"items": {
"provider_settings.dify_runner_provider_id": {
"description": "Dify 执行器提供商 ID",
"type": "string",
"_special": "select_dify_runner_provider",
},
},
"condition": {
"provider_settings.agent_runner_type": "dify",
},
},
"coze_runner": {
"description": "Coze",
"type": "object",
"items": {
"provider_settings.coze_runner_provider_id": {
"description": "Coze 执行器提供商 ID",
"type": "string",
"_special": "select_coze_runner_provider",
},
},
"condition": {
"provider_settings.agent_runner_type": "coze",
},
},
"ai": {
"description": "模型",
"type": "object",
@@ -2123,6 +2173,9 @@ CONFIG_METADATA_3 = {
"type": "text",
},
},
"condition": {
"provider_settings.agent_runner_type": "local",
},
},
"persona": {
"description": "人格",
@@ -2134,6 +2187,9 @@ CONFIG_METADATA_3 = {
"_special": "select_persona",
},
},
"condition": {
"provider_settings.agent_runner_type": "local",
},
},
"knowledgebase": {
"description": "知识库",
@@ -2145,6 +2201,9 @@ CONFIG_METADATA_3 = {
"_special": "select_knowledgebase",
},
},
"condition": {
"provider_settings.agent_runner_type": "local",
},
},
"websearch": {
"description": "网页搜索",
@@ -2181,6 +2240,9 @@ CONFIG_METADATA_3 = {
"type": "bool",
},
},
"condition": {
"provider_settings.agent_runner_type": "local",
},
},
"others": {
"description": "其他配置",
@@ -2248,6 +2310,9 @@ CONFIG_METADATA_3 = {
"type": "bool",
},
},
"condition": {
"provider_settings.agent_runner_type": "local",
},
},
},
},
@@ -101,6 +101,21 @@ function shouldShowItem(itemMeta, itemKey) {
return true
}
// 检查最外层的 object 是否应该显示
function shouldShowSection() {
const sectionMeta = props.metadata[props.metadataKey]
if (!sectionMeta?.condition) {
return true
}
for (const [conditionKey, expectedValue] of Object.entries(sectionMeta.condition)) {
const actualValue = getValueBySelector(props.iterable, conditionKey)
if (actualValue !== expectedValue) {
return false
}
}
return true
}
function hasVisibleItemsAfter(items, currentIndex) {
const itemEntries = Object.entries(items)
@@ -114,12 +129,27 @@ function hasVisibleItemsAfter(items, currentIndex) {
return false
}
// 将 options 和 labels 转换为 v-select 的 items 格式
function getSelectItems(itemMeta) {
if (!itemMeta?.options) {
return []
}
if (itemMeta?.labels && itemMeta.labels.length === itemMeta.options.length) {
return itemMeta.options.map((value, index) => ({
title: itemMeta.labels[index],
value: value
}))
}
return itemMeta.options
}
</script>
<template>
<v-card style="margin-bottom: 16px; padding-bottom: 8px; background-color: rgb(var(--v-theme-background));" rounded="md" variant="outlined">
<v-card v-if="shouldShowSection()" style="margin-bottom: 16px; padding-bottom: 8px; background-color: rgb(var(--v-theme-background));"
rounded="md" variant="outlined">
<v-card-text class="config-section" v-if="metadata[metadataKey]?.type === 'object'" style="padding-bottom: 8px;">
<v-list-item-title class="config-title">
{{ metadata[metadataKey]?.description }}
@@ -154,7 +184,7 @@ function hasVisibleItemsAfter(items, currentIndex) {
<div class="w-100" v-if="!itemMeta?._special">
<!-- Select input for JSON selector -->
<v-select v-if="itemMeta?.options" v-model="createSelectorModel(itemKey).value"
:items="itemMeta?.options" :disabled="itemMeta?.readonly" density="compact" variant="outlined"
:items="getSelectItems(itemMeta)" :disabled="itemMeta?.readonly" density="compact" variant="outlined"
class="config-field" hide-details></v-select>
<!-- Code Editor for JSON selector -->
@@ -186,22 +216,16 @@ function hasVisibleItemsAfter(items, currentIndex) {
<!-- Boolean switch for JSON selector -->
<v-switch v-else-if="itemMeta?.type === 'bool'" v-model="createSelectorModel(itemKey).value"
color="primary" inset density="compact" hide-details style="display: flex; justify-content: end;"></v-switch>
color="primary" inset density="compact" hide-details
style="display: flex; justify-content: end;"></v-switch>
<!-- List item for JSON selector -->
<ListConfigItem
v-else-if="itemMeta?.type === 'list'"
v-model="createSelectorModel(itemKey).value"
button-text="修改"
class="config-field"
/>
<ListConfigItem v-else-if="itemMeta?.type === 'list'" v-model="createSelectorModel(itemKey).value"
button-text="修改" class="config-field" />
<!-- Object editor for JSON selector -->
<ObjectEditor
v-else-if="itemMeta?.type === 'dict'"
v-model="createSelectorModel(itemKey).value"
class="config-field"
/>
<ObjectEditor v-else-if="itemMeta?.type === 'dict'" v-model="createSelectorModel(itemKey).value"
class="config-field" />
<!-- Fallback for JSON selector -->
<v-text-field v-else v-model="createSelectorModel(itemKey).value" density="compact" variant="outlined"
@@ -210,50 +234,29 @@ function hasVisibleItemsAfter(items, currentIndex) {
<!-- Special handling for specific metadata types -->
<div v-else-if="itemMeta?._special === 'select_provider'">
<ProviderSelector
v-model="createSelectorModel(itemKey).value"
:provider-type="'chat_completion'"
/>
<ProviderSelector v-model="createSelectorModel(itemKey).value" :provider-type="'chat_completion'" />
</div>
<div v-else-if="itemMeta?._special === 'select_provider_stt'">
<ProviderSelector
v-model="createSelectorModel(itemKey).value"
:provider-type="'speech_to_text'"
/>
<ProviderSelector v-model="createSelectorModel(itemKey).value" :provider-type="'speech_to_text'" />
</div>
<div v-else-if="itemMeta?._special === 'select_provider_tts'">
<ProviderSelector
v-model="createSelectorModel(itemKey).value"
:provider-type="'text_to_speech'"
/>
<ProviderSelector v-model="createSelectorModel(itemKey).value" :provider-type="'text_to_speech'" />
</div>
<div v-else-if="itemMeta?._special === 'provider_pool'">
<ProviderSelector
v-model="createSelectorModel(itemKey).value"
:provider-type="'chat_completion'"
button-text="选择提供商池..."
/>
<ProviderSelector v-model="createSelectorModel(itemKey).value" :provider-type="'chat_completion'"
button-text="选择提供商池..." />
</div>
<div v-else-if="itemMeta?._special === 'select_persona'">
<PersonaSelector
v-model="createSelectorModel(itemKey).value"
/>
<PersonaSelector v-model="createSelectorModel(itemKey).value" />
</div>
<div v-else-if="itemMeta?._special === 'persona_pool'">
<PersonaSelector
v-model="createSelectorModel(itemKey).value"
button-text="选择人格池..."
/>
<PersonaSelector v-model="createSelectorModel(itemKey).value" button-text="选择人格池..." />
</div>
<div v-else-if="itemMeta?._special === 'select_knowledgebase'">
<KnowledgeBaseSelector
v-model="createSelectorModel(itemKey).value"
/>
<KnowledgeBaseSelector v-model="createSelectorModel(itemKey).value" />
</div>
<div v-else-if="itemMeta?._special === 'select_plugin_set'">
<PluginSetSelector
v-model="createSelectorModel(itemKey).value"
/>
<PluginSetSelector v-model="createSelectorModel(itemKey).value" />
</div>
<div v-else-if="itemMeta?._special === 't2i_template'">
<T2ITemplateEditor />
@@ -262,21 +265,17 @@ function hasVisibleItemsAfter(items, currentIndex) {
</v-row>
<!-- Plugin Set Selector 全宽显示区域 -->
<v-row v-if="!itemMeta?.invisible && itemMeta?._special === 'select_plugin_set'" class="plugin-set-display-row">
<v-row v-if="!itemMeta?.invisible && itemMeta?._special === 'select_plugin_set'"
class="plugin-set-display-row">
<v-col cols="12" class="plugin-set-display">
<div v-if="createSelectorModel(itemKey).value && createSelectorModel(itemKey).value.length > 0" class="selected-plugins-full-width">
<div v-if="createSelectorModel(itemKey).value && createSelectorModel(itemKey).value.length > 0"
class="selected-plugins-full-width">
<div class="plugins-header">
<small class="text-grey">已选择的插件</small>
</div>
<div class="d-flex flex-wrap ga-2 mt-2">
<v-chip
v-for="plugin in (createSelectorModel(itemKey).value || [])"
:key="plugin"
size="small"
label
color="primary"
variant="outlined"
>
<v-chip v-for="plugin in (createSelectorModel(itemKey).value || [])" :key="plugin" size="small" label
color="primary" variant="outlined">
{{ plugin === '*' ? '所有插件' : plugin }}
</v-chip>
</div>
@@ -284,7 +283,8 @@ function hasVisibleItemsAfter(items, currentIndex) {
</v-col>
</v-row>
</template>
<v-divider class="config-divider" v-if="shouldShowItem(itemMeta, itemKey) && hasVisibleItemsAfter(metadata[metadataKey].items, index)"></v-divider>
<v-divider class="config-divider"
v-if="shouldShowItem(itemMeta, itemKey) && hasVisibleItemsAfter(metadata[metadataKey].items, index)"></v-divider>
</div>
</div>