mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/1Panel-dev/1Panel.git
synced 2026-09-20 08:03:55 +08:00
feat: QwenPaw support config username/password (#13478)
This commit is contained in:
@@ -969,9 +969,9 @@ export namespace AI {
|
||||
|
||||
export interface AgentOtherConfigUpdateReq {
|
||||
agentId: number;
|
||||
userTimezone: string;
|
||||
userTimezone?: string;
|
||||
browserEnabled: boolean;
|
||||
npmRegistry: string;
|
||||
npmRegistry?: string;
|
||||
dashboardUsername?: string;
|
||||
dashboardPassword?: string;
|
||||
}
|
||||
|
||||
@@ -922,6 +922,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'Saving will automatically restart the container so the changes take effect.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Saving the username or password will automatically rebuild the container so the changes take effect.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Saving updates the QwenPaw login credentials immediately without restarting the container.',
|
||||
channelDeleteConfirm: 'Delete the {0} channel configuration?',
|
||||
apiTypeBaseURLHelper: 'This type sends requests to {0}. Recommended Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -925,6 +925,8 @@ const message = {
|
||||
'Al guardar, el contenedor se reiniciará automáticamente para que la configuración surta efecto.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Al guardar el usuario o la contraseña, el contenedor se reconstruirá automáticamente para que los cambios surtan efecto.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Al guardar, las credenciales de QwenPaw se actualizan de inmediato sin reiniciar el contenedor.',
|
||||
channelDeleteConfirm: '¿Eliminar la configuración del canal {0}?',
|
||||
apiTypeBaseURLHelper: 'Este tipo envía solicitudes a {0}. Base URL recomendada: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -910,6 +910,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'ذخیره به طور خودکار کانتینر را مجدداً راهاندازی میکند تا تغییرات اعمال شوند.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ذخیره نام کاربری یا رمز عبور، کانتینر را بهطور خودکار بازسازی میکند تا تغییرات اعمال شوند.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'با ذخیرهسازی، اطلاعات ورود QwenPaw بدون راهاندازی مجدد کانتینر فوراً بهروزرسانی میشود.',
|
||||
channelDeleteConfirm: 'پیکربندی کانال {0} حذف شود؟',
|
||||
apiTypeBaseURLHelper: 'این نوع درخواستها را به {0} ارسال میکند. Base URL پیشنهادی: {1}',
|
||||
apiTypeBaseURLMismatch: 'Base URL فعلی شبیه مسیر {0} است، اما {1} انتخاب شده است. URL پیشنهادی: {2}',
|
||||
|
||||
@@ -914,6 +914,8 @@ const message = {
|
||||
channelAutoRestartHelper: '保存後、設定を反映するためにコンテナが自動で再起動されます。',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ユーザー名またはパスワードを保存すると、変更を反映するためにコンテナが自動で再作成されます。',
|
||||
dashboardAuthImmediateHelper:
|
||||
'保存すると QwenPaw のログイン認証情報がすぐに更新され、コンテナの再起動は不要です。',
|
||||
channelDeleteConfirm: '{0} チャンネルの設定を削除しますか?',
|
||||
apiTypeBaseURLHelper: 'このタイプは最終的に {0} にリクエストします。推奨 Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -904,6 +904,8 @@ const message = {
|
||||
channelAutoRestartHelper: '저장하면 설정 적용을 위해 컨테이너가 자동으로 재시작됩니다.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'사용자 이름 또는 비밀번호를 저장하면 변경 사항 적용을 위해 컨테이너가 자동으로 재생성됩니다.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'저장하면 컨테이너를 다시 시작하지 않고 QwenPaw 로그인 자격 증명이 즉시 업데이트됩니다.',
|
||||
channelDeleteConfirm: '{0} 채널 구성을 삭제하시겠습니까?',
|
||||
apiTypeBaseURLHelper: '이 유형은 최종적으로 {0}에 요청합니다. 권장 Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -904,6 +904,8 @@ const message = {
|
||||
channelAutoRestartHelper: 'ການບັນທຶກຈະຣີສະຕາດຄອນເທນເນີອັດຕະໂນມັດເພື່ອໃຫ້ການປ່ຽນແປງມີຜົນ.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'ການບັນທຶກຊື່ຜູ້ໃຊ້ ຫຼື ລະຫັດຜ່ານ Dashboard ຈະສ້າງຄອນເທນເນີໃໝ່ອັດຕະໂນມັດເພື່ອໃຫ້ການປ່ຽນແປງມີຜົນ.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'ເມື່ອບັນທຶກ ຂໍ້ມູນເຂົ້າລະບົບ QwenPaw ຈະຖືກອັບເດດທັນທີໂດຍບໍ່ຕ້ອງຣີສະຕາດຄອນເທນເນີ.',
|
||||
channelDeleteConfirm: 'ລຶບການຕັ້ງຄ່າຊ່ອງທາງ {0}?',
|
||||
apiTypeBaseURLHelper: 'ປະເພດນີ້ຈະສົ່ງການຮ້ອງຂໍໄປທີ່ {0}. Base URL ທີ່ແນະນຳ: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -933,6 +933,8 @@ const message = {
|
||||
'Menyimpan akan memulakan semula bekas secara automatik supaya konfigurasi berkuat kuasa.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Menyimpan nama pengguna atau kata laluan akan membina semula bekas secara automatik supaya perubahan berkuat kuasa.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Apabila disimpan, kelayakan log masuk QwenPaw dikemas kini serta-merta tanpa memulakan semula bekas.',
|
||||
channelDeleteConfirm: 'Padam konfigurasi saluran {0}?',
|
||||
apiTypeBaseURLHelper: 'Jenis ini menghantar permintaan ke {0}. Base URL yang disyorkan: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -929,6 +929,8 @@ const message = {
|
||||
'Ao salvar, o contêiner será reiniciado automaticamente para que a configuração entre em vigor.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Ao salvar o usuário ou a senha, o contêiner será reconstruído automaticamente para que as alterações entrem em vigor.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Ao salvar, as credenciais do QwenPaw são atualizadas imediatamente, sem reiniciar o contêiner.',
|
||||
channelDeleteConfirm: 'Excluir a configuração do canal {0}?',
|
||||
apiTypeBaseURLHelper: 'Este tipo envia requisições para {0}. Base URL recomendada: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -922,6 +922,8 @@ const message = {
|
||||
'После сохранения контейнер будет автоматически перезапущен, чтобы настройки вступили в силу.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'После сохранения имени пользователя или пароля контейнер будет автоматически пересобран, чтобы изменения вступили в силу.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'После сохранения учетные данные QwenPaw обновляются сразу, без перезапуска контейнера.',
|
||||
channelDeleteConfirm: 'Удалить конфигурацию канала {0}?',
|
||||
apiTypeBaseURLHelper: 'Этот тип отправляет запросы в {0}. Рекомендуемый Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -931,6 +931,8 @@ const message = {
|
||||
'Kaydettiğinizde ayarların etkili olması için konteyner otomatik olarak yeniden başlatılır.',
|
||||
dashboardAuthAutoRebuildHelper:
|
||||
'Kullanıcı adı veya parola kaydedildiğinde değişikliklerin etkili olması için konteyner otomatik olarak yeniden oluşturulur.',
|
||||
dashboardAuthImmediateHelper:
|
||||
'Kaydedildiğinde QwenPaw oturum açma bilgileri konteyner yeniden başlatılmadan hemen güncellenir.',
|
||||
channelDeleteConfirm: '{0} kanal yapılandırması silinsin mi?',
|
||||
apiTypeBaseURLHelper: 'Bu tür istekleri {0} yoluna gönderir. Önerilen Base URL: {1}',
|
||||
customImageURLHelper:
|
||||
|
||||
@@ -877,6 +877,7 @@ const message = {
|
||||
scanConnectHelper: '點擊後將在任務日誌中顯示 QR Code,掃碼確認成功後將自動重新啟動容器。',
|
||||
channelAutoRestartHelper: '保存後將自動重新啟動容器以使設定生效。',
|
||||
dashboardAuthAutoRebuildHelper: '保存使用者名稱或密碼後將自動重建容器以使設定生效。',
|
||||
dashboardAuthImmediateHelper: '保存後將立即更新 QwenPaw 登入憑據,無需重新啟動容器。',
|
||||
channelDeleteConfirm: '確認刪除 {0} 頻道設定?',
|
||||
apiTypeBaseURLHelper: '目前類型最終請求 {0},Base URL 建議填寫 {1}',
|
||||
customImageURLHelper: 'Custom 圖片帳號請填寫完整的圖片產生介面 URL,系統不會自動補全路徑,例如:{0}',
|
||||
|
||||
@@ -890,6 +890,7 @@ const message = {
|
||||
scanConnectHelper: '点击后将在任务日志中显示二维码,扫码确认成功后将自动重启容器。',
|
||||
channelAutoRestartHelper: '保存后将自动重启容器以使配置生效。',
|
||||
dashboardAuthAutoRebuildHelper: '保存用户名密码后将自动重建容器以使配置生效。',
|
||||
dashboardAuthImmediateHelper: '保存后将立即更新 QwenPaw 登录凭据,无需重启容器。',
|
||||
channelDeleteConfirm: '确认删除 {0} 频道配置?',
|
||||
apiTypeBaseURLHelper: '当前类型最终请求 {0},Base URL 建议填写 {1}',
|
||||
customImageURLHelper: 'Custom 图片账号请填写完整的图片生成接口 URL,系统不会自动补全路径,例如:{0}',
|
||||
|
||||
@@ -26,6 +26,10 @@ export const supportsAgentToken = (agentType: string): boolean => {
|
||||
return agentType === 'openclaw';
|
||||
};
|
||||
|
||||
export const supportsAgentDashboardAuth = (agentType: string): boolean => {
|
||||
return agentType === 'hermes-agent' || agentType === 'copaw';
|
||||
};
|
||||
|
||||
export const isOpenclawHTTPSWindowVersion = (version: string): boolean => {
|
||||
return compareVersion(version, openclawHTTPSVersion) && !compareVersion(version, openclawHTTPVersion);
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<el-form-item :label="$t('aiTools.agents.webuiPort')" prop="webUIPort">
|
||||
<el-input-number v-model="form.webUIPort" :min="1" :max="65535" />
|
||||
</el-form-item>
|
||||
<template v-if="form.agentType === 'hermes-agent'">
|
||||
<template v-if="supportsAgentDashboardAuth(form.agentType)">
|
||||
<el-form-item :label="$t('commons.login.username')" prop="dashboardUsername">
|
||||
<el-input v-model="form.dashboardUsername" />
|
||||
</el-form-item>
|
||||
@@ -131,6 +131,7 @@ import {
|
||||
buildDefaultAllowedOrigin,
|
||||
getAgentProviderDisplayName,
|
||||
parseAllowedOriginsInput,
|
||||
supportsAgentDashboardAuth,
|
||||
validateAllowedOriginsInput,
|
||||
} from '@/utils/agent';
|
||||
import { App } from '@/api/interface/app';
|
||||
@@ -187,8 +188,8 @@ const generateDashboardPassword = () => {
|
||||
form.dashboardPassword = getRandomStr(8);
|
||||
};
|
||||
|
||||
const ensureHermesDashboardAuth = () => {
|
||||
if (form.agentType !== 'hermes-agent') {
|
||||
const ensureDashboardAuth = () => {
|
||||
if (!supportsAgentDashboardAuth(form.agentType)) {
|
||||
return;
|
||||
}
|
||||
if (!form.dashboardUsername) {
|
||||
@@ -411,7 +412,7 @@ const handleAgentTypeChange = async () => {
|
||||
form.provider = '';
|
||||
form.accountId = undefined as unknown as number;
|
||||
form.baseURL = '';
|
||||
ensureHermesDashboardAuth();
|
||||
ensureDashboardAuth();
|
||||
if (form.agentType === 'openclaw') {
|
||||
await loadSystemIP();
|
||||
allowedOriginsAutoFilled.value = true;
|
||||
@@ -487,8 +488,8 @@ const submit = async () => {
|
||||
model: showModelConfig.value ? form.model : undefined,
|
||||
accountId: showModelConfig.value ? form.accountId : undefined,
|
||||
token: form.agentType === 'openclaw' ? form.token : undefined,
|
||||
dashboardUsername: form.agentType === 'hermes-agent' ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: form.agentType === 'hermes-agent' ? form.dashboardPassword : undefined,
|
||||
dashboardUsername: supportsAgentDashboardAuth(form.agentType) ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: supportsAgentDashboardAuth(form.agentType) ? form.dashboardPassword : undefined,
|
||||
taskID: taskID,
|
||||
advanced: form.advanced,
|
||||
containerName: form.containerName,
|
||||
@@ -536,7 +537,7 @@ const openDrawer = async (agentType?: AI.AgentType) => {
|
||||
form.agentType = targetType;
|
||||
setDefaultWebUIPort();
|
||||
form.token = getRandomStr(32).toLowerCase();
|
||||
ensureHermesDashboardAuth();
|
||||
ensureDashboardAuth();
|
||||
if (form.agentType === 'copaw') {
|
||||
form.allowedOrigins = '';
|
||||
lastAutoAllowedOrigins.value = '';
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
>
|
||||
<ChannelsTab ref="channelsRef" :app-version="appVersion" :agent-type="agentType" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="t('aiTools.model.model')" name="model">
|
||||
<el-tab-pane v-if="supportsAgentModelConfig(agentType)" :label="t('aiTools.model.model')" name="model">
|
||||
<ModelTab ref="modelRef" @updated="handleModelUpdated" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="agentType === 'openclaw'" :label="t('aiTools.agents.agentRoleTab')" name="agent">
|
||||
@@ -26,7 +26,7 @@
|
||||
<PluginsTab ref="pluginsRef" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
v-if="agentType === 'openclaw' || agentType === 'hermes-agent'"
|
||||
v-if="agentType === 'openclaw' || agentType === 'hermes-agent' || agentType === 'copaw'"
|
||||
:label="t('file.setting')"
|
||||
name="settings"
|
||||
>
|
||||
@@ -48,6 +48,7 @@ import AgentTab from './tabs/agents/index.vue';
|
||||
import SkillsTab from './tabs/skills.vue';
|
||||
import PluginsTab from './tabs/plugins.vue';
|
||||
import SettingsTab from './tabs/settings.vue';
|
||||
import { supportsAgentModelConfig } from '@/utils/agent';
|
||||
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['updated']);
|
||||
@@ -165,13 +166,13 @@ const openDrawer = async (agent: AI.AgentItem) => {
|
||||
configPath.value = agent.configPath;
|
||||
agentType.value = agent.agentType;
|
||||
header.value = `${agent.name} - ${t('menu.config')}`;
|
||||
activeTab.value = agent.agentType === 'openclaw' || agent.agentType === 'hermes-agent' ? 'channels' : 'model';
|
||||
activeTab.value = agent.agentType === 'copaw' ? 'settings' : 'channels';
|
||||
open.value = true;
|
||||
if (agent.agentType === 'openclaw' || agent.agentType === 'hermes-agent') {
|
||||
await loadChannels();
|
||||
return;
|
||||
}
|
||||
await loadModel();
|
||||
await loadSettings();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
</el-select>
|
||||
<span class="input-help">{{ t('aiTools.agents.npmRegistryHelper') }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('aiTools.agents.timeZone')" prop="userTimezone">
|
||||
<el-form-item v-if="agentType !== 'copaw'" :label="t('aiTools.agents.timeZone')" prop="userTimezone">
|
||||
<el-input v-model="form.userTimezone" />
|
||||
</el-form-item>
|
||||
<template v-if="agentType === 'hermes-agent'">
|
||||
<template v-if="supportsAgentDashboardAuth(agentType)">
|
||||
<el-form-item :label="t('commons.login.username')" prop="dashboardUsername">
|
||||
<el-input v-model="form.dashboardUsername" />
|
||||
</el-form-item>
|
||||
@@ -33,7 +33,9 @@
|
||||
{{
|
||||
agentType === 'hermes-agent'
|
||||
? t('aiTools.agents.dashboardAuthAutoRebuildHelper')
|
||||
: t('aiTools.agents.channelAutoRestartHelper')
|
||||
: agentType === 'copaw'
|
||||
? t('aiTools.agents.dashboardAuthImmediateHelper')
|
||||
: t('aiTools.agents.channelAutoRestartHelper')
|
||||
}}
|
||||
</span>
|
||||
</el-form>
|
||||
@@ -47,6 +49,7 @@ import { Rules } from '@/global/form-rules';
|
||||
import { AI } from '@/api/interface/ai';
|
||||
import { getAgentOtherConfig, updateAgentOtherConfig } from '@/api/modules/ai';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { supportsAgentDashboardAuth } from '@/utils/agent';
|
||||
|
||||
const { t } = useI18n();
|
||||
const loading = ref(false);
|
||||
@@ -71,6 +74,16 @@ const npmRegistryOptions = [
|
||||
'https://repo.huaweicloud.com/repository/npm/',
|
||||
];
|
||||
|
||||
const resetForm = () => {
|
||||
Object.assign(form, {
|
||||
userTimezone: '',
|
||||
browserEnabled: true,
|
||||
npmRegistry: defaultNPMRegistry,
|
||||
dashboardUsername: 'admin',
|
||||
dashboardPassword: '',
|
||||
});
|
||||
};
|
||||
|
||||
const validateNPMRegistry = (_rule: any, value: string, callback: (error?: Error) => void) => {
|
||||
if (!value) {
|
||||
callback(new Error(t('commons.rule.requiredInput')));
|
||||
@@ -93,11 +106,12 @@ const rules = reactive({
|
||||
const load = async (params: { agentId: number; agentType: AI.AgentType }) => {
|
||||
agentId.value = params.agentId;
|
||||
agentType.value = params.agentType;
|
||||
resetForm();
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getAgentOtherConfig({ agentId: params.agentId });
|
||||
Object.assign(form, res.data || {});
|
||||
if (params.agentType === 'hermes-agent' && !form.dashboardUsername) {
|
||||
if (supportsAgentDashboardAuth(params.agentType) && !form.dashboardUsername) {
|
||||
form.dashboardUsername = 'admin';
|
||||
}
|
||||
} finally {
|
||||
@@ -114,11 +128,11 @@ const saveConfig = async () => {
|
||||
try {
|
||||
await updateAgentOtherConfig({
|
||||
agentId: agentId.value,
|
||||
userTimezone: form.userTimezone,
|
||||
userTimezone: agentType.value === 'copaw' ? undefined : form.userTimezone,
|
||||
browserEnabled: form.browserEnabled,
|
||||
npmRegistry: agentType.value === 'openclaw' ? form.npmRegistry : defaultNPMRegistry,
|
||||
dashboardUsername: agentType.value === 'hermes-agent' ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: agentType.value === 'hermes-agent' ? form.dashboardPassword : undefined,
|
||||
dashboardUsername: supportsAgentDashboardAuth(agentType.value) ? form.dashboardUsername : undefined,
|
||||
dashboardPassword: supportsAgentDashboardAuth(agentType.value) ? form.dashboardPassword : undefined,
|
||||
});
|
||||
MsgSuccess(t('aiTools.agents.saveSuccess'));
|
||||
} finally {
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
</el-button>
|
||||
</el-space>
|
||||
<el-space
|
||||
v-else-if="row.agentType === 'hermes-agent'"
|
||||
v-else-if="supportsAgentDashboardAuth(row.agentType)"
|
||||
direction="vertical"
|
||||
alignment="start"
|
||||
:size="2"
|
||||
@@ -303,6 +303,7 @@ import {
|
||||
getOpenclawAccessScheme,
|
||||
supportsAgentModelConfig,
|
||||
supportsAgentToken,
|
||||
supportsAgentDashboardAuth,
|
||||
} from '@/utils/agent';
|
||||
import { routerToFileWithPath } from '@/utils/router';
|
||||
import { listDomains } from '@/api/modules/website';
|
||||
@@ -356,7 +357,8 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('menu.config'),
|
||||
click: (row: AI.AgentItem) => openConfig(row),
|
||||
show: (row: AI.AgentItem) => supportsAgentModelConfig(row.agentType),
|
||||
show: (row: AI.AgentItem) =>
|
||||
supportsAgentModelConfig(row.agentType) || supportsAgentDashboardAuth(row.agentType),
|
||||
disabled: (row: AI.AgentItem) => row.status !== 'Running',
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user