From 31846cbba3b5faa6905d40b72978d2149dda9210 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Fri, 10 Apr 2026 19:15:07 +0800 Subject: [PATCH] feat: enhance onboarding steps to include computer access configuration and related help information --- .../i18n/locales/en-US/features/welcome.json | 23 ++- .../i18n/locales/ru-RU/features/welcome.json | 25 ++- .../i18n/locales/zh-CN/features/welcome.json | 23 ++- dashboard/src/views/WelcomePage.vue | 182 ++++++++++++++++-- 4 files changed, 219 insertions(+), 34 deletions(-) diff --git a/dashboard/src/i18n/locales/en-US/features/welcome.json b/dashboard/src/i18n/locales/en-US/features/welcome.json index 670d0a66d..7c1232774 100644 --- a/dashboard/src/i18n/locales/en-US/features/welcome.json +++ b/dashboard/src/i18n/locales/en-US/features/welcome.json @@ -12,11 +12,21 @@ "onboard": { "title": "Quick Onboarding", "subtitle": "Complete initialization directly on the welcome page.", - "step1Title": "Configure Platform Bot", - "step1Desc": "Connect AstrBot to IM platforms like QQ, Lark, Slack, Telegram, etc.", - "step2Title": "Configure AI Model", - "step2Desc": "Configure AI models for AstrBot.", + "step1Title": "Configure AI Model", + "step1Desc": "Configure AI models for AstrBot.", + "step2Title": "Configure Platform Bot", + "step2Desc": "Connect AstrBot to IM platforms like QQ, Lark, Slack, Telegram, etc.", + "step3Title": "Allow Agent to Use the Computer", + "step3Desc": "Set whether the Agent can access and use this computer.", + "step3HelpTitle": "Access Details", + "step3HelpItem1": "The Agent can access and use the workspace directory, which is isolated for each user, as well as Skills to handle more complex tasks.", + "step3HelpItem2": "For AstrBot administrators, the Agent is additionally allowed to execute shell commands, run Python code, and access all local directories on this machine.", + "step3HelpClose": "Close", + "step3SelectLabel": "Computer Access", + "step3Allow": "Allow", + "step3Deny": "Disallow", "configure": "Configure", + "save": "Save", "skip": "Skip", "pending": "Pending", "completed": "Completed", @@ -24,7 +34,10 @@ "platformLoadFailed": "Failed to load platform configuration", "providerLoadFailed": "Failed to load provider configuration", "providerUpdateFailed": "Failed to update default chat provider in config file \"default\"", - "providerDefaultUpdated": "Default chat provider in config file \"default\" has been set to {id}" + "providerDefaultUpdated": "Default chat provider in config file \"default\" has been set to {id}", + "computerAccessUpdateFailed": "Failed to update Agent computer access", + "computerAccessAllowed": "Agent is now allowed to access and use the computer", + "computerAccessDenied": "Agent is no longer allowed to access and use the computer" }, "resources": { "title": "Resources", diff --git a/dashboard/src/i18n/locales/ru-RU/features/welcome.json b/dashboard/src/i18n/locales/ru-RU/features/welcome.json index ea7d3043a..8936518e9 100644 --- a/dashboard/src/i18n/locales/ru-RU/features/welcome.json +++ b/dashboard/src/i18n/locales/ru-RU/features/welcome.json @@ -12,11 +12,21 @@ "onboard": { "title": "Быстрый старт", "subtitle": "Вы можете выполнить первичную настройку прямо здесь.", - "step1Title": "Настройка платформ", - "step1Desc": "Подключите AstrBot к QQ, Lark, WeChat, Telegram и другим мессенджерам.", - "step2Title": "Настройка AI моделей", - "step2Desc": "Выберите и настройте AI провайдеров для AstrBot.", + "step1Title": "Настройка AI моделей", + "step1Desc": "Выберите и настройте AI провайдеров для AstrBot.", + "step2Title": "Настройка платформ", + "step2Desc": "Подключите AstrBot к QQ, Lark, WeChat, Telegram и другим мессенджерам.", + "step3Title": "Разрешить Agent использовать компьютер", + "step3Desc": "Укажите, может ли Agent получать доступ к этому компьютеру и использовать его.", + "step3HelpTitle": "Сведения о доступе", + "step3HelpItem1": "Agent сможет получать доступ к каталогу рабочего пространства и использовать его, при этом рабочие каталоги разных пользователей изолированы друг от друга, а также использовать Skills для выполнения более сложных задач.", + "step3HelpItem2": "Для администраторов AstrBot Agent дополнительно сможет выполнять shell-команды, запускать Python-код и получать доступ ко всем локальным каталогам на этом компьютере.", + "step3HelpClose": "Закрыть", + "step3SelectLabel": "Доступ к компьютеру", + "step3Allow": "Разрешить", + "step3Deny": "Запретить", "configure": "Настроить", + "save": "Сохранить", "skip": "Пропустить", "pending": "Ожидает", "completed": "Готово", @@ -24,7 +34,10 @@ "platformLoadFailed": "Ошибка загрузки конфигурации платформ", "providerLoadFailed": "Ошибка загрузки конфигурации провайдеров", "providerUpdateFailed": "Ошибка обновления провайдера по умолчанию в файле default", - "providerDefaultUpdated": "Провайдер {id} установлен по умолчанию в файле default" + "providerDefaultUpdated": "Провайдер {id} установлен по умолчанию в файле default", + "computerAccessUpdateFailed": "Не удалось обновить доступ Agent к компьютеру", + "computerAccessAllowed": "Agent теперь может получать доступ к компьютеру и использовать его", + "computerAccessDenied": "Agent больше не может получать доступ к компьютеру и использовать его" }, "resources": { "title": "Ресурсы", @@ -34,4 +47,4 @@ "afdianTitle": "Afdian", "afdianDesc": "Поддержите команду AstrBot через Afdian." } -} \ No newline at end of file +} diff --git a/dashboard/src/i18n/locales/zh-CN/features/welcome.json b/dashboard/src/i18n/locales/zh-CN/features/welcome.json index 1eb23d7ca..ff968c2b9 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/welcome.json +++ b/dashboard/src/i18n/locales/zh-CN/features/welcome.json @@ -12,11 +12,21 @@ "onboard": { "title": "快速引导", "subtitle": "欢迎页可直接完成初始化。", - "step1Title": "配置平台机器人", - "step1Desc": "将 AstrBot 连接到 QQ、飞书、企业微信、Telegram 等 IM 平台。", - "step2Title": "配置 AI 模型", - "step2Desc": "为 AstrBot 配置 AI 模型。", + "step1Title": "配置 AI 模型", + "step1Desc": "为 AstrBot 配置 AI 模型。", + "step2Title": "配置平台机器人", + "step2Desc": "将 AstrBot 连接到 QQ、飞书、企业微信、Telegram 等 IM 平台。", + "step3Title": "允许 Agent 使用电脑", + "step3Desc": "设置 Agent 是否可以访问和使用当前电脑。", + "step3HelpTitle": "允许 Agent 使用电脑", + "step3HelpItem1": "Agent 将可以访问和使用工作区目录(每个用户的工作区目录相互独立)以及 Skills 来执行更多复杂任务。", + "step3HelpItem2": "对于 AstrBot 管理员,会额外允许 Agent 执行 Shell 命令、Python 代码,以及访问本机的所有目录。", + "step3HelpClose": "关闭", + "step3SelectLabel": "电脑访问权限", + "step3Allow": "允许", + "step3Deny": "不允许", "configure": "去配置", + "save": "保存", "skip": "跳过", "pending": "待处理", "completed": "已完成", @@ -24,7 +34,10 @@ "platformLoadFailed": "加载平台配置失败", "providerLoadFailed": "加载提供商配置失败", "providerUpdateFailed": "更新 default 配置文件默认对话提供商失败", - "providerDefaultUpdated": "已将 default 配置文件的默认对话提供商设置为 {id}" + "providerDefaultUpdated": "已将 default 配置文件的默认对话提供商设置为 {id}", + "computerAccessUpdateFailed": "更新 Agent 电脑访问权限失败", + "computerAccessAllowed": "已允许 Agent 访问和使用电脑", + "computerAccessDenied": "已禁止 Agent 访问和使用电脑" }, "resources": { "title": "相关资源", diff --git a/dashboard/src/views/WelcomePage.vue b/dashboard/src/views/WelcomePage.vue index 5cabdc66a..a4872c3b0 100644 --- a/dashboard/src/views/WelcomePage.vue +++ b/dashboard/src/views/WelcomePage.vue @@ -20,11 +20,28 @@ - +
{{ tm('onboard.step1Title') }}

{{ tm('onboard.step1Desc') }}

+
+ + {{ tm('onboard.configure') }} + +
+ {{ tm('onboard.completed') }} +
+
+
+
+ + +
+
{{ tm('onboard.step2Title') }}
+

{{ tm('onboard.step2Desc') }}

@@ -38,22 +55,37 @@
- +
-
{{ tm('onboard.step2Title') - }} -
-

{{ tm('onboard.step2Desc') }}

-
- - {{ tm('onboard.configure') }} +
+
{{ tm('onboard.step3Title') }}
+ + ? -
- {{ tm('onboard.completed') }} -
+
+

{{ tm('onboard.step3Desc') }}

+
+
@@ -136,6 +168,25 @@ + + + + {{ tm('onboard.step3HelpTitle') }} + + +
    +
  1. {{ tm('onboard.step3HelpItem1') }}
  2. +
  3. {{ tm('onboard.step3HelpItem2') }}
  4. +
+
+ + + + {{ tm('onboard.step3HelpClose') }} + + +
+
@@ -151,6 +202,7 @@ import 'markstream-vue/index.css'; import 'highlight.js/styles/github.css'; type StepState = 'pending' | 'completed' | 'skipped'; +type ComputerAccessRuntime = 'local' | 'none'; const { tm } = useModuleI18n('features/welcome'); const { locale } = useI18n(); @@ -158,6 +210,7 @@ const { success: showSuccess, error: showError } = useToast(); const showAddPlatformDialog = ref(false); const showProviderDialog = ref(false); +const showComputerAccessHelpDialog = ref(false); const loadingPlatformDialog = ref(false); const platformMetadata = ref>({}); @@ -167,6 +220,10 @@ const providerCountBeforeOpen = ref(0); const platformStepState = ref('pending'); const providerStepState = ref('pending'); +const computerAccessStepState = ref('pending'); +const computerAccessRuntime = ref('none'); +const savedComputerAccessRuntime = ref('none'); +const savingComputerAccess = ref(false); const welcomeAnnouncementRaw = ref(null); function resolveWelcomeAnnouncement(raw: unknown, currentLocale: string) { @@ -276,6 +333,11 @@ async function loadPlatformConfigBase() { platformConfigData.value = res.data.data.config || {}; } +async function fetchDefaultConfig() { + const res = await axios.get('/api/config/abconf', { params: { id: 'default' } }); + return res.data?.data?.config || {}; +} + function getChatProvidersFromTemplatePayload(payload: any) { const providers = payload?.providers || []; const sources = payload?.provider_sources || []; @@ -315,8 +377,7 @@ async function syncDefaultConfigProviderIfNeeded() { const targetProviderId = pickDefaultProviderId(providers); if (!targetProviderId) return; - const configRes = await axios.get('/api/config/abconf', { params: { id: 'default' } }); - const configData = configRes.data?.data?.config || {}; + const configData = await fetchDefaultConfig(); if (!configData.provider_settings) { configData.provider_settings = {}; } @@ -336,6 +397,62 @@ async function syncDefaultConfigProviderIfNeeded() { showSuccess(tm('onboard.providerDefaultUpdated', { id: targetProviderId })); } +function normalizeComputerAccessRuntime(runtime: unknown): ComputerAccessRuntime { + return runtime === 'local' || runtime === 'sandbox' ? 'local' : 'none'; +} + +function syncComputerAccessRuntime(configData: any) { + const providerSettings = configData?.provider_settings || {}; + const currentRuntime = providerSettings?.computer_use_runtime; + const normalizedRuntime = normalizeComputerAccessRuntime(currentRuntime); + + computerAccessRuntime.value = normalizedRuntime; + savedComputerAccessRuntime.value = normalizedRuntime; + computerAccessStepState.value = + currentRuntime === 'local' || currentRuntime === 'none' || currentRuntime === 'sandbox' + ? 'completed' + : 'pending'; +} + +const computerAccessOptions = computed(() => [ + { title: tm('onboard.step3Allow'), value: 'local' }, + { title: tm('onboard.step3Deny'), value: 'none' } +]); + +async function saveComputerAccessRuntime() { + savingComputerAccess.value = true; + try { + const configData = await fetchDefaultConfig(); + if (!configData.provider_settings) { + configData.provider_settings = {}; + } + + configData.provider_settings.computer_use_runtime = computerAccessRuntime.value; + + const updateRes = await axios.post('/api/config/astrbot/update', { + conf_id: 'default', + config: configData + }); + if (updateRes.data.status !== 'ok') { + throw new Error(updateRes.data.message || tm('onboard.computerAccessUpdateFailed')); + } + + savedComputerAccessRuntime.value = computerAccessRuntime.value; + computerAccessStepState.value = 'completed'; + showSuccess( + tm( + computerAccessRuntime.value === 'local' + ? 'onboard.computerAccessAllowed' + : 'onboard.computerAccessDenied' + ) + ); + } catch (err: any) { + showError(err?.response?.data?.message || err?.message || tm('onboard.computerAccessUpdateFailed')); + } finally { + savingComputerAccess.value = false; + } +} + async function loadWelcomeAnnouncement() { try { const res = await axios.get('https://cloud.astrbot.app/api/v1/announcement'); @@ -366,6 +483,13 @@ onMounted(async () => { } catch (e) { console.error(e); } + + try { + const defaultConfig = await fetchDefaultConfig(); + syncComputerAccessRuntime(defaultConfig); + } catch (e) { + console.error(e); + } }); async function openPlatformDialog() { @@ -416,6 +540,18 @@ watch(showProviderDialog, async (visible, wasVisible) => { showError(err?.response?.data?.message || err?.message || tm('onboard.providerUpdateFailed')); } }); + +watch(computerAccessRuntime, async (value, oldValue) => { + if (value === oldValue) return; + if (value === savedComputerAccessRuntime.value) return; + if (savingComputerAccess.value) return; + + try { + await saveComputerAccessRuntime(); + } catch { + computerAccessRuntime.value = savedComputerAccessRuntime.value; + } +});