feat(config): 添加 agent 运行器类型及相关配置支持
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user