From 2213fb1ebfdc0129ac45b6ad3c7cb653711e162a Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sun, 1 Feb 2026 18:12:11 +0800 Subject: [PATCH] feat: add proactive messaging support in CronJobPage and enhance file download tool with user notification option --- astrbot/core/computer/tools/fs.py | 22 +++++++++----- astrbot/core/platform/platform.py | 9 ++++++ .../sources/webchat/webchat_adapter.py | 1 + .../full/vertical-sidebar/sidebarItem.ts | 30 +++++++++---------- dashboard/src/views/CronJobPage.vue | 28 ++++++++++++++++- 5 files changed, 66 insertions(+), 24 deletions(-) diff --git a/astrbot/core/computer/tools/fs.py b/astrbot/core/computer/tools/fs.py index b68622940..47f130700 100644 --- a/astrbot/core/computer/tools/fs.py +++ b/astrbot/core/computer/tools/fs.py @@ -144,7 +144,11 @@ class FileDownloadTool(FunctionTool): "remote_path": { "type": "string", "description": "The path of the file in the sandbox to download.", - } + }, + "also_send_to_user": { + "type": "boolean", + "description": "Whether to also send the downloaded file to the user via message. Defaults to true.", + }, }, "required": ["remote_path"], } @@ -154,6 +158,7 @@ class FileDownloadTool(FunctionTool): self, context: ContextWrapper[AstrAgentContext], remote_path: str, + also_send_to_user: bool = True, ) -> ToolExecResult: sb = await get_booter( context.context.context, @@ -168,13 +173,14 @@ class FileDownloadTool(FunctionTool): await sb.download_file(remote_path, local_path) logger.info(f"File {remote_path} downloaded from sandbox to {local_path}") - try: - name = os.path.basename(local_path) - await context.context.event.send( - MessageChain(chain=[File(name=name, file=local_path)]) - ) - except Exception as e: - logger.error(f"Error sending file message: {e}") + if also_send_to_user: + try: + name = os.path.basename(local_path) + await context.context.event.send( + MessageChain(chain=[File(name=name, file=local_path)]) + ) + except Exception as e: + logger.error(f"Error sending file message: {e}") # remove try: diff --git a/astrbot/core/platform/platform.py b/astrbot/core/platform/platform.py index c2e55fb63..8592273d1 100644 --- a/astrbot/core/platform/platform.py +++ b/astrbot/core/platform/platform.py @@ -90,6 +90,14 @@ class Platform(abc.ABC): def get_stats(self) -> dict: """获取平台统计信息""" meta = self.meta() + meta_info = { + "id": meta.id, + "name": meta.name, + "display_name": meta.adapter_display_name or meta.name, + "description": meta.description, + "support_streaming_message": meta.support_streaming_message, + "support_proactive_message": meta.support_proactive_message, + } return { "id": meta.id or self.config.get("id"), "type": meta.name, @@ -105,6 +113,7 @@ class Platform(abc.ABC): if self.last_error else None, "unified_webhook": self.unified_webhook(), + "meta": meta_info, } @abc.abstractmethod diff --git a/astrbot/core/platform/sources/webchat/webchat_adapter.py b/astrbot/core/platform/sources/webchat/webchat_adapter.py index 36a451fbd..316c95d81 100644 --- a/astrbot/core/platform/sources/webchat/webchat_adapter.py +++ b/astrbot/core/platform/sources/webchat/webchat_adapter.py @@ -86,6 +86,7 @@ class WebChatAdapter(Platform): name="webchat", description="webchat", id="webchat", + support_proactive_message=False, ) async def send_by_session( diff --git a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts index e75ddb661..fce2c8efc 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts +++ b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts @@ -43,25 +43,15 @@ const sidebarItem: menu[] = [ icon: 'mdi-book-open-variant', to: '/knowledge-base', }, + { + title: 'core.navigation.persona', + icon: 'mdi-heart', + to: '/persona' + }, { title: 'core.navigation.groups.more', icon: 'mdi-dots-horizontal', children: [ - { - title: 'core.navigation.persona', - icon: 'mdi-heart', - to: '/persona' - }, - { - title: 'core.navigation.subagent', - icon: 'mdi-vector-link', - to: '/subagent' - }, - { - title: 'core.navigation.cron', - icon: 'mdi-clock-outline', - to: '/cron' - }, { title: 'core.navigation.conversation', icon: 'mdi-database', @@ -72,6 +62,16 @@ const sidebarItem: menu[] = [ icon: 'mdi-pencil-ruler', to: '/session-management' }, + { + title: 'core.navigation.cron', + icon: 'mdi-clock-outline', + to: '/cron' + }, + { + title: 'core.navigation.subagent', + icon: 'mdi-vector-link', + to: '/subagent' + }, { title: 'core.navigation.dashboard', icon: 'mdi-view-dashboard', diff --git a/dashboard/src/views/CronJobPage.vue b/dashboard/src/views/CronJobPage.vue index 3c58c642c..23d2eb561 100644 --- a/dashboard/src/views/CronJobPage.vue +++ b/dashboard/src/views/CronJobPage.vue @@ -6,7 +6,14 @@

未来任务管理

Beta -
查看给 AstrBot 布置的未来任务。AstrBot 将会被自动唤醒、执行任务,然后将结果告知任务布置方。
+
+ 查看给 AstrBot 布置的未来任务。AstrBot 将会被自动唤醒、执行任务,然后将结果告知任务布置方。 + 主动发送结果仅支持以下平台: + + {{ proactivePlatforms.map((p) => `${p.display_name || p.name}(${p.id})`).join('、') }} + + 暂无支持主动消息的平台,请在平台设置中开启。 +
刷新 @@ -60,6 +67,7 @@ import axios from 'axios' const loading = ref(false) const jobs = ref([]) +const proactivePlatforms = ref<{ id: string; name: string; display_name?: string }[]>([]) const snackbar = ref({ show: false, message: '', color: 'success' }) @@ -102,6 +110,23 @@ async function loadJobs() { } } +async function loadPlatforms() { + try { + const res = await axios.get('/api/platform/stats') + if (res.data.status === 'ok' && Array.isArray(res.data.data?.platforms)) { + proactivePlatforms.value = res.data.data.platforms + .filter((p: any) => p?.meta?.support_proactive_message) + .map((p: any) => ({ + id: p?.id || p?.meta?.id || 'unknown', + name: p?.meta?.name || p?.type || '', + display_name: p?.meta?.display_name || p?.display_name + })) + } + } catch (e) { + // ignore platform fetch errors in UI; subtitle will show fallback + } +} + async function toggleJob(job: any) { try { const res = await axios.patch(`/api/cron/jobs/${job.job_id}`, { enabled: job.enabled }) @@ -131,6 +156,7 @@ async function deleteJob(job: any) { onMounted(() => { loadJobs() + loadPlatforms() })