fix: localize provider source config UI (#4933)
* fix: localize provider source ui * feat: localize provider metadata keys * chore: add provider metadata translations * chore: format provider i18n changes * fix: preserve metadata fields in i18n conversion * fix: internationalize platform config and dialog * fix: add Weixin official account platform icon --------- Co-authored-by: Soulter <905617992@qq.com>
This commit is contained in:
@@ -42,6 +42,55 @@ class ConfigMetadataI18n:
|
||||
"""
|
||||
result = {}
|
||||
|
||||
def convert_items(
|
||||
group: str, section: str, items: dict[str, Any], prefix: str = ""
|
||||
) -> dict[str, Any]:
|
||||
items_result: dict[str, Any] = {}
|
||||
|
||||
for field_key, field_data in items.items():
|
||||
if not isinstance(field_data, dict):
|
||||
items_result[field_key] = field_data
|
||||
continue
|
||||
|
||||
field_name = field_key
|
||||
field_path = f"{prefix}.{field_name}" if prefix else field_name
|
||||
|
||||
field_result = {
|
||||
key: value
|
||||
for key, value in field_data.items()
|
||||
if key not in {"description", "hint", "labels", "name"}
|
||||
}
|
||||
|
||||
if "description" in field_data:
|
||||
field_result["description"] = (
|
||||
f"{group}.{section}.{field_path}.description"
|
||||
)
|
||||
if "hint" in field_data:
|
||||
field_result["hint"] = f"{group}.{section}.{field_path}.hint"
|
||||
if "labels" in field_data:
|
||||
field_result["labels"] = f"{group}.{section}.{field_path}.labels"
|
||||
if "name" in field_data:
|
||||
field_result["name"] = f"{group}.{section}.{field_path}.name"
|
||||
|
||||
if "items" in field_data and isinstance(field_data["items"], dict):
|
||||
field_result["items"] = convert_items(
|
||||
group, section, field_data["items"], field_path
|
||||
)
|
||||
|
||||
if "template_schema" in field_data and isinstance(
|
||||
field_data["template_schema"], dict
|
||||
):
|
||||
field_result["template_schema"] = convert_items(
|
||||
group,
|
||||
section,
|
||||
field_data["template_schema"],
|
||||
f"{field_path}.template_schema",
|
||||
)
|
||||
|
||||
items_result[field_key] = field_result
|
||||
|
||||
return items_result
|
||||
|
||||
for group_key, group_data in metadata.items():
|
||||
group_result = {
|
||||
"name": f"{group_key}.name",
|
||||
@@ -50,59 +99,19 @@ class ConfigMetadataI18n:
|
||||
|
||||
for section_key, section_data in group_data.get("metadata", {}).items():
|
||||
section_result = {
|
||||
"description": f"{group_key}.{section_key}.description",
|
||||
"type": section_data.get("type"),
|
||||
key: value
|
||||
for key, value in section_data.items()
|
||||
if key not in {"description", "hint", "labels", "name"}
|
||||
}
|
||||
section_result["description"] = f"{group_key}.{section_key}.description"
|
||||
|
||||
# 复制其他属性
|
||||
for key in ["items", "condition", "_special", "invisible"]:
|
||||
if key in section_data:
|
||||
section_result[key] = section_data[key]
|
||||
|
||||
# 处理 hint
|
||||
if "hint" in section_data:
|
||||
section_result["hint"] = f"{group_key}.{section_key}.hint"
|
||||
|
||||
# 处理 items 中的字段
|
||||
if "items" in section_data and isinstance(section_data["items"], dict):
|
||||
items_result = {}
|
||||
for field_key, field_data in section_data["items"].items():
|
||||
# 处理嵌套的点号字段名(如 provider_settings.enable)
|
||||
field_name = field_key
|
||||
|
||||
field_result = {}
|
||||
|
||||
# 复制基本属性
|
||||
for attr in [
|
||||
"type",
|
||||
"condition",
|
||||
"_special",
|
||||
"invisible",
|
||||
"options",
|
||||
"slider",
|
||||
]:
|
||||
if attr in field_data:
|
||||
field_result[attr] = field_data[attr]
|
||||
|
||||
# 转换文本属性为国际化键
|
||||
if "description" in field_data:
|
||||
field_result["description"] = (
|
||||
f"{group_key}.{section_key}.{field_name}.description"
|
||||
)
|
||||
|
||||
if "hint" in field_data:
|
||||
field_result["hint"] = (
|
||||
f"{group_key}.{section_key}.{field_name}.hint"
|
||||
)
|
||||
|
||||
if "labels" in field_data:
|
||||
field_result["labels"] = (
|
||||
f"{group_key}.{section_key}.{field_name}.labels"
|
||||
)
|
||||
|
||||
items_result[field_key] = field_result
|
||||
|
||||
section_result["items"] = items_result
|
||||
section_result["items"] = convert_items(
|
||||
group_key, section_key, section_data["items"]
|
||||
)
|
||||
|
||||
group_result["metadata"][section_key] = section_result
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import inspect
|
||||
import os
|
||||
import traceback
|
||||
@@ -407,8 +408,19 @@ class ConfigRoute(Route):
|
||||
return Response().ok(message="更新 provider source 成功").__dict__
|
||||
|
||||
async def get_provider_template(self):
|
||||
provider_metadata = ConfigMetadataI18n.convert_to_i18n_keys(
|
||||
{
|
||||
"provider_group": {
|
||||
"metadata": {
|
||||
"provider": CONFIG_METADATA_2["provider_group"]["metadata"][
|
||||
"provider"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
config_schema = {
|
||||
"provider": CONFIG_METADATA_2["provider_group"]["metadata"]["provider"]
|
||||
"provider": provider_metadata["provider_group"]["metadata"]["provider"]
|
||||
}
|
||||
data = {
|
||||
"config_schema": config_schema,
|
||||
@@ -1278,11 +1290,24 @@ class ConfigRoute(Route):
|
||||
|
||||
async def _get_astrbot_config(self):
|
||||
config = self.config
|
||||
metadata = copy.deepcopy(CONFIG_METADATA_2)
|
||||
platform_i18n = ConfigMetadataI18n.convert_to_i18n_keys(
|
||||
{
|
||||
"platform_group": {
|
||||
"metadata": {
|
||||
"platform": metadata["platform_group"]["metadata"]["platform"]
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
metadata["platform_group"]["metadata"]["platform"] = platform_i18n[
|
||||
"platform_group"
|
||||
]["metadata"]["platform"]
|
||||
|
||||
# 平台适配器的默认配置模板注入
|
||||
platform_default_tmpl = CONFIG_METADATA_2["platform_group"]["metadata"][
|
||||
"platform"
|
||||
]["config_template"]
|
||||
platform_default_tmpl = metadata["platform_group"]["metadata"]["platform"][
|
||||
"config_template"
|
||||
]
|
||||
|
||||
# 收集需要注册logo的平台
|
||||
logo_registration_tasks = []
|
||||
@@ -1300,14 +1325,14 @@ class ConfigRoute(Route):
|
||||
await asyncio.gather(*logo_registration_tasks, return_exceptions=True)
|
||||
|
||||
# 服务提供商的默认配置模板注入
|
||||
provider_default_tmpl = CONFIG_METADATA_2["provider_group"]["metadata"][
|
||||
"provider"
|
||||
]["config_template"]
|
||||
provider_default_tmpl = metadata["provider_group"]["metadata"]["provider"][
|
||||
"config_template"
|
||||
]
|
||||
for provider in provider_registry:
|
||||
if provider.default_config_tmpl:
|
||||
provider_default_tmpl[provider.type] = provider.default_config_tmpl
|
||||
|
||||
return {"metadata": CONFIG_METADATA_2, "config": config}
|
||||
return {"metadata": metadata, "config": config}
|
||||
|
||||
async def _get_plugin_config(self, plugin_name: str):
|
||||
ret: dict = {"metadata": None, "config": None}
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<h3>
|
||||
选择消息平台类别
|
||||
{{ tm('createDialog.step1Title') }}
|
||||
</h3>
|
||||
<small style="color: grey;">想把机器人接入到哪里?如 QQ、企业微信、飞书、Discord、Telegram 等。</small>
|
||||
<small style="color: grey;">{{ tm('createDialog.step1Hint') }}</small>
|
||||
<div>
|
||||
|
||||
<div v-if="!updatingMode">
|
||||
<v-select v-model="selectedPlatformType" :items="Object.keys(platformTemplates)" item-title="name"
|
||||
item-value="name" label="消息平台类别" variant="outlined" rounded="md" dense hide-details class="mt-6"
|
||||
item-value="name" :label="tm('createDialog.platformTypeLabel')" variant="outlined" rounded="md" dense hide-details class="mt-6"
|
||||
style="max-width: 30%; min-width: 300px;">
|
||||
|
||||
<template v-slot:item="{ props: itemProps, item }">
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-text-field label="消息平台类别" variant="outlined" rounded="md" dense hide-details class="mt-6"
|
||||
<v-text-field :label="tm('createDialog.platformTypeLabel')" variant="outlined" rounded="md" dense hide-details class="mt-6"
|
||||
style="max-width: 30%; min-width: 300px;" v-model="updatingPlatformConfig.type"
|
||||
disabled></v-text-field>
|
||||
<div class="mt-3">
|
||||
@@ -65,13 +65,13 @@
|
||||
<div>
|
||||
<div class="d-flex align-center">
|
||||
<h3>
|
||||
配置文件
|
||||
{{ tm('createDialog.configFileTitle') }}
|
||||
</h3>
|
||||
<v-chip size="x-small" color="primary" variant="tonal" rounded="sm" class="ml-2"
|
||||
v-if="!updatingMode">可选</v-chip>
|
||||
v-if="!updatingMode">{{ tm('createDialog.optional') }}</v-chip>
|
||||
</div>
|
||||
<small style="color: grey;">想如何配置机器人?配置文件包含了聊天模型、人格、知识库、插件范围等丰富的机器人配置项。</small>
|
||||
<small style="color: grey;" v-if="!updatingMode">默认使用默认配置文件 “default”。您也可以稍后配置。</small>
|
||||
<small style="color: grey;">{{ tm('createDialog.configHint') }}</small>
|
||||
<small style="color: grey;" v-if="!updatingMode">{{ tm('createDialog.configDefaultHint') }}</small>
|
||||
</div>
|
||||
<div>
|
||||
<v-btn variant="plain" icon @click="toggleConfigSection" class="mt-2">
|
||||
@@ -86,12 +86,12 @@
|
||||
<v-radio-group class="mt-2" v-model="aBConfigRadioVal" hide-details="true">
|
||||
<v-radio value="0">
|
||||
<template v-slot:label>
|
||||
<span>使用现有配置文件</span>
|
||||
<span>{{ tm('createDialog.useExistingConfig') }}</span>
|
||||
</template>
|
||||
</v-radio>
|
||||
<div class="d-flex align-center ml-10 my-2" v-if="aBConfigRadioVal === '0'">
|
||||
<v-select v-model="selectedAbConfId" :items="configInfoList" item-title="name"
|
||||
item-value="id" label="选择配置文件" variant="outlined" rounded="md" dense hide-details
|
||||
item-value="id" :label="tm('createDialog.selectConfigLabel')" variant="outlined" rounded="md" dense hide-details
|
||||
style="max-width: 30%; min-width: 200px;">
|
||||
</v-select>
|
||||
<v-btn icon variant="text" density="comfortable" class="ml-2"
|
||||
@@ -99,10 +99,10 @@
|
||||
<v-icon>mdi-arrow-top-right-thick</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-radio value="1" label="创建新配置文件">
|
||||
<v-radio value="1" :label="tm('createDialog.createNewConfig')">
|
||||
</v-radio>
|
||||
<div class="d-flex align-center" v-if="aBConfigRadioVal === '1'">
|
||||
<v-text-field v-model="selectedAbConfId" label="新配置文件名称" variant="outlined" rounded="md" dense
|
||||
<v-text-field v-model="selectedAbConfId" :label="tm('createDialog.newConfigNameLabel')" variant="outlined" rounded="md" dense
|
||||
hide-details style="max-width: 30%; min-width: 200px;" class="ml-10 my-2">
|
||||
</v-text-field>
|
||||
</div>
|
||||
@@ -131,12 +131,12 @@
|
||||
<v-progress-circular indeterminate color="primary"></v-progress-circular>
|
||||
</div>
|
||||
<div v-else-if="newConfigData && newConfigMetadata" class="config-preview-container">
|
||||
<h4 class="mb-3">使用新的配置文件</h4>
|
||||
<h4 class="mb-3">{{ tm('createDialog.newConfigTitle') }}</h4>
|
||||
<AstrBotCoreConfigWrapper :metadata="newConfigMetadata" :config_data="newConfigData" />
|
||||
</div>
|
||||
<div v-else class="text-center py-4 text-grey">
|
||||
<v-icon>mdi-information-outline</v-icon>
|
||||
<p class="mt-2">无法加载默认配置模板</p>
|
||||
<p class="mt-2">{{ tm('createDialog.newConfigLoadFailed') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -147,18 +147,18 @@
|
||||
<div>
|
||||
<v-btn v-if="isEditingRoutes" color="primary" variant="tonal" @click="addNewRoute" size="small">
|
||||
<v-icon start>mdi-plus</v-icon>
|
||||
添加路由规则
|
||||
{{ tm('createDialog.addRouteRule') }}
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-btn :color="isEditingRoutes ? 'grey' : 'primary'" variant="tonal" size="small"
|
||||
@click="toggleEditMode">
|
||||
<v-icon start>{{ isEditingRoutes ? 'mdi-eye' : 'mdi-pencil' }}</v-icon>
|
||||
{{ isEditingRoutes ? '查看' : '编辑' }}
|
||||
{{ isEditingRoutes ? tm('createDialog.viewMode') : tm('createDialog.editMode') }}
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<v-data-table :headers="routeTableHeaders" :items="platformRoutes" item-value="umop"
|
||||
no-data-text="该平台暂无路由规则,将使用默认配置文件" hide-default-footer :items-per-page="-1" class="mt-2"
|
||||
:no-data-text="tm('createDialog.noRouteRules')" hide-default-footer :items-per-page="-1" class="mt-2"
|
||||
variant="outlined">
|
||||
|
||||
<template v-slot:item.source="{ item }">
|
||||
@@ -170,9 +170,9 @@
|
||||
<small v-else>{{ getMessageTypeLabel(item.messageType) }}</small>
|
||||
<small class="mx-1">:</small>
|
||||
<v-text-field v-if="isEditingRoutes" v-model="item.sessionId" variant="outlined" density="compact"
|
||||
hide-details placeholder="会话ID或*">
|
||||
hide-details :placeholder="tm('createDialog.sessionIdPlaceholder')">
|
||||
</v-text-field>
|
||||
<small v-else>{{ item.sessionId === '*' ? '全部会话' : item.sessionId }}</small>
|
||||
<small v-else>{{ item.sessionId === '*' ? tm('createDialog.allSessions') : item.sessionId }}</small>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
</v-btn>
|
||||
</div>
|
||||
<small v-if="configInfoList.findIndex(c => c.id === item.configId) === -1" style="color: red;"
|
||||
class="ml-2">配置文件不存在</small>
|
||||
class="ml-2">{{ tm('createDialog.configMissing') }}</small>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item, index }">
|
||||
@@ -211,8 +211,7 @@
|
||||
</template>
|
||||
|
||||
</v-data-table>
|
||||
<small class="ml-2 mt-2 d-block" style="color: grey">*消息下发时,根据会话来源按顺序从上到下匹配首个符合条件的配置文件。使用 * 表示匹配所有。使用 /sid 指令获取会话
|
||||
ID。全部不匹配时将使用默认配置文件。</small>
|
||||
<small class="ml-2 mt-2 d-block" style="color: grey">{{ tm('createDialog.routeHint') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -266,10 +265,10 @@
|
||||
<v-card-actions class="px-4 pb-4">
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="error" @click="handleOneBotEmptyTokenWarningDismiss(true)">
|
||||
无视警告并继续创建
|
||||
{{ tm('createDialog.warningContinue') }}
|
||||
</v-btn>
|
||||
<v-btn color="primary" @click="handleOneBotEmptyTokenWarningDismiss(false)">
|
||||
重新修改
|
||||
{{ tm('createDialog.warningEditAgain') }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
@@ -286,9 +285,9 @@
|
||||
<v-card class="config-drawer-card" elevation="12">
|
||||
<div class="config-drawer-header">
|
||||
<div>
|
||||
<span class="text-h6">配置文件管理</span>
|
||||
<span class="text-h6">{{ tm('createDialog.configDrawerTitle') }}</span>
|
||||
<div v-if="configDrawerTargetId" class="text-caption text-grey">
|
||||
ID: {{ configDrawerTargetId }}
|
||||
{{ tm('createDialog.configDrawerIdLabel') }}: {{ configDrawerTargetId }}
|
||||
</div>
|
||||
</div>
|
||||
<v-btn icon variant="text" @click="closeConfigDrawer">
|
||||
@@ -359,23 +358,9 @@ export default {
|
||||
|
||||
// 平台配置文件表格(已弃用,改用 platformRoutes)
|
||||
platformConfigs: [],
|
||||
configTableHeaders: [
|
||||
{ title: '与此实例关联的配置文件 ID', key: 'name', sortable: false },
|
||||
{ title: '在此实例下的应用范围', key: 'scope', sortable: false },
|
||||
],
|
||||
|
||||
// 平台路由表
|
||||
platformRoutes: [],
|
||||
routeTableHeaders: [
|
||||
{ title: '消息会话来源(消息类型:会话 ID)', key: 'source', sortable: false, width: '60%' },
|
||||
{ title: '使用配置文件', key: 'configId', sortable: false, width: '20%' },
|
||||
{ title: '操作', key: 'actions', sortable: false, align: 'center', width: '20%' },
|
||||
],
|
||||
messageTypeOptions: [
|
||||
{ label: '全部消息', value: '*' },
|
||||
{ label: '群组消息(GroupMessage)', value: 'GroupMessage' },
|
||||
{ label: '私聊消息(FriendMessage)', value: 'FriendMessage' },
|
||||
],
|
||||
isEditingRoutes: false, // 编辑模式开关
|
||||
|
||||
// ID冲突确认对话框
|
||||
@@ -437,6 +422,26 @@ export default {
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
configTableHeaders() {
|
||||
return [
|
||||
{ title: this.tm('createDialog.configTableHeaders.configId'), key: 'name', sortable: false },
|
||||
{ title: this.tm('createDialog.configTableHeaders.scope'), key: 'scope', sortable: false },
|
||||
];
|
||||
},
|
||||
routeTableHeaders() {
|
||||
return [
|
||||
{ title: this.tm('createDialog.routeTableHeaders.source'), key: 'source', sortable: false, width: '60%' },
|
||||
{ title: this.tm('createDialog.routeTableHeaders.config'), key: 'configId', sortable: false, width: '20%' },
|
||||
{ title: this.tm('createDialog.routeTableHeaders.actions'), key: 'actions', sortable: false, align: 'center', width: '20%' },
|
||||
];
|
||||
},
|
||||
messageTypeOptions() {
|
||||
return [
|
||||
{ label: this.tm('createDialog.messageTypeOptions.all'), value: '*' },
|
||||
{ label: this.tm('createDialog.messageTypeOptions.group'), value: 'GroupMessage' },
|
||||
{ label: this.tm('createDialog.messageTypeOptions.friend'), value: 'FriendMessage' },
|
||||
];
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -603,7 +608,7 @@ export default {
|
||||
const targetId = configId || 'default';
|
||||
|
||||
if (configId && this.configInfoList.findIndex(c => c.id === configId) === -1) {
|
||||
this.showError('目标配置文件不存在,已打开配置页面以便检查。');
|
||||
this.showError(this.tm('messages.configNotFoundOpenConfig'));
|
||||
}
|
||||
|
||||
this.configDrawerTargetId = targetId;
|
||||
@@ -637,7 +642,7 @@ export default {
|
||||
const id = this.originalUpdatingPlatformId || this.updatingPlatformConfig.id;
|
||||
if (!id) {
|
||||
this.loading = false;
|
||||
this.showError('更新失败,缺少平台 ID。');
|
||||
this.showError(this.tm('messages.updateMissingPlatformId'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -655,7 +660,7 @@ export default {
|
||||
})
|
||||
|
||||
if (resp.data.status === 'error') {
|
||||
throw new Error(resp.data.message || '平台更新失败');
|
||||
throw new Error(resp.data.message || this.tm('messages.platformUpdateFailed'));
|
||||
}
|
||||
|
||||
// 同时更新路由表
|
||||
@@ -665,7 +670,7 @@ export default {
|
||||
this.showDialog = false;
|
||||
this.resetForm();
|
||||
this.$emit('refresh-config');
|
||||
this.showSuccess('更新成功');
|
||||
this.showSuccess(this.tm('messages.updateSuccess'));
|
||||
} catch (err) {
|
||||
this.loading = false;
|
||||
this.showError(err.response?.data?.message || err.message);
|
||||
@@ -710,7 +715,7 @@ export default {
|
||||
this.showDialog = false;
|
||||
this.resetForm();
|
||||
this.$emit('refresh-config');
|
||||
this.showSuccess(res.data.message || '平台添加成功,配置文件已更新');
|
||||
this.showSuccess(res.data.message || this.tm('messages.addSuccessWithConfig'));
|
||||
} catch (err) {
|
||||
this.loading = false;
|
||||
this.showError(err.response?.data?.message || err.message);
|
||||
@@ -738,7 +743,7 @@ export default {
|
||||
}
|
||||
|
||||
if (!configId) {
|
||||
throw new Error('无法获取配置文件ID');
|
||||
throw new Error(this.tm('messages.configIdMissing'));
|
||||
}
|
||||
|
||||
// 第二步:统一更新路由表
|
||||
@@ -755,7 +760,8 @@ export default {
|
||||
console.log(`成功更新路由表: ${umop} -> ${configId}`);
|
||||
} catch (err) {
|
||||
console.error('更新路由表失败:', err);
|
||||
throw new Error(`更新路由表失败: ${err.response?.data?.message || err.message}`);
|
||||
const errorMessage = err.response?.data?.message || err.message;
|
||||
throw new Error(this.tm('messages.routingUpdateFailed', { message: errorMessage }));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -778,7 +784,8 @@ export default {
|
||||
return newConfigId;
|
||||
} catch (err) {
|
||||
console.error('创建新配置文件失败:', err);
|
||||
throw new Error(`创建新配置文件失败: ${err.response?.data?.message || err.message}`);
|
||||
const errorMessage = err.response?.data?.message || err.message;
|
||||
throw new Error(this.tm('messages.createConfigFailed', { message: errorMessage }));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -922,7 +929,7 @@ export default {
|
||||
const newPlatformId = this.updatingPlatformConfig?.id || originalPlatformId;
|
||||
|
||||
if (!originalPlatformId && !newPlatformId) {
|
||||
throw new Error('无法获取平台 ID');
|
||||
throw new Error(this.tm('messages.platformIdMissing'));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -958,7 +965,8 @@ export default {
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('保存路由表失败:', err);
|
||||
throw new Error(`保存路由表失败: ${err.response?.data?.message || err.message}`);
|
||||
const errorMessage = err.response?.data?.message || err.message;
|
||||
throw new Error(this.tm('messages.routingSaveFailed', { message: errorMessage }));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -987,10 +995,10 @@ export default {
|
||||
// 获取消息类型标签
|
||||
getMessageTypeLabel(messageType) {
|
||||
const typeMap = {
|
||||
'*': '全部消息',
|
||||
'': '全部消息',
|
||||
'GroupMessage': '群组消息',
|
||||
'FriendMessage': '私聊消息'
|
||||
'*': this.tm('createDialog.messageTypeLabels.all'),
|
||||
'': this.tm('createDialog.messageTypeLabels.all'),
|
||||
'GroupMessage': this.tm('createDialog.messageTypeLabels.group'),
|
||||
'FriendMessage': this.tm('createDialog.messageTypeLabels.friend')
|
||||
};
|
||||
return typeMap[messageType] || messageType;
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
rounded="xl"
|
||||
size="small"
|
||||
>
|
||||
新增
|
||||
{{ tm('providerSources.add') }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list density="compact">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { VueMonacoEditor } from '@guolao/vue-monaco-editor'
|
||||
import { ref, computed } from 'vue'
|
||||
import ConfigItemRenderer from './ConfigItemRenderer.vue'
|
||||
import TemplateListEditor from './TemplateListEditor.vue'
|
||||
import { useI18n } from '@/i18n/composables'
|
||||
import { useI18n, useModuleI18n } from '@/i18n/composables'
|
||||
import axios from 'axios'
|
||||
import { useToast } from '@/utils/toast'
|
||||
|
||||
@@ -35,6 +35,12 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const { tm, getRaw } = useModuleI18n('features/config-metadata')
|
||||
|
||||
const translateIfKey = (value) => {
|
||||
if (!value || typeof value !== 'string') return value
|
||||
return getRaw(value) ? tm(value) : value
|
||||
}
|
||||
|
||||
const filteredIterable = computed(() => {
|
||||
if (!props.iterable) return {}
|
||||
@@ -134,11 +140,11 @@ function hasVisibleItemsAfter(items, currentIndex) {
|
||||
<template>
|
||||
<div class="config-section" v-if="iterable && metadata[metadataKey]?.type === 'object'">
|
||||
<v-list-item-title class="config-title">
|
||||
{{ metadata[metadataKey]?.description }} <span class="metadata-key">({{ metadataKey }})</span>
|
||||
{{ translateIfKey(metadata[metadataKey]?.description) }} <span class="metadata-key">({{ metadataKey }})</span>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle class="config-hint">
|
||||
<span v-if="metadata[metadataKey]?.obvious_hint && metadata[metadataKey]?.hint" class="important-hint">‼️</span>
|
||||
{{ metadata[metadataKey]?.hint }}
|
||||
{{ translateIfKey(metadata[metadataKey]?.hint) }}
|
||||
</v-list-item-subtitle>
|
||||
</div>
|
||||
|
||||
@@ -180,14 +186,14 @@ function hasVisibleItemsAfter(items, currentIndex) {
|
||||
<div class="config-section mb-2">
|
||||
<v-list-item-title class="config-title">
|
||||
<span v-if="metadata[metadataKey].items[key]?.description">
|
||||
{{ metadata[metadataKey].items[key]?.description }}
|
||||
{{ translateIfKey(metadata[metadataKey].items[key]?.description) }}
|
||||
<span class="property-key">({{ key }})</span>
|
||||
</span>
|
||||
<span v-else>{{ key }}</span>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle class="config-hint">
|
||||
<span v-if="metadata[metadataKey].items[key]?.obvious_hint && metadata[metadataKey].items[key]?.hint" class="important-hint">‼️</span>
|
||||
{{ metadata[metadataKey].items[key]?.hint }}
|
||||
{{ translateIfKey(metadata[metadataKey].items[key]?.hint) }}
|
||||
</v-list-item-subtitle>
|
||||
</div>
|
||||
<TemplateListEditor
|
||||
@@ -205,7 +211,7 @@ function hasVisibleItemsAfter(items, currentIndex) {
|
||||
<v-list-item density="compact">
|
||||
<v-list-item-title class="property-name">
|
||||
<span v-if="metadata[metadataKey].items[key]?.description">
|
||||
{{ metadata[metadataKey].items[key]?.description }}
|
||||
{{ translateIfKey(metadata[metadataKey].items[key]?.description) }}
|
||||
<span class="property-key">({{ key }})</span>
|
||||
</span>
|
||||
<span v-else>{{ key }}</span>
|
||||
@@ -214,7 +220,7 @@ function hasVisibleItemsAfter(items, currentIndex) {
|
||||
<v-list-item-subtitle class="property-hint">
|
||||
<span v-if="metadata[metadataKey].items[key]?.obvious_hint && metadata[metadataKey].items[key]?.hint"
|
||||
class="important-hint">‼️</span>
|
||||
{{ metadata[metadataKey].items[key]?.hint }}
|
||||
{{ translateIfKey(metadata[metadataKey].items[key]?.hint) }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-col>
|
||||
|
||||
@@ -59,14 +59,14 @@ export function useProviderSources(options: UseProviderSourcesOptions) {
|
||||
|
||||
let suppressSourceWatch = false
|
||||
|
||||
const providerTypes = [
|
||||
const providerTypes = computed(() => [
|
||||
{ value: 'chat_completion', label: tm('providers.tabs.chatCompletion'), icon: 'mdi-message-text' },
|
||||
{ value: 'agent_runner', label: tm('providers.tabs.agentRunner'), icon: 'mdi-robot' },
|
||||
{ value: 'speech_to_text', label: tm('providers.tabs.speechToText'), icon: 'mdi-microphone-message' },
|
||||
{ value: 'text_to_speech', label: tm('providers.tabs.textToSpeech'), icon: 'mdi-volume-high' },
|
||||
{ value: 'embedding', label: tm('providers.tabs.embedding'), icon: 'mdi-code-json' },
|
||||
{ value: 'rerank', label: tm('providers.tabs.rerank'), icon: 'mdi-compare-vertical' }
|
||||
]
|
||||
])
|
||||
|
||||
// ===== Computed =====
|
||||
const availableSourceTypes = computed(() => {
|
||||
|
||||
@@ -294,6 +294,235 @@
|
||||
},
|
||||
"platform_group": {
|
||||
"name": "Platform",
|
||||
"platform": {
|
||||
"description": "Message Platform Adapters",
|
||||
"active_send_mode": {
|
||||
"description": "Use Proactive Send API"
|
||||
},
|
||||
"appid": {
|
||||
"description": "App ID",
|
||||
"hint": "Required. App ID for the QQ Official Bot platform. See the docs for how to obtain it."
|
||||
},
|
||||
"callback_server_host": {
|
||||
"description": "Callback Server Host",
|
||||
"hint": "Callback server host. Leave empty to disable the callback server."
|
||||
},
|
||||
"card_template_id": {
|
||||
"description": "Card Template ID",
|
||||
"hint": "Optional. DingTalk interactive card template ID. When enabled, streaming replies will use interactive cards."
|
||||
},
|
||||
"discord_activity_name": {
|
||||
"description": "Discord Activity Name",
|
||||
"hint": "Optional Discord activity name. Leave empty to disable."
|
||||
},
|
||||
"discord_command_register": {
|
||||
"description": "Auto-register plugin commands as Discord slash commands"
|
||||
},
|
||||
"discord_proxy": {
|
||||
"description": "Discord Proxy URL",
|
||||
"hint": "Optional proxy URL: http://ip:port"
|
||||
},
|
||||
"discord_token": {
|
||||
"description": "Discord Bot Token",
|
||||
"hint": "Enter your Discord Bot Token here."
|
||||
},
|
||||
"enable": {
|
||||
"description": "Enable",
|
||||
"hint": "Whether to enable this adapter. Disabled adapters will not receive messages."
|
||||
},
|
||||
"enable_group_c2c": {
|
||||
"description": "Enable Message List Private Chat",
|
||||
"hint": "When enabled, the bot can receive private chats from QQ message list. You may need to add the bot as a friend by scanning a QR code in the QQ bot platform. See docs."
|
||||
},
|
||||
"enable_guild_direct_message": {
|
||||
"description": "Enable Guild Direct Messages",
|
||||
"hint": "When enabled, the bot can receive guild direct messages."
|
||||
},
|
||||
"id": {
|
||||
"description": "Bot Name",
|
||||
"hint": "Bot name"
|
||||
},
|
||||
"is_sandbox": {
|
||||
"description": "Sandbox Mode"
|
||||
},
|
||||
"kf_name": {
|
||||
"description": "WeChat Customer Service Account Name",
|
||||
"hint": "Optional. Customer service account name (not ID). Get it at https://kf.weixin.qq.com/kf/frame#/accounts"
|
||||
},
|
||||
"lark_bot_name": {
|
||||
"description": "Lark Bot Name",
|
||||
"hint": "Must be correct; otherwise @ mentions will not wake the bot and only prefix wake will work."
|
||||
},
|
||||
"lark_connection_mode": {
|
||||
"description": "Subscription Mode",
|
||||
"labels": [
|
||||
"Long Connection Mode",
|
||||
"Webhook Server Mode"
|
||||
]
|
||||
},
|
||||
"lark_encrypt_key": {
|
||||
"description": "Encrypt Key",
|
||||
"hint": "Encryption key for decrypting Lark callback data."
|
||||
},
|
||||
"lark_verification_token": {
|
||||
"description": "Verification Token",
|
||||
"hint": "Token for verifying Lark callback requests."
|
||||
},
|
||||
"misskey_allow_insecure_downloads": {
|
||||
"description": "Allow Insecure Downloads (Disable SSL Verification)",
|
||||
"hint": "If remote servers have certificate issues, SSL verification will be disabled as a fallback. Use only when necessary due to security risks."
|
||||
},
|
||||
"misskey_default_visibility": {
|
||||
"description": "Default Post Visibility",
|
||||
"hint": "Default visibility for bot posts. public: public, home: home timeline, followers: followers only."
|
||||
},
|
||||
"misskey_download_chunk_size": {
|
||||
"description": "Stream Download Chunk Size (bytes)",
|
||||
"hint": "Bytes read per chunk during streaming download and MD5 calculation. Too small increases overhead; too large uses more memory."
|
||||
},
|
||||
"misskey_download_timeout": {
|
||||
"description": "Remote Download Timeout (seconds)",
|
||||
"hint": "Timeout for downloading remote files (seconds), used when falling back to local upload."
|
||||
},
|
||||
"misskey_enable_chat": {
|
||||
"description": "Enable Chat Message Responses",
|
||||
"hint": "When enabled, the bot listens and responds to private chat messages."
|
||||
},
|
||||
"misskey_enable_file_upload": {
|
||||
"description": "Enable File Upload to Misskey",
|
||||
"hint": "When enabled, the adapter uploads files in message chains to Misskey. URL files try server-side upload first; if async upload fails, it falls back to local download and upload."
|
||||
},
|
||||
"misskey_instance_url": {
|
||||
"description": "Misskey Instance URL",
|
||||
"hint": "e.g. https://misskey.example. The Misskey instance where the bot account lives."
|
||||
},
|
||||
"misskey_local_only": {
|
||||
"description": "Local Only (No Federation)",
|
||||
"hint": "When enabled, bot posts are visible only on this instance and are not federated."
|
||||
},
|
||||
"misskey_max_download_bytes": {
|
||||
"description": "Max Download Size (bytes)",
|
||||
"hint": "To limit download size to prevent OOM, set the maximum bytes; empty or null means no limit."
|
||||
},
|
||||
"misskey_token": {
|
||||
"description": "Misskey Access Token",
|
||||
"hint": "API access token generated in the connection service settings."
|
||||
},
|
||||
"misskey_upload_concurrency": {
|
||||
"description": "Upload Concurrency Limit",
|
||||
"hint": "Max number of concurrent upload tasks (integer, default 3)."
|
||||
},
|
||||
"misskey_upload_folder": {
|
||||
"description": "Target Drive Folder ID",
|
||||
"hint": "Optional: ID of the target folder in Misskey drive. Leave empty to use the root folder."
|
||||
},
|
||||
"port": {
|
||||
"description": "Callback Server Port",
|
||||
"hint": "Callback server port. Leave empty to disable the callback server."
|
||||
},
|
||||
"satori_api_base_url": {
|
||||
"description": "Satori API Endpoint",
|
||||
"hint": "Base URL for the Satori API."
|
||||
},
|
||||
"satori_auto_reconnect": {
|
||||
"description": "Enable Auto Reconnect",
|
||||
"hint": "Automatically reconnect the WebSocket when disconnected."
|
||||
},
|
||||
"satori_endpoint": {
|
||||
"description": "Satori WebSocket Endpoint",
|
||||
"hint": "WebSocket endpoint for Satori events."
|
||||
},
|
||||
"satori_heartbeat_interval": {
|
||||
"description": "Satori Heartbeat Interval",
|
||||
"hint": "Interval in seconds between heartbeat messages."
|
||||
},
|
||||
"satori_reconnect_delay": {
|
||||
"description": "Satori Reconnect Delay",
|
||||
"hint": "Delay before attempting to reconnect (seconds)."
|
||||
},
|
||||
"satori_token": {
|
||||
"description": "Satori Token",
|
||||
"hint": "Token for Satori API authentication."
|
||||
},
|
||||
"secret": {
|
||||
"description": "Secret",
|
||||
"hint": "Required."
|
||||
},
|
||||
"slack_connection_mode": {
|
||||
"description": "Slack Connection Mode",
|
||||
"hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode."
|
||||
},
|
||||
"slack_webhook_host": {
|
||||
"description": "Slack Webhook Host",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"slack_webhook_path": {
|
||||
"description": "Slack Webhook Path",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"slack_webhook_port": {
|
||||
"description": "Slack Webhook Port",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"telegram_command_auto_refresh": {
|
||||
"description": "Telegram Command Auto Refresh",
|
||||
"hint": "When enabled, AstrBot automatically refreshes Telegram commands at runtime. (Setting this alone has no effect)"
|
||||
},
|
||||
"telegram_command_register": {
|
||||
"description": "Telegram Command Registration",
|
||||
"hint": "When enabled, AstrBot automatically registers Telegram commands."
|
||||
},
|
||||
"telegram_command_register_interval": {
|
||||
"description": "Telegram Command Auto Refresh Interval",
|
||||
"hint": "Telegram command auto-refresh interval in seconds."
|
||||
},
|
||||
"telegram_token": {
|
||||
"description": "Bot Token",
|
||||
"hint": "If you are in mainland China, set a proxy or change api_base in Other Settings."
|
||||
},
|
||||
"type": {
|
||||
"description": "Adapter Type"
|
||||
},
|
||||
"unified_webhook_mode": {
|
||||
"description": "Unified Webhook Mode",
|
||||
"hint": "When enabled, use AstrBot unified webhook entry without opening a separate port. Callback URL is /api/platform/webhook/{webhook_uuid}."
|
||||
},
|
||||
"webhook_uuid": {
|
||||
"description": "Webhook UUID",
|
||||
"hint": "Unique identifier for unified webhook mode; generated when creating the platform."
|
||||
},
|
||||
"wecom_ai_bot_name": {
|
||||
"description": "WeCom AI Bot Name",
|
||||
"hint": "Must be correct; otherwise some commands won't work."
|
||||
},
|
||||
"wecomaibot_friend_message_welcome_text": {
|
||||
"description": "WeCom AI Bot DM Welcome Message",
|
||||
"hint": "When a user enters a DM session on that day, reply with a welcome message. Leave empty to disable."
|
||||
},
|
||||
"wecomaibot_init_respond_text": {
|
||||
"description": "WeCom AI Bot Initial Response Text",
|
||||
"hint": "First reply when the bot receives a message. Leave empty to use default."
|
||||
},
|
||||
"wpp_active_message_poll": {
|
||||
"description": "Enable Proactive Message Polling",
|
||||
"hint": "Only enable if WeChat messages are not syncing to AstrBot on time. Disabled by default."
|
||||
},
|
||||
"wpp_active_message_poll_interval": {
|
||||
"description": "Proactive Message Poll Interval",
|
||||
"hint": "Interval in seconds, default 3, should not exceed 60 or it may be considered old messages."
|
||||
},
|
||||
"ws_reverse_host": {
|
||||
"description": "Reverse WebSocket Host",
|
||||
"hint": "AstrBot acts as the server."
|
||||
},
|
||||
"ws_reverse_port": {
|
||||
"description": "Reverse WebSocket Port"
|
||||
},
|
||||
"ws_reverse_token": {
|
||||
"description": "Reverse WebSocket Token",
|
||||
"hint": "Reverse WebSocket token. If not set, token verification is disabled."
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"description": "General",
|
||||
"admins_id": {
|
||||
@@ -619,6 +848,443 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"provider_group": {
|
||||
"provider": {
|
||||
"genie_onnx_model_dir": {
|
||||
"description": "ONNX Model Directory",
|
||||
"hint": "The directory path containing the ONNX model files"
|
||||
},
|
||||
"genie_language": {
|
||||
"description": "Language"
|
||||
},
|
||||
"xai_native_search": {
|
||||
"description": "Enable native search",
|
||||
"hint": "When enabled, uses xAI Chat Completions native Live Search for web queries (billed on demand). Only applies to xAI providers."
|
||||
},
|
||||
"rerank_api_base": {
|
||||
"description": "Rerank Model API Base URL",
|
||||
"hint": "AstrBot appends /v1/rerank to the request URL."
|
||||
},
|
||||
"rerank_api_key": {
|
||||
"description": "API Key",
|
||||
"hint": "Leave empty if no API key is required."
|
||||
},
|
||||
"rerank_model": {
|
||||
"description": "Rerank model name"
|
||||
},
|
||||
"return_documents": {
|
||||
"description": "Return source documents in rerank results",
|
||||
"hint": "Default is false to reduce network overhead."
|
||||
},
|
||||
"instruct": {
|
||||
"description": "Custom rerank task description",
|
||||
"hint": "Only effective for qwen3-rerank models. Recommended to write in English."
|
||||
},
|
||||
"launch_model_if_not_running": {
|
||||
"description": "Auto-start model if not running",
|
||||
"hint": "If the model is not running in Xinference, attempt to start it automatically. Recommended to disable in production."
|
||||
},
|
||||
"modalities": {
|
||||
"description": "Model capabilities",
|
||||
"hint": "Modalities supported by the model. If the model does not support images, uncheck image.",
|
||||
"labels": [
|
||||
"Text",
|
||||
"Image",
|
||||
"Tool use"
|
||||
]
|
||||
},
|
||||
"custom_headers": {
|
||||
"description": "Custom request headers",
|
||||
"hint": "Key/value pairs added here are merged into the OpenAI SDK default_headers for custom HTTP headers. Values must be strings."
|
||||
},
|
||||
"custom_extra_body": {
|
||||
"description": "Custom request body parameters",
|
||||
"hint": "Add extra parameters to requests, such as temperature, top_p, max_tokens, etc.",
|
||||
"template_schema": {
|
||||
"temperature": {
|
||||
"description": "Temperature",
|
||||
"hint": "Controls randomness, typically 0-2. Higher is more random.",
|
||||
"name": "Temperature"
|
||||
},
|
||||
"top_p": {
|
||||
"description": "Top-p sampling",
|
||||
"hint": "Nucleus sampling parameter, usually 0-1. Controls probability mass considered.",
|
||||
"name": "Top-p"
|
||||
},
|
||||
"max_tokens": {
|
||||
"description": "Max tokens",
|
||||
"hint": "Maximum number of generated tokens.",
|
||||
"name": "Max Tokens"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gpt_weights_path": {
|
||||
"description": "GPT model file path",
|
||||
"hint": "The .ckpt file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS)."
|
||||
},
|
||||
"sovits_weights_path": {
|
||||
"description": "SoVITS model file path",
|
||||
"hint": "The .pth file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS)."
|
||||
},
|
||||
"gsv_default_parms": {
|
||||
"description": "GPT_SoVITS default parameters",
|
||||
"hint": "Reference audio file path and text are required; other parameters are optional.",
|
||||
"gsv_ref_audio_path": {
|
||||
"description": "Reference audio file path",
|
||||
"hint": "Required! Use an absolute path without quotes."
|
||||
},
|
||||
"gsv_prompt_text": {
|
||||
"description": "Reference audio text",
|
||||
"hint": "Required! Provide the transcript of the reference audio."
|
||||
},
|
||||
"gsv_prompt_lang": {
|
||||
"description": "Reference audio text language",
|
||||
"hint": "Language of the reference audio text; default is Chinese."
|
||||
},
|
||||
"gsv_aux_ref_audio_paths": {
|
||||
"description": "Auxiliary reference audio file paths",
|
||||
"hint": "Auxiliary reference audio files; optional."
|
||||
},
|
||||
"gsv_text_lang": {
|
||||
"description": "Text language",
|
||||
"hint": "Default is Chinese."
|
||||
},
|
||||
"gsv_top_k": {
|
||||
"description": "Speech diversity",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_top_p": {
|
||||
"description": "Nucleus sampling threshold",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_temperature": {
|
||||
"description": "Speech randomness",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_text_split_method": {
|
||||
"description": "Text splitting method",
|
||||
"hint": "Options: `cut0` no split, `cut1` split every 4 sentences, `cut2` split every 50 chars, `cut3` split by Chinese period, `cut4` split by English period, `cut5` split by punctuation."
|
||||
},
|
||||
"gsv_batch_size": {
|
||||
"description": "Batch size",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_batch_threshold": {
|
||||
"description": "Batch threshold",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_split_bucket": {
|
||||
"description": "Split text into buckets for parallel processing",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_speed_factor": {
|
||||
"description": "Speech playback speed",
|
||||
"hint": "1 is the original speed."
|
||||
},
|
||||
"gsv_fragment_interval": {
|
||||
"description": "Interval between speech segments",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_streaming_mode": {
|
||||
"description": "Enable streaming mode",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_seed": {
|
||||
"description": "Random seed",
|
||||
"hint": "For reproducible results."
|
||||
},
|
||||
"gsv_parallel_infer": {
|
||||
"description": "Run inference in parallel",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_repetition_penalty": {
|
||||
"description": "Repetition penalty",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_media_type": {
|
||||
"description": "Output media type",
|
||||
"hint": "Recommended: wav"
|
||||
}
|
||||
},
|
||||
"embedding_dimensions": {
|
||||
"description": "Embedding dimensions",
|
||||
"hint": "Embedding vector dimensions. May need adjustment per model; see model documentation. This must be correct or the vector database will not work."
|
||||
},
|
||||
"embedding_model": {
|
||||
"description": "Embedding model",
|
||||
"hint": "Embedding model name."
|
||||
},
|
||||
"embedding_api_key": {
|
||||
"description": "API Key"
|
||||
},
|
||||
"embedding_api_base": {
|
||||
"description": "API Base URL"
|
||||
},
|
||||
"volcengine_cluster": {
|
||||
"description": "Volcengine cluster",
|
||||
"hint": "For voice cloning models, choose volcano_icl or volcano_icl_concurr; default is volcano_tts."
|
||||
},
|
||||
"volcengine_voice_type": {
|
||||
"description": "Volcengine voice",
|
||||
"hint": "Enter voice id (Voice_type)."
|
||||
},
|
||||
"volcengine_speed_ratio": {
|
||||
"description": "Speech rate",
|
||||
"hint": "Speech rate, range 0.2 to 3.0, default 1.0."
|
||||
},
|
||||
"volcengine_volume_ratio": {
|
||||
"description": "Volume",
|
||||
"hint": "Volume, range 0.0 to 2.0, default 1.0."
|
||||
},
|
||||
"azure_tts_voice": {
|
||||
"description": "Voice style",
|
||||
"hint": "API voice name"
|
||||
},
|
||||
"azure_tts_style": {
|
||||
"description": "Style",
|
||||
"hint": "A voice-specific speaking style. Can express emotions like happy, sympathetic, and calm."
|
||||
},
|
||||
"azure_tts_role": {
|
||||
"description": "Role (optional)",
|
||||
"hint": "Speaking role-play. The voice can emulate different ages and genders without changing the voice name. For example, a male voice can raise pitch to simulate a female voice, but the voice name does not change. If the role is missing or unsupported, this attribute is ignored."
|
||||
},
|
||||
"azure_tts_rate": {
|
||||
"description": "Speech rate",
|
||||
"hint": "Controls speaking rate. You can apply the rate at word or sentence level. Rate should be 0.5x to 2x of original audio."
|
||||
},
|
||||
"azure_tts_volume": {
|
||||
"description": "Speech volume",
|
||||
"hint": "Controls volume level. You can apply changes at sentence level. Use 0.0 to 100.0 (quiet to loud, e.g., 75). Default is 100.0."
|
||||
},
|
||||
"azure_tts_region": {
|
||||
"description": "API region",
|
||||
"hint": "Region where Azure TTS processes data. See https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions"
|
||||
},
|
||||
"azure_tts_subscription_key": {
|
||||
"description": "Service subscription key",
|
||||
"hint": "Azure TTS subscription key (not a token)."
|
||||
},
|
||||
"dashscope_tts_voice": {
|
||||
"description": "Voice"
|
||||
},
|
||||
"gm_resp_image_modal": {
|
||||
"description": "Enable image modality",
|
||||
"hint": "When enabled, responses can include images. Requires model support or it will error. See the Google Gemini website for supported models. Tip: if you need image generation, disable the `Enable member recognition` setting for better results."
|
||||
},
|
||||
"gm_native_search": {
|
||||
"description": "Enable native search",
|
||||
"hint": "When enabled, all function tools are disabled. Check official docs for free quota limits."
|
||||
},
|
||||
"gm_native_coderunner": {
|
||||
"description": "Enable native code runner",
|
||||
"hint": "When enabled, all function tools are disabled."
|
||||
},
|
||||
"gm_url_context": {
|
||||
"description": "Enable URL context",
|
||||
"hint": "When enabled, all function tools are disabled."
|
||||
},
|
||||
"gm_safety_settings": {
|
||||
"description": "Safety filters",
|
||||
"hint": "Set the safety filtering level for model input. Levels: NONE (no blocking), HIGH (block high risk), MEDIUM_AND_ABOVE (block medium risk and above), LOW_AND_ABOVE (block low risk and above). See Gemini API docs.",
|
||||
"harassment": {
|
||||
"description": "Harassment",
|
||||
"hint": "Negative or harmful comments"
|
||||
},
|
||||
"hate_speech": {
|
||||
"description": "Hate speech",
|
||||
"hint": "Rude, disrespectful, or profane content"
|
||||
},
|
||||
"sexually_explicit": {
|
||||
"description": "Sexually explicit content",
|
||||
"hint": "References to sexual acts or other obscene content"
|
||||
},
|
||||
"dangerous_content": {
|
||||
"description": "Dangerous content",
|
||||
"hint": "Content that promotes, encourages, or assists harmful behavior"
|
||||
}
|
||||
},
|
||||
"gm_thinking_config": {
|
||||
"description": "Thinking Config",
|
||||
"budget": {
|
||||
"description": "Thinking Budget",
|
||||
"hint": "Guides the model on the specific number of thinking tokens to use for reasoning. See: https://ai.google.dev/gemini-api/docs/thinking#set-budget"
|
||||
},
|
||||
"level": {
|
||||
"description": "Thinking Level",
|
||||
"hint": "Recommended for Gemini 3 models and onwards, lets you control reasoning behavior.See: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels"
|
||||
}
|
||||
},
|
||||
"anth_thinking_config": {
|
||||
"description": "Thinking Config",
|
||||
"budget": {
|
||||
"description": "Thinking Budget",
|
||||
"hint": "Anthropic thinking.budget_tokens param. Must >= 1024. See: https://platform.claude.com/docs/en/build-with-claude/extended-thinking"
|
||||
}
|
||||
},
|
||||
"minimax-group-id": {
|
||||
"description": "User group",
|
||||
"hint": "Visible in Account Management -> Basic Info."
|
||||
},
|
||||
"minimax-langboost": {
|
||||
"description": "Target language/dialect",
|
||||
"hint": "Enhances recognition for specified languages/dialects and improves speech performance in those scenarios."
|
||||
},
|
||||
"minimax-voice-speed": {
|
||||
"description": "Speech rate",
|
||||
"hint": "Speech speed for synthesis, range [0.5, 2], default 1.0. Higher is faster."
|
||||
},
|
||||
"minimax-voice-vol": {
|
||||
"description": "Volume",
|
||||
"hint": "Volume for synthesis, range (0, 10], default 1.0. Higher is louder."
|
||||
},
|
||||
"minimax-voice-pitch": {
|
||||
"description": "Pitch",
|
||||
"hint": "Pitch for synthesis, range [-12, 12], default 0."
|
||||
},
|
||||
"minimax-is-timber-weight": {
|
||||
"description": "Enable mixed voices",
|
||||
"hint": "Enable mixing up to four voices with custom weights. When enabled, single voice settings are ignored."
|
||||
},
|
||||
"minimax-timber-weight": {
|
||||
"description": "Mixed voices",
|
||||
"hint": "Mixed voices and their weights. Up to four voices, integer weights in [1, 100]. Get presets and templates from the official API TTS debug console. Must be a JSON string; check the console to confirm parsing. See defaults and the official code preview for structure."
|
||||
},
|
||||
"minimax-voice-id": {
|
||||
"description": "Single voice",
|
||||
"hint": "Single voice ID; see the official documentation."
|
||||
},
|
||||
"minimax-voice-emotion": {
|
||||
"description": "Emotion",
|
||||
"hint": "Controls emotion of synthesized speech. When set to auto, it selects emotion based on text."
|
||||
},
|
||||
"minimax-voice-latex": {
|
||||
"description": "Read LaTeX formulas",
|
||||
"hint": "Read LaTeX formulas, but ensure input text is formatted per the official requirements."
|
||||
},
|
||||
"minimax-voice-english-normalization": {
|
||||
"description": "English text normalization",
|
||||
"hint": "Improves number-reading performance but slightly increases latency."
|
||||
},
|
||||
"rag_options": {
|
||||
"description": "RAG options",
|
||||
"hint": "Knowledge base retrieval settings, optional. Only supported for Agent app types (agent apps, including RAG apps). For Bailian apps, enabling this disables multi-turn conversations.",
|
||||
"pipeline_ids": {
|
||||
"description": "Knowledge base ID list",
|
||||
"hint": "Retrieve all documents in the specified knowledge bases. Go to https://bailian.console.aliyun.com/ Data Apps -> Knowledge Index to create and get IDs."
|
||||
},
|
||||
"file_ids": {
|
||||
"description": "Unstructured document IDs",
|
||||
"hint": "Retrieve specified unstructured documents. Go to https://bailian.console.aliyun.com/ Data Management to create and get IDs."
|
||||
},
|
||||
"output_reference": {
|
||||
"description": "Output knowledge base/document references",
|
||||
"hint": "Append reference sources to the end of each answer. Default is False."
|
||||
}
|
||||
},
|
||||
"sensevoice_hint": {
|
||||
"description": "Deploy SenseVoice",
|
||||
"hint": "Before enabling, install funasr, funasr_onnx, torchaudio, torch, modelscope, and jieba (CPU by default, about 1 GB download), and install ffmpeg. Otherwise STT will not work."
|
||||
},
|
||||
"is_emotion": {
|
||||
"description": "Emotion recognition",
|
||||
"hint": "Enable emotion recognition. happy?sad?angry?neutral?fearful?disgusted?surprised?unknown"
|
||||
},
|
||||
"stt_model": {
|
||||
"description": "Model name",
|
||||
"hint": "Model name on modelscope. Default: iic/SenseVoiceSmall."
|
||||
},
|
||||
"variables": {
|
||||
"description": "Workflow fixed input variables",
|
||||
"hint": "Optional. Fixed workflow input variables are used as workflow inputs. You can also set variables dynamically with /set during a chat. If names conflict, dynamic settings take precedence."
|
||||
},
|
||||
"dashscope_app_type": {
|
||||
"description": "App type",
|
||||
"hint": "Bailian app type."
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Timeout",
|
||||
"hint": "Timeout in seconds."
|
||||
},
|
||||
"openai-tts-voice": {
|
||||
"description": "voice",
|
||||
"hint": "OpenAI TTS voice. OpenAI defaults: 'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'."
|
||||
},
|
||||
"fishaudio-tts-character": {
|
||||
"description": "character",
|
||||
"hint": "Fishaudio TTS character. Default is Klee. More roles: https://fish.audio/zh-CN/discovery"
|
||||
},
|
||||
"fishaudio-tts-reference-id": {
|
||||
"description": "reference_id",
|
||||
"hint": "Fishaudio TTS reference model ID (optional). If set, the model ID is used directly instead of looking up by role name. Example: 626bb6d3f3364c9cbc3aa6a67300a664. More models: https://fish.audio/zh-CN/discovery; open a model detail page to copy the model ID."
|
||||
},
|
||||
"whisper_hint": {
|
||||
"description": "Notes for local Whisper deployment",
|
||||
"hint": "Before enabling, install the openai-whisper library (NVIDIA users download ~2GB mainly for torch and cuda; CPU users download ~1GB), and install ffmpeg. Otherwise STT will not work."
|
||||
},
|
||||
"id": {
|
||||
"description": "ID"
|
||||
},
|
||||
"type": {
|
||||
"description": "Provider category"
|
||||
},
|
||||
"provider_type": {
|
||||
"description": "Provider capability type"
|
||||
},
|
||||
"enable": {
|
||||
"description": "Enable"
|
||||
},
|
||||
"key": {
|
||||
"description": "API Key"
|
||||
},
|
||||
"api_base": {
|
||||
"description": "API Base URL"
|
||||
},
|
||||
"model": {
|
||||
"description": "Model ID",
|
||||
"hint": "Model name, e.g., gpt-4o-mini, deepseek-chat."
|
||||
},
|
||||
"max_context_tokens": {
|
||||
"description": "Model context window size",
|
||||
"hint": "Maximum context tokens. If 0, it auto-fills from model metadata (if available); you can also edit manually."
|
||||
},
|
||||
"dify_api_key": {
|
||||
"description": "API Key",
|
||||
"hint": "Dify API Key. This field is required."
|
||||
},
|
||||
"dify_api_base": {
|
||||
"description": "API Base URL",
|
||||
"hint": "Dify API Base URL. Default: https://api.dify.ai/v1"
|
||||
},
|
||||
"dify_api_type": {
|
||||
"description": "Dify app type",
|
||||
"hint": "Dify API type. According to Dify docs, supported types are chat, chatflow, agent, workflow."
|
||||
},
|
||||
"dify_workflow_output_key": {
|
||||
"description": "Dify workflow output variable name",
|
||||
"hint": "Dify workflow output variable name. Only used when app type is workflow. Default: astrbot_wf_output."
|
||||
},
|
||||
"dify_query_input_key": {
|
||||
"description": "Prompt input variable name",
|
||||
"hint": "Input variable name for the message text. Default: astrbot_text_query."
|
||||
},
|
||||
"coze_api_key": {
|
||||
"description": "Coze API Key",
|
||||
"hint": "Coze API key for accessing Coze services."
|
||||
},
|
||||
"bot_id": {
|
||||
"description": "Bot ID",
|
||||
"hint": "Coze bot ID, obtained after creating a bot on the Coze platform."
|
||||
},
|
||||
"coze_api_base": {
|
||||
"description": "API Base URL",
|
||||
"hint": "Base URL for the Coze API. Default: https://api.coze.cn"
|
||||
},
|
||||
"auto_save_history": {
|
||||
"description": "Conversation history managed by Coze",
|
||||
"hint": "When enabled, Coze manages conversation history. AstrBot's locally saved context will not take effect (read-only), and operations on AstrBot context will not apply. If disabled, AstrBot manages the context."
|
||||
}
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"documentation": "Official Documentation",
|
||||
"support": "Join Support Group",
|
||||
|
||||
@@ -45,12 +45,67 @@
|
||||
},
|
||||
"invalidPlatformId": "Platform ID cannot contain ':' or '!'."
|
||||
},
|
||||
"createDialog": {
|
||||
"step1Title": "Choose Platform Category",
|
||||
"step1Hint": "Where do you want to connect the bot? e.g. QQ, WeCom, Feishu, Discord, Telegram.",
|
||||
"platformTypeLabel": "Platform Category",
|
||||
"configFileTitle": "Config File",
|
||||
"optional": "Optional",
|
||||
"configHint": "How do you want to configure the bot? The config file includes model, persona, knowledge base, plugins, and more.",
|
||||
"configDefaultHint": "Uses the default config file \"default\" by default. You can configure it later.",
|
||||
"useExistingConfig": "Use existing config file",
|
||||
"selectConfigLabel": "Select config file",
|
||||
"createNewConfig": "Create new config file",
|
||||
"newConfigNameLabel": "New config name",
|
||||
"newConfigTitle": "Use new config file",
|
||||
"newConfigLoadFailed": "Failed to load default config template",
|
||||
"addRouteRule": "Add route rule",
|
||||
"viewMode": "View",
|
||||
"editMode": "Edit",
|
||||
"noRouteRules": "No route rules for this platform. The default config file will be used.",
|
||||
"sessionIdPlaceholder": "Session ID or *",
|
||||
"allSessions": "All sessions",
|
||||
"configMissing": "Config file not found",
|
||||
"routeHint": "When delivering messages, the first matching config file from top to bottom is used based on session source. Use * to match all. Use /sid to get the session ID. If none match, the default config file is used.",
|
||||
"warningContinue": "Ignore warning and continue",
|
||||
"warningEditAgain": "Edit again",
|
||||
"configDrawerTitle": "Config File Management",
|
||||
"configDrawerIdLabel": "ID",
|
||||
"configTableHeaders": {
|
||||
"configId": "Config ID linked to this instance",
|
||||
"scope": "Scope in this instance"
|
||||
},
|
||||
"routeTableHeaders": {
|
||||
"source": "Message Source (Type: Session ID)",
|
||||
"config": "Config File",
|
||||
"actions": "Actions"
|
||||
},
|
||||
"messageTypeOptions": {
|
||||
"all": "All messages",
|
||||
"group": "Group messages (GroupMessage)",
|
||||
"friend": "Direct messages (FriendMessage)"
|
||||
},
|
||||
"messageTypeLabels": {
|
||||
"all": "All messages",
|
||||
"group": "Group messages",
|
||||
"friend": "Direct messages"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"updateSuccess": "Update successful!",
|
||||
"addSuccess": "Add successful!",
|
||||
"deleteSuccess": "Delete successful!",
|
||||
"statusUpdateSuccess": "Status update successful!",
|
||||
"deleteConfirm": "Are you sure you want to delete platform adapter"
|
||||
"deleteConfirm": "Are you sure you want to delete platform adapter",
|
||||
"configNotFoundOpenConfig": "Target config file not found. Opened the config page for review.",
|
||||
"updateMissingPlatformId": "Update failed: missing platform ID.",
|
||||
"platformUpdateFailed": "Platform update failed.",
|
||||
"addSuccessWithConfig": "Platform added. Config file updated.",
|
||||
"configIdMissing": "Unable to get config file ID.",
|
||||
"routingUpdateFailed": "Failed to update routing table: {message}",
|
||||
"createConfigFailed": "Failed to create config file: {message}",
|
||||
"platformIdMissing": "Unable to get platform ID.",
|
||||
"routingSaveFailed": "Failed to save routing table: {message}"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "Enabled",
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
},
|
||||
"providerSources": {
|
||||
"title": "Provider Sources",
|
||||
"add": "Add",
|
||||
"empty": "No provider sources",
|
||||
"selectHint": "Please select a provider source",
|
||||
"save": "Save Configuration",
|
||||
@@ -141,4 +142,4 @@
|
||||
"modelId": "Model ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,10 @@
|
||||
},
|
||||
"context_limit_reached_strategy": {
|
||||
"description": "超出模型上下文窗口时的处理方式",
|
||||
"labels": ["按对话轮数截断", "由 LLM 压缩上下文"],
|
||||
"labels": [
|
||||
"按对话轮数截断",
|
||||
"由 LLM 压缩上下文"
|
||||
],
|
||||
"hint": "当按对话轮数截断时,会根据上面\"丢弃对话轮数\"的配置丢弃最旧的 N 轮对话。当由 LLM 压缩上下文时,会使用指定的模型进行上下文压缩。"
|
||||
},
|
||||
"llm_compress_instruction": {
|
||||
@@ -272,7 +275,6 @@
|
||||
"关闭流式回复"
|
||||
]
|
||||
},
|
||||
|
||||
"wake_prefix": {
|
||||
"description": "LLM 聊天额外唤醒前缀",
|
||||
"hint": "如果唤醒前缀为 /, 额外聊天唤醒前缀为 chat,则需要 /chat 才会触发 LLM 请求"
|
||||
@@ -295,6 +297,235 @@
|
||||
},
|
||||
"platform_group": {
|
||||
"name": "平台配置",
|
||||
"platform": {
|
||||
"description": "消息平台适配器",
|
||||
"active_send_mode": {
|
||||
"description": "是否换用主动发送接口"
|
||||
},
|
||||
"appid": {
|
||||
"description": "appid",
|
||||
"hint": "必填项。QQ 官方机器人平台的 appid。如何获取请参考文档。"
|
||||
},
|
||||
"callback_server_host": {
|
||||
"description": "回调服务器主机",
|
||||
"hint": "回调服务器主机。留空则不启用回调服务器。"
|
||||
},
|
||||
"card_template_id": {
|
||||
"description": "卡片模板 ID",
|
||||
"hint": "可选。钉钉互动卡片模板 ID。启用后将使用互动卡片进行流式回复。"
|
||||
},
|
||||
"discord_activity_name": {
|
||||
"description": "Discord 活动名称",
|
||||
"hint": "可选的 Discord 活动名称。留空则不设置活动。"
|
||||
},
|
||||
"discord_command_register": {
|
||||
"description": "是否自动将插件指令注册为 Discord 斜杠指令"
|
||||
},
|
||||
"discord_proxy": {
|
||||
"description": "Discord 代理地址",
|
||||
"hint": "可选的代理地址:http://ip:port"
|
||||
},
|
||||
"discord_token": {
|
||||
"description": "Discord Bot Token",
|
||||
"hint": "在此处填入你的 Discord Bot Token"
|
||||
},
|
||||
"enable": {
|
||||
"description": "启用",
|
||||
"hint": "是否启用该适配器。未启用的适配器对应的消息平台将不会接收到消息。"
|
||||
},
|
||||
"enable_group_c2c": {
|
||||
"description": "启用消息列表单聊",
|
||||
"hint": "启用后,机器人可以接收到 QQ 消息列表中的私聊消息。你可能需要在 QQ 机器人平台上通过扫描二维码的方式添加机器人为你的好友。详见文档。"
|
||||
},
|
||||
"enable_guild_direct_message": {
|
||||
"description": "启用频道私聊",
|
||||
"hint": "启用后,机器人可以接收到频道的私聊消息。"
|
||||
},
|
||||
"id": {
|
||||
"description": "机器人名称",
|
||||
"hint": "机器人名称"
|
||||
},
|
||||
"is_sandbox": {
|
||||
"description": "沙箱模式"
|
||||
},
|
||||
"kf_name": {
|
||||
"description": "微信客服账号名",
|
||||
"hint": "可选。微信客服账号名(不是 ID)。可在 https://kf.weixin.qq.com/kf/frame#/accounts 获取"
|
||||
},
|
||||
"lark_bot_name": {
|
||||
"description": "飞书机器人的名字",
|
||||
"hint": "请务必填写正确,否则 @ 机器人将无法唤醒,只能通过前缀唤醒。"
|
||||
},
|
||||
"lark_connection_mode": {
|
||||
"description": "订阅方式",
|
||||
"labels": [
|
||||
"长连接模式",
|
||||
"推送至服务器模式"
|
||||
]
|
||||
},
|
||||
"lark_encrypt_key": {
|
||||
"description": "Encrypt Key",
|
||||
"hint": "用于解密飞书回调数据的加密密钥"
|
||||
},
|
||||
"lark_verification_token": {
|
||||
"description": "Verification Token",
|
||||
"hint": "用于验证飞书回调请求的令牌"
|
||||
},
|
||||
"misskey_allow_insecure_downloads": {
|
||||
"description": "允许不安全下载(禁用 SSL 验证)",
|
||||
"hint": "当远端服务器存在证书问题导致无法正常下载时,自动禁用 SSL 验证作为回退方案。适用于某些图床的证书配置问题。启用有安全风险,仅在必要时使用。"
|
||||
},
|
||||
"misskey_default_visibility": {
|
||||
"description": "默认帖子可见性",
|
||||
"hint": "机器人发帖时的默认可见性设置。public:公开,home:主页时间线,followers:仅关注者。"
|
||||
},
|
||||
"misskey_download_chunk_size": {
|
||||
"description": "流式下载分块大小(字节)",
|
||||
"hint": "流式下载和计算 MD5 时使用的每次读取字节数,过小会增加开销,过大会占用内存。"
|
||||
},
|
||||
"misskey_download_timeout": {
|
||||
"description": "远端下载超时时间(秒)",
|
||||
"hint": "下载远程文件时的超时时间(秒),用于异步上传回退到本地上传的场景。"
|
||||
},
|
||||
"misskey_enable_chat": {
|
||||
"description": "启用聊天消息响应",
|
||||
"hint": "启用后,机器人将会监听和响应私信聊天消息"
|
||||
},
|
||||
"misskey_enable_file_upload": {
|
||||
"description": "启用文件上传到 Misskey",
|
||||
"hint": "启用后,适配器会尝试将消息链中的文件上传到 Misskey。URL 文件会先尝试服务器端上传,异步上传失败时会回退到下载后本地上传。"
|
||||
},
|
||||
"misskey_instance_url": {
|
||||
"description": "Misskey 实例 URL",
|
||||
"hint": "例如 https://misskey.example,填写 Bot 账号所在的 Misskey 实例地址"
|
||||
},
|
||||
"misskey_local_only": {
|
||||
"description": "仅限本站(不参与联合)",
|
||||
"hint": "启用后,机器人发出的帖子将仅在本实例可见,不会联合到其他实例"
|
||||
},
|
||||
"misskey_max_download_bytes": {
|
||||
"description": "最大允许下载字节数(超出则中止)",
|
||||
"hint": "如果希望限制下载文件的最大大小以防止 OOM,请填写最大字节数;留空或 null 表示不限制。"
|
||||
},
|
||||
"misskey_token": {
|
||||
"description": "Misskey Access Token",
|
||||
"hint": "连接服务设置生成的 API 鉴权访问令牌(Access token)"
|
||||
},
|
||||
"misskey_upload_concurrency": {
|
||||
"description": "并发上传限制",
|
||||
"hint": "同时进行的文件上传任务上限(整数,默认 3)。"
|
||||
},
|
||||
"misskey_upload_folder": {
|
||||
"description": "上传到网盘的目标文件夹 ID",
|
||||
"hint": "可选:填写 Misskey 网盘中目标文件夹的 ID,上传的文件将放置到该文件夹内。留空则使用账号网盘根目录。"
|
||||
},
|
||||
"port": {
|
||||
"description": "回调服务器端口",
|
||||
"hint": "回调服务器端口。留空则不启用回调服务器。"
|
||||
},
|
||||
"satori_api_base_url": {
|
||||
"description": "Satori API 终结点",
|
||||
"hint": "Satori API 的基础地址。"
|
||||
},
|
||||
"satori_auto_reconnect": {
|
||||
"description": "启用自动重连",
|
||||
"hint": "断开连接时是否自动重新连接 WebSocket。"
|
||||
},
|
||||
"satori_endpoint": {
|
||||
"description": "Satori WebSocket 终结点",
|
||||
"hint": "Satori 事件的 WebSocket 端点。"
|
||||
},
|
||||
"satori_heartbeat_interval": {
|
||||
"description": "Satori 心跳间隔",
|
||||
"hint": "发送心跳消息的间隔(秒)。"
|
||||
},
|
||||
"satori_reconnect_delay": {
|
||||
"description": "Satori 重连延迟",
|
||||
"hint": "尝试重新连接前的延迟时间(秒)。"
|
||||
},
|
||||
"satori_token": {
|
||||
"description": "Satori 令牌",
|
||||
"hint": "用于 Satori API 身份验证的令牌。"
|
||||
},
|
||||
"secret": {
|
||||
"description": "secret",
|
||||
"hint": "必填项。"
|
||||
},
|
||||
"slack_connection_mode": {
|
||||
"description": "Slack Connection Mode",
|
||||
"hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode."
|
||||
},
|
||||
"slack_webhook_host": {
|
||||
"description": "Slack Webhook Host",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"slack_webhook_path": {
|
||||
"description": "Slack Webhook Path",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"slack_webhook_port": {
|
||||
"description": "Slack Webhook Port",
|
||||
"hint": "Only valid when Slack connection mode is `webhook`."
|
||||
},
|
||||
"telegram_command_auto_refresh": {
|
||||
"description": "Telegram 命令自动刷新",
|
||||
"hint": "启用后,AstrBot 将会在运行时自动刷新 Telegram 命令。(单独设置此项无效)"
|
||||
},
|
||||
"telegram_command_register": {
|
||||
"description": "Telegram 命令注册",
|
||||
"hint": "启用后,AstrBot 将会自动注册 Telegram 命令。"
|
||||
},
|
||||
"telegram_command_register_interval": {
|
||||
"description": "Telegram 命令自动刷新间隔",
|
||||
"hint": "Telegram 命令自动刷新间隔,单位为秒。"
|
||||
},
|
||||
"telegram_token": {
|
||||
"description": "Bot Token",
|
||||
"hint": "如果你的网络环境为中国大陆,请在 `其他配置` 处设置代理或更改 api_base。"
|
||||
},
|
||||
"type": {
|
||||
"description": "适配器类型"
|
||||
},
|
||||
"unified_webhook_mode": {
|
||||
"description": "统一 Webhook 模式",
|
||||
"hint": "启用后,将使用 AstrBot 统一 Webhook 入口,无需单独开启端口。回调地址为 /api/platform/webhook/{webhook_uuid}。"
|
||||
},
|
||||
"webhook_uuid": {
|
||||
"description": "Webhook UUID",
|
||||
"hint": "统一 Webhook 模式下的唯一标识符,创建平台时自动生成。"
|
||||
},
|
||||
"wecom_ai_bot_name": {
|
||||
"description": "企业微信智能机器人的名字",
|
||||
"hint": "请务必填写正确,否则无法使用一些指令。"
|
||||
},
|
||||
"wecomaibot_friend_message_welcome_text": {
|
||||
"description": "企业微信智能机器人私聊欢迎语",
|
||||
"hint": "当用户当天进入智能机器人单聊会话,回复欢迎语,留空则不回复。"
|
||||
},
|
||||
"wecomaibot_init_respond_text": {
|
||||
"description": "企业微信智能机器人初始响应文本",
|
||||
"hint": "当机器人收到消息时,首先回复的文本内容。留空则使用默认值。"
|
||||
},
|
||||
"wpp_active_message_poll": {
|
||||
"description": "是否启用主动消息轮询",
|
||||
"hint": "只有当你发现微信消息没有按时同步到 AstrBot 时,才需要启用这个功能,默认不启用。"
|
||||
},
|
||||
"wpp_active_message_poll_interval": {
|
||||
"description": "主动消息轮询间隔",
|
||||
"hint": "主动消息轮询间隔,单位为秒,默认 3 秒,最大不要超过 60 秒,否则可能被认为是旧消息。"
|
||||
},
|
||||
"ws_reverse_host": {
|
||||
"description": "反向 Websocket 主机",
|
||||
"hint": "AstrBot 将作为服务器端。"
|
||||
},
|
||||
"ws_reverse_port": {
|
||||
"description": "反向 Websocket 端口"
|
||||
},
|
||||
"ws_reverse_token": {
|
||||
"description": "反向 Websocket Token",
|
||||
"hint": "反向 Websocket Token。未设置则不启用 Token 验证。"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"description": "基本",
|
||||
"admins_id": {
|
||||
@@ -620,6 +851,443 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"provider_group": {
|
||||
"provider": {
|
||||
"genie_onnx_model_dir": {
|
||||
"description": "ONNX Model Directory",
|
||||
"hint": "The directory path containing the ONNX model files"
|
||||
},
|
||||
"genie_language": {
|
||||
"description": "Language"
|
||||
},
|
||||
"xai_native_search": {
|
||||
"description": "启用原生搜索功能",
|
||||
"hint": "启用后,将通过 xAI 的 Chat Completions 原生 Live Search 进行联网检索(按需计费)。仅对 xAI 提供商生效。"
|
||||
},
|
||||
"rerank_api_base": {
|
||||
"description": "重排序模型 API Base URL",
|
||||
"hint": "AstrBot 会在请求时在末尾加上 /v1/rerank。"
|
||||
},
|
||||
"rerank_api_key": {
|
||||
"description": "API Key",
|
||||
"hint": "如果不需要 API Key, 请留空。"
|
||||
},
|
||||
"rerank_model": {
|
||||
"description": "重排序模型名称"
|
||||
},
|
||||
"return_documents": {
|
||||
"description": "是否在排序结果中返回文档原文",
|
||||
"hint": "默认值false,以减少网络传输开销。"
|
||||
},
|
||||
"instruct": {
|
||||
"description": "自定义排序任务类型说明",
|
||||
"hint": "仅在使用 qwen3-rerank 模型时生效。建议使用英文撰写。"
|
||||
},
|
||||
"launch_model_if_not_running": {
|
||||
"description": "模型未运行时自动启动",
|
||||
"hint": "如果模型当前未在 Xinference 服务中运行,是否尝试自动启动它。在生产环境中建议关闭。"
|
||||
},
|
||||
"modalities": {
|
||||
"description": "模型能力",
|
||||
"hint": "模型支持的模态。如所填写的模型不支持图像,请取消勾选图像。",
|
||||
"labels": [
|
||||
"文本",
|
||||
"图像",
|
||||
"工具使用"
|
||||
]
|
||||
},
|
||||
"custom_headers": {
|
||||
"description": "自定义添加请求头",
|
||||
"hint": "此处添加的键值对将被合并到 OpenAI SDK 的 default_headers 中,用于自定义 HTTP 请求头。值必须为字符串。"
|
||||
},
|
||||
"custom_extra_body": {
|
||||
"description": "自定义请求体参数",
|
||||
"hint": "用于在请求时添加额外的参数,如 temperature、top_p、max_tokens 等。",
|
||||
"template_schema": {
|
||||
"temperature": {
|
||||
"description": "温度参数",
|
||||
"hint": "控制输出的随机性,范围通常为 0-2。值越高越随机。",
|
||||
"name": "Temperature"
|
||||
},
|
||||
"top_p": {
|
||||
"description": "Top-p 采样",
|
||||
"hint": "核采样参数,范围通常为 0-1。控制模型考虑的概率质量。",
|
||||
"name": "Top-p"
|
||||
},
|
||||
"max_tokens": {
|
||||
"description": "最大令牌数",
|
||||
"hint": "生成的最大令牌数。",
|
||||
"name": "Max Tokens"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gpt_weights_path": {
|
||||
"description": "GPT模型文件路径",
|
||||
"hint": "即“.ckpt”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)"
|
||||
},
|
||||
"sovits_weights_path": {
|
||||
"description": "SoVITS模型文件路径",
|
||||
"hint": "即“.pth”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)"
|
||||
},
|
||||
"gsv_default_parms": {
|
||||
"description": "GPT_SoVITS默认参数",
|
||||
"hint": "参考音频文件路径、参考音频文本必填,其他参数根据个人爱好自行填写",
|
||||
"gsv_ref_audio_path": {
|
||||
"description": "参考音频文件路径",
|
||||
"hint": "必填!请使用绝对路径!路径两端不要带双引号!"
|
||||
},
|
||||
"gsv_prompt_text": {
|
||||
"description": "参考音频文本",
|
||||
"hint": "必填!请填写参考音频讲述的文本"
|
||||
},
|
||||
"gsv_prompt_lang": {
|
||||
"description": "参考音频文本语言",
|
||||
"hint": "请填写参考音频讲述的文本的语言,默认为中文"
|
||||
},
|
||||
"gsv_aux_ref_audio_paths": {
|
||||
"description": "辅助参考音频文件路径",
|
||||
"hint": "辅助参考音频文件,可不填"
|
||||
},
|
||||
"gsv_text_lang": {
|
||||
"description": "文本语言",
|
||||
"hint": "默认为中文"
|
||||
},
|
||||
"gsv_top_k": {
|
||||
"description": "生成语音的多样性",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_top_p": {
|
||||
"description": "核采样的阈值",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_temperature": {
|
||||
"description": "生成语音的随机性",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_text_split_method": {
|
||||
"description": "切分文本的方法",
|
||||
"hint": "可选值: `cut0`:不切分 `cut1`:四句一切 `cut2`:50字一切 `cut3`:按中文句号切 `cut4`:按英文句号切 `cut5`:按标点符号切"
|
||||
},
|
||||
"gsv_batch_size": {
|
||||
"description": "批处理大小",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_batch_threshold": {
|
||||
"description": "批处理阈值",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_split_bucket": {
|
||||
"description": "将文本分割成桶以便并行处理",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_speed_factor": {
|
||||
"description": "语音播放速度",
|
||||
"hint": "1为原始语速"
|
||||
},
|
||||
"gsv_fragment_interval": {
|
||||
"description": "语音片段之间的间隔时间",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_streaming_mode": {
|
||||
"description": "启用流模式",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_seed": {
|
||||
"description": "随机种子",
|
||||
"hint": "用于结果的可重复性"
|
||||
},
|
||||
"gsv_parallel_infer": {
|
||||
"description": "并行执行推理",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_repetition_penalty": {
|
||||
"description": "重复惩罚因子",
|
||||
"hint": ""
|
||||
},
|
||||
"gsv_media_type": {
|
||||
"description": "输出媒体的类型",
|
||||
"hint": "建议用wav"
|
||||
}
|
||||
},
|
||||
"embedding_dimensions": {
|
||||
"description": "嵌入维度",
|
||||
"hint": "嵌入向量的维度。根据模型不同,可能需要调整,请参考具体模型的文档。此配置项请务必填写正确,否则将导致向量数据库无法正常工作。"
|
||||
},
|
||||
"embedding_model": {
|
||||
"description": "嵌入模型",
|
||||
"hint": "嵌入模型名称。"
|
||||
},
|
||||
"embedding_api_key": {
|
||||
"description": "API Key"
|
||||
},
|
||||
"embedding_api_base": {
|
||||
"description": "API Base URL"
|
||||
},
|
||||
"volcengine_cluster": {
|
||||
"description": "火山引擎集群",
|
||||
"hint": "若使用语音复刻大模型,可选volcano_icl或volcano_icl_concurr,默认使用volcano_tts"
|
||||
},
|
||||
"volcengine_voice_type": {
|
||||
"description": "火山引擎音色",
|
||||
"hint": "输入声音id(Voice_type)"
|
||||
},
|
||||
"volcengine_speed_ratio": {
|
||||
"description": "语速设置",
|
||||
"hint": "语速设置,范围为 0.2 到 3.0,默认值为 1.0"
|
||||
},
|
||||
"volcengine_volume_ratio": {
|
||||
"description": "音量设置",
|
||||
"hint": "音量设置,范围为 0.0 到 2.0,默认值为 1.0"
|
||||
},
|
||||
"azure_tts_voice": {
|
||||
"description": "音色设置",
|
||||
"hint": "API 音色"
|
||||
},
|
||||
"azure_tts_style": {
|
||||
"description": "风格设置",
|
||||
"hint": "声音特定的讲话风格。 可以表达快乐、同情和平静等情绪。"
|
||||
},
|
||||
"azure_tts_role": {
|
||||
"description": "模仿设置(可选)",
|
||||
"hint": "讲话角色扮演。 声音可以模仿不同的年龄和性别,但声音名称不会更改。 例如,男性语音可以提高音调和改变语调来模拟女性语音,但语音名称不会更改。 如果角色缺失或不受声音的支持,则会忽略此属性。"
|
||||
},
|
||||
"azure_tts_rate": {
|
||||
"description": "语速设置",
|
||||
"hint": "指示文本的讲出速率。可在字词或句子层面应用语速。 速率变化应为原始音频的 0.5 到 2 倍。"
|
||||
},
|
||||
"azure_tts_volume": {
|
||||
"description": "语音音量设置",
|
||||
"hint": "指示语音的音量级别。 可在句子层面应用音量的变化。以从 0.0 到 100.0(从最安静到最大声,例如 75)的数字表示。 默认值为 100.0。"
|
||||
},
|
||||
"azure_tts_region": {
|
||||
"description": "API 地区",
|
||||
"hint": "Azure_TTS 处理数据所在区域,具体参考 https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions"
|
||||
},
|
||||
"azure_tts_subscription_key": {
|
||||
"description": "服务订阅密钥",
|
||||
"hint": "Azure_TTS 服务的订阅密钥(注意不是令牌)"
|
||||
},
|
||||
"dashscope_tts_voice": {
|
||||
"description": "音色"
|
||||
},
|
||||
"gm_resp_image_modal": {
|
||||
"description": "启用图片模态",
|
||||
"hint": "启用后,将支持返回图片内容。需要模型支持,否则会报错。具体支持模型请查看 Google Gemini 官方网站。温馨提示,如果您需要生成图片,请关闭 `启用群员识别` 配置获得更好的效果。"
|
||||
},
|
||||
"gm_native_search": {
|
||||
"description": "启用原生搜索功能",
|
||||
"hint": "启用后所有函数工具将全部失效,免费次数限制请查阅官方文档"
|
||||
},
|
||||
"gm_native_coderunner": {
|
||||
"description": "启用原生代码执行器",
|
||||
"hint": "启用后所有函数工具将全部失效"
|
||||
},
|
||||
"gm_url_context": {
|
||||
"description": "启用URL上下文功能",
|
||||
"hint": "启用后所有函数工具将全部失效"
|
||||
},
|
||||
"gm_safety_settings": {
|
||||
"description": "安全过滤器",
|
||||
"hint": "设置模型输入的内容安全过滤级别。过滤级别分类为NONE(不屏蔽)、HIGH(高风险时屏蔽)、MEDIUM_AND_ABOVE(中等风险及以上屏蔽)、LOW_AND_ABOVE(低风险及以上时屏蔽),具体参见Gemini API文档。",
|
||||
"harassment": {
|
||||
"description": "骚扰内容",
|
||||
"hint": "负面或有害评论"
|
||||
},
|
||||
"hate_speech": {
|
||||
"description": "仇恨言论",
|
||||
"hint": "粗鲁、无礼或亵渎性质内容"
|
||||
},
|
||||
"sexually_explicit": {
|
||||
"description": "露骨色情内容",
|
||||
"hint": "包含性行为或其他淫秽内容的引用"
|
||||
},
|
||||
"dangerous_content": {
|
||||
"description": "危险内容",
|
||||
"hint": "宣扬、助长或鼓励有害行为的信息"
|
||||
}
|
||||
},
|
||||
"gm_thinking_config": {
|
||||
"description": "思考配置",
|
||||
"budget": {
|
||||
"description": "思考预算",
|
||||
"hint": "用于指定模型推理时使用的思考 token 数量上限。参见: https://ai.google.dev/gemini-api/docs/thinking#set-budget"
|
||||
},
|
||||
"level": {
|
||||
"description": "思考级别",
|
||||
"hint": "推荐用于 Gemini 3 及以上模型,可控制推理行为。参见: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels"
|
||||
}
|
||||
},
|
||||
"anth_thinking_config": {
|
||||
"description": "思考配置",
|
||||
"budget": {
|
||||
"description": "思考预算",
|
||||
"hint": "Anthropic thinking.budget_tokens 参数。必须 >= 1024。参见: https://platform.claude.com/docs/en/build-with-claude/extended-thinking"
|
||||
}
|
||||
},
|
||||
"minimax-group-id": {
|
||||
"description": "用户组",
|
||||
"hint": "于账户管理->基本信息中可见"
|
||||
},
|
||||
"minimax-langboost": {
|
||||
"description": "指定语言/方言",
|
||||
"hint": "增强对指定的小语种和方言的识别能力,设置后可以提升在指定小语种/方言场景下的语音表现"
|
||||
},
|
||||
"minimax-voice-speed": {
|
||||
"description": "语速",
|
||||
"hint": "生成声音的语速, 取值[0.5, 2], 默认为1.0, 取值越大,语速越快"
|
||||
},
|
||||
"minimax-voice-vol": {
|
||||
"description": "音量",
|
||||
"hint": "生成声音的音量, 取值(0, 10], 默认为1.0, 取值越大,音量越高"
|
||||
},
|
||||
"minimax-voice-pitch": {
|
||||
"description": "语调",
|
||||
"hint": "生成声音的语调, 取值[-12, 12], 默认为0"
|
||||
},
|
||||
"minimax-is-timber-weight": {
|
||||
"description": "启用混合音色",
|
||||
"hint": "启用混合音色, 支持以自定义权重混合最多四种音色, 启用后自动忽略单一音色设置"
|
||||
},
|
||||
"minimax-timber-weight": {
|
||||
"description": "混合音色",
|
||||
"hint": "混合音色及其权重, 最多支持四种音色, 权重为整数, 取值[1, 100]. 可在官网API语音调试台预览代码获得预设以及编写模板, 需要严格按照json字符串格式编写, 可以查看控制台判断是否解析成功. 具体结构可参照默认值以及官网代码预览."
|
||||
},
|
||||
"minimax-voice-id": {
|
||||
"description": "单一音色",
|
||||
"hint": "单一音色编号, 详见官网文档"
|
||||
},
|
||||
"minimax-voice-emotion": {
|
||||
"description": "情绪",
|
||||
"hint": "控制合成语音的情绪。当为 auto 时,将根据文本内容自动选择情绪。"
|
||||
},
|
||||
"minimax-voice-latex": {
|
||||
"description": "支持朗读latex公式",
|
||||
"hint": "朗读latex公式, 但是需要确保输入文本按官网要求格式化"
|
||||
},
|
||||
"minimax-voice-english-normalization": {
|
||||
"description": "支持英语文本规范化",
|
||||
"hint": "可提升数字阅读场景的性能,但会略微增加延迟"
|
||||
},
|
||||
"rag_options": {
|
||||
"description": "RAG 选项",
|
||||
"hint": "检索知识库设置, 非必填。仅 Agent 应用类型支持(智能体应用, 包括 RAG 应用)。阿里云百炼应用开启此功能后将无法多轮对话。",
|
||||
"pipeline_ids": {
|
||||
"description": "知识库 ID 列表",
|
||||
"hint": "对指定知识库内所有文档进行检索, 前往 https://bailian.console.aliyun.com/ 数据应用->知识索引创建和获取 ID。"
|
||||
},
|
||||
"file_ids": {
|
||||
"description": "非结构化文档 ID, 传入该参数将对指定非结构化文档进行检索。",
|
||||
"hint": "对指定非结构化文档进行检索。前往 https://bailian.console.aliyun.com/ 数据管理创建和获取 ID。"
|
||||
},
|
||||
"output_reference": {
|
||||
"description": "是否输出知识库/文档的引用",
|
||||
"hint": "在每次回答尾部加上引用源。默认为 False。"
|
||||
}
|
||||
},
|
||||
"sensevoice_hint": {
|
||||
"description": "部署SenseVoice",
|
||||
"hint": "启用前请 pip 安装 funasr、funasr_onnx、torchaudio、torch、modelscope、jieba 库(默认使用CPU,大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。"
|
||||
},
|
||||
"is_emotion": {
|
||||
"description": "情绪识别",
|
||||
"hint": "是否开启情绪识别。happy|sad|angry|neutral|fearful|disgusted|surprised|unknown"
|
||||
},
|
||||
"stt_model": {
|
||||
"description": "模型名称",
|
||||
"hint": "modelscope 上的模型名称。默认:iic/SenseVoiceSmall。"
|
||||
},
|
||||
"variables": {
|
||||
"description": "工作流固定输入变量",
|
||||
"hint": "可选。工作流固定输入变量,将会作为工作流的输入。也可以在对话时使用 /set 指令动态设置变量。如果变量名冲突,优先使用动态设置的变量。"
|
||||
},
|
||||
"dashscope_app_type": {
|
||||
"description": "应用类型",
|
||||
"hint": "百炼应用的应用类型。"
|
||||
},
|
||||
"timeout": {
|
||||
"description": "超时时间",
|
||||
"hint": "超时时间,单位为秒。"
|
||||
},
|
||||
"openai-tts-voice": {
|
||||
"description": "voice",
|
||||
"hint": "OpenAI TTS 的声音。OpenAI 默认支持:'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'"
|
||||
},
|
||||
"fishaudio-tts-character": {
|
||||
"description": "character",
|
||||
"hint": "fishaudio TTS 的角色。默认为可莉。更多角色请访问:https://fish.audio/zh-CN/discovery"
|
||||
},
|
||||
"fishaudio-tts-reference-id": {
|
||||
"description": "reference_id",
|
||||
"hint": "fishaudio TTS 的参考模型ID(可选)。如果填入此字段,将直接使用模型ID而不通过角色名称查询。例如:626bb6d3f3364c9cbc3aa6a67300a664。更多模型请访问:https://fish.audio/zh-CN/discovery,进入模型详情界面后可复制模型ID"
|
||||
},
|
||||
"whisper_hint": {
|
||||
"description": "本地部署 Whisper 模型须知",
|
||||
"hint": "启用前请 pip 安装 openai-whisper 库(N卡用户大约下载 2GB,主要是 torch 和 cuda,CPU 用户大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。"
|
||||
},
|
||||
"id": {
|
||||
"description": "ID"
|
||||
},
|
||||
"type": {
|
||||
"description": "模型提供商种类"
|
||||
},
|
||||
"provider_type": {
|
||||
"description": "模型提供商能力种类"
|
||||
},
|
||||
"enable": {
|
||||
"description": "启用"
|
||||
},
|
||||
"key": {
|
||||
"description": "API Key"
|
||||
},
|
||||
"api_base": {
|
||||
"description": "API Base URL"
|
||||
},
|
||||
"model": {
|
||||
"description": "模型 ID",
|
||||
"hint": "模型名称,如 gpt-4o-mini, deepseek-chat。"
|
||||
},
|
||||
"max_context_tokens": {
|
||||
"description": "模型上下文窗口大小",
|
||||
"hint": "模型最大上下文 Token 大小。如果为 0,则会自动从模型元数据填充(如有),也可手动修改。"
|
||||
},
|
||||
"dify_api_key": {
|
||||
"description": "API Key",
|
||||
"hint": "Dify API Key。此项必填。"
|
||||
},
|
||||
"dify_api_base": {
|
||||
"description": "API Base URL",
|
||||
"hint": "Dify API Base URL。默认为 https://api.dify.ai/v1"
|
||||
},
|
||||
"dify_api_type": {
|
||||
"description": "Dify 应用类型",
|
||||
"hint": "Dify API 类型。根据 Dify 官网,目前支持 chat, chatflow, agent, workflow 三种应用类型。"
|
||||
},
|
||||
"dify_workflow_output_key": {
|
||||
"description": "Dify Workflow 输出变量名",
|
||||
"hint": "Dify Workflow 输出变量名。当应用类型为 workflow 时才使用。默认为 astrbot_wf_output。"
|
||||
},
|
||||
"dify_query_input_key": {
|
||||
"description": "Prompt 输入变量名",
|
||||
"hint": "发送的消息文本内容对应的输入变量名。默认为 astrbot_text_query。"
|
||||
},
|
||||
"coze_api_key": {
|
||||
"description": "Coze API Key",
|
||||
"hint": "Coze API 密钥,用于访问 Coze 服务。"
|
||||
},
|
||||
"bot_id": {
|
||||
"description": "Bot ID",
|
||||
"hint": "Coze 机器人的 ID,在 Coze 平台上创建机器人后获得。"
|
||||
},
|
||||
"coze_api_base": {
|
||||
"description": "API Base URL",
|
||||
"hint": "Coze API 的基础 URL 地址,默认为 https://api.coze.cn"
|
||||
},
|
||||
"auto_save_history": {
|
||||
"description": "由 Coze 管理对话记录",
|
||||
"hint": "启用后,将由 Coze 进行对话历史记录管理, 此时 AstrBot 本地保存的上下文不会生效(仅供浏览), 对 AstrBot 的上下文进行的操作也不会生效。如果为禁用, 则使用 AstrBot 管理上下文。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"documentation": "官方文档",
|
||||
"support": "加群询问",
|
||||
|
||||
@@ -45,12 +45,67 @@
|
||||
},
|
||||
"invalidPlatformId": "平台 ID 不能包含 ':' 或 '!'。"
|
||||
},
|
||||
"createDialog": {
|
||||
"step1Title": "选择消息平台类别",
|
||||
"step1Hint": "想把机器人接入到哪里?如 QQ、企业微信、飞书、Discord、Telegram 等。",
|
||||
"platformTypeLabel": "消息平台类别",
|
||||
"configFileTitle": "配置文件",
|
||||
"optional": "可选",
|
||||
"configHint": "想如何配置机器人?配置文件包含了聊天模型、人格、知识库、插件范围等丰富的机器人配置项。",
|
||||
"configDefaultHint": "默认使用默认配置文件 “default”。您也可以稍后配置。",
|
||||
"useExistingConfig": "使用现有配置文件",
|
||||
"selectConfigLabel": "选择配置文件",
|
||||
"createNewConfig": "创建新配置文件",
|
||||
"newConfigNameLabel": "新配置文件名称",
|
||||
"newConfigTitle": "使用新的配置文件",
|
||||
"newConfigLoadFailed": "无法加载默认配置模板",
|
||||
"addRouteRule": "添加路由规则",
|
||||
"viewMode": "查看",
|
||||
"editMode": "编辑",
|
||||
"noRouteRules": "该平台暂无路由规则,将使用默认配置文件",
|
||||
"sessionIdPlaceholder": "会话ID或*",
|
||||
"allSessions": "全部会话",
|
||||
"configMissing": "配置文件不存在",
|
||||
"routeHint": "*消息下发时,根据会话来源按顺序从上到下匹配首个符合条件的配置文件。使用 * 表示匹配所有。使用 /sid 指令获取会话 ID。全部不匹配时将使用默认配置文件。",
|
||||
"warningContinue": "无视警告并继续创建",
|
||||
"warningEditAgain": "重新修改",
|
||||
"configDrawerTitle": "配置文件管理",
|
||||
"configDrawerIdLabel": "ID",
|
||||
"configTableHeaders": {
|
||||
"configId": "与此实例关联的配置文件 ID",
|
||||
"scope": "在此实例下的应用范围"
|
||||
},
|
||||
"routeTableHeaders": {
|
||||
"source": "消息会话来源(消息类型:会话 ID)",
|
||||
"config": "使用配置文件",
|
||||
"actions": "操作"
|
||||
},
|
||||
"messageTypeOptions": {
|
||||
"all": "全部消息",
|
||||
"group": "群组消息(GroupMessage)",
|
||||
"friend": "私聊消息(FriendMessage)"
|
||||
},
|
||||
"messageTypeLabels": {
|
||||
"all": "全部消息",
|
||||
"group": "群组消息",
|
||||
"friend": "私聊消息"
|
||||
}
|
||||
},
|
||||
"messages": {
|
||||
"updateSuccess": "更新成功!",
|
||||
"addSuccess": "添加成功!",
|
||||
"deleteSuccess": "删除成功!",
|
||||
"statusUpdateSuccess": "状态更新成功!",
|
||||
"deleteConfirm": "确定要删除平台适配器"
|
||||
"deleteConfirm": "确定要删除平台适配器",
|
||||
"configNotFoundOpenConfig": "目标配置文件不存在,已打开配置页面以便检查。",
|
||||
"updateMissingPlatformId": "更新失败,缺少平台 ID。",
|
||||
"platformUpdateFailed": "平台更新失败。",
|
||||
"addSuccessWithConfig": "平台添加成功,配置文件已更新",
|
||||
"configIdMissing": "无法获取配置文件ID。",
|
||||
"routingUpdateFailed": "更新路由表失败: {message}",
|
||||
"createConfigFailed": "创建新配置文件失败: {message}",
|
||||
"platformIdMissing": "无法获取平台 ID。",
|
||||
"routingSaveFailed": "保存路由表失败: {message}"
|
||||
},
|
||||
"status": {
|
||||
"enabled": "已启用",
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
},
|
||||
"providerSources": {
|
||||
"title": "提供商源",
|
||||
"add": "新增",
|
||||
"empty": "暂无提供商源",
|
||||
"selectHint": "请选择一个提供商源",
|
||||
"save": "保存配置",
|
||||
@@ -142,4 +143,4 @@
|
||||
"modelId": "模型 ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ export function getPlatformIcon(name) {
|
||||
return new URL('@/assets/images/platform_logos/qq.png', import.meta.url).href
|
||||
} else if (name === 'wecom' || name === 'wecom_ai_bot') {
|
||||
return new URL('@/assets/images/platform_logos/wecom.png', import.meta.url).href
|
||||
} else if (name === 'weixin_official_account') {
|
||||
return new URL('@/assets/images/platform_logos/wechat.png', import.meta.url).href
|
||||
} else if (name === 'lark') {
|
||||
return new URL('@/assets/images/platform_logos/lark.png', import.meta.url).href
|
||||
} else if (name === 'dingtalk') {
|
||||
|
||||
Reference in New Issue
Block a user