From 382aaaf053dcc5f04316fb5471c15ad0d82e653b Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sun, 1 Feb 2026 22:04:44 +0800 Subject: [PATCH] feat: i18n --- astrbot/core/computer/tools/fs.py | 2 +- astrbot/core/star/context.py | 2 +- astrbot/core/tools/cron_tools.py | 1 + astrbot/dashboard/routes/cron.py | 4 +- dashboard/src/i18n/loader.ts | 2 + .../src/i18n/locales/en-US/features/cron.json | 64 +++++++ .../i18n/locales/en-US/features/subagent.json | 53 ++++++ .../src/i18n/locales/zh-CN/features/cron.json | 64 +++++++ .../i18n/locales/zh-CN/features/subagent.json | 53 ++++++ dashboard/src/i18n/translations.ts | 12 +- dashboard/src/views/CronJobPage.vue | 140 +++++++++------ dashboard/src/views/SubAgentPage.vue | 160 +++++++++++------- 12 files changed, 437 insertions(+), 120 deletions(-) create mode 100644 dashboard/src/i18n/locales/en-US/features/cron.json create mode 100644 dashboard/src/i18n/locales/en-US/features/subagent.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/cron.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/subagent.json diff --git a/astrbot/core/computer/tools/fs.py b/astrbot/core/computer/tools/fs.py index a1c0f848f..9acc371b2 100644 --- a/astrbot/core/computer/tools/fs.py +++ b/astrbot/core/computer/tools/fs.py @@ -187,7 +187,7 @@ class FileDownloadTool(FunctionTool): os.remove(local_path) except Exception as e: logger.error(f"Error removing temp file {local_path}: {e}") - + return f"File downloaded successfully to {local_path} and sent to user. The file has been removed from local storage." return f"File downloaded successfully to {local_path}" diff --git a/astrbot/core/star/context.py b/astrbot/core/star/context.py index ec7cbbe9e..c7438baf2 100644 --- a/astrbot/core/star/context.py +++ b/astrbot/core/star/context.py @@ -24,7 +24,6 @@ from astrbot.core.platform_message_history_mgr import PlatformMessageHistoryMana from astrbot.core.provider.entities import LLMResponse, ProviderRequest, ProviderType from astrbot.core.provider.func_tool_manager import FunctionTool, FunctionToolManager from astrbot.core.provider.manager import ProviderManager -from astrbot.core.subagent_orchestrator import SubAgentOrchestrator from astrbot.core.provider.provider import ( EmbeddingProvider, Provider, @@ -36,6 +35,7 @@ from astrbot.core.star.filter.platform_adapter_type import ( ADAPTER_NAME_2_TYPE, PlatformAdapterType, ) +from astrbot.core.subagent_orchestrator import SubAgentOrchestrator from ..exceptions import ProviderNotFoundError from .filter.command import CommandFilter diff --git a/astrbot/core/tools/cron_tools.py b/astrbot/core/tools/cron_tools.py index f3e9f1ca4..ee22b943d 100644 --- a/astrbot/core/tools/cron_tools.py +++ b/astrbot/core/tools/cron_tools.py @@ -1,4 +1,5 @@ from datetime import datetime + from pydantic import Field from pydantic.dataclasses import dataclass diff --git a/astrbot/dashboard/routes/cron.py b/astrbot/dashboard/routes/cron.py index ae739273a..6bef93859 100644 --- a/astrbot/dashboard/routes/cron.py +++ b/astrbot/dashboard/routes/cron.py @@ -76,9 +76,7 @@ class CronRoute(Route): run_at = payload.get("run_at") if not session: - return jsonify( - Response().error("session is required").__dict__ - ) + return jsonify(Response().error("session is required").__dict__) if run_once and not run_at: return jsonify( Response().error("run_at is required when run_once=true").__dict__ diff --git a/dashboard/src/i18n/loader.ts b/dashboard/src/i18n/loader.ts index 5d39d0b64..4ea85a213 100644 --- a/dashboard/src/i18n/loader.ts +++ b/dashboard/src/i18n/loader.ts @@ -52,6 +52,8 @@ export class I18nLoader { { name: 'features/auth', path: 'features/auth.json' }, { name: 'features/chart', path: 'features/chart.json' }, { name: 'features/dashboard', path: 'features/dashboard.json' }, + { name: 'features/cron', path: 'features/cron.json' }, + { name: 'features/subagent', path: 'features/subagent.json' }, { name: 'features/alkaid/index', path: 'features/alkaid/index.json' }, { name: 'features/alkaid/knowledge-base', path: 'features/alkaid/knowledge-base.json' }, { name: 'features/alkaid/memory', path: 'features/alkaid/memory.json' }, diff --git a/dashboard/src/i18n/locales/en-US/features/cron.json b/dashboard/src/i18n/locales/en-US/features/cron.json new file mode 100644 index 000000000..60ec6b055 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/cron.json @@ -0,0 +1,64 @@ +{ + "page": { + "title": "Future Task Management", + "beta": "Beta", + "subtitle": "See scheduled tasks for AstrBot. AstrBot will wake up, run them, and deliver the results.", + "proactive": { + "supported": "Proactive delivery is available on: {platforms}", + "unsupported": "No proactive messaging platforms enabled. Turn them on in Platform settings." + } + }, + "actions": { + "create": "New Task", + "refresh": "Refresh", + "delete": "Delete", + "cancel": "Cancel", + "submit": "Create" + }, + "table": { + "title": "Registered Tasks", + "empty": "No tasks yet.", + "headers": { + "name": "Name", + "type": "Type", + "cron": "Cron", + "nextRun": "Next Run", + "lastRun": "Last Run", + "note": "Note", + "actions": "Actions" + }, + "type": { + "once": "One-off", + "recurring": "Recurring", + "activeAgent": "Active Agent", + "workflow": "Workflow", + "unknown": "{type}" + }, + "timezoneLocal": "local", + "notAvailable": "—" + }, + "form": { + "title": "New Task", + "runOnce": "One-off task", + "name": "Task name", + "note": "Task description", + "cron": "Cron expression", + "cronPlaceholder": "0 9 * * *", + "runAt": "Run at", + "session": "Target session (platform_id:message_type:session_id)", + "timezone": "Timezone (optional, e.g. Asia/Shanghai)", + "enabled": "Enabled" + }, + "messages": { + "loadFailed": "Failed to load tasks", + "updateFailed": "Failed to update", + "deleteSuccess": "Deleted", + "deleteFailed": "Failed to delete", + "sessionRequired": "Session is required", + "noteRequired": "Description is required", + "cronRequired": "Cron expression is required", + "runAtRequired": "Please select run time", + "createSuccess": "Created successfully", + "createFailed": "Failed to create" + } +} diff --git a/dashboard/src/i18n/locales/en-US/features/subagent.json b/dashboard/src/i18n/locales/en-US/features/subagent.json new file mode 100644 index 000000000..8c8ed34e5 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/subagent.json @@ -0,0 +1,53 @@ +{ + "page": { + "title": "SubAgent Orchestration", + "beta": "Beta", + "subtitle": "The main LLM only chats and delegates; tools live on individual SubAgents." + }, + "actions": { + "refresh": "Refresh", + "save": "Save", + "add": "Add SubAgent", + "delete": "Delete" + }, + "switches": { + "enable": "Enable SubAgent orchestration", + "dedupe": "Deduplicate main LLM tools (hide tools duplicated by SubAgents)" + }, + "description": { + "disabled": "When off: SubAgent is disabled; the main LLM mounts tools via persona rules (all by default) and calls them directly.", + "enabled": "When on: the main LLM keeps its own tools and mounts transfer_to_* delegate tools. With deduplication, tools overlapping with SubAgents are removed from the main tool set." + }, + "section": { + "title": "SubAgents" + }, + "cards": { + "statusEnabled": "Enabled", + "statusDisabled": "Disabled", + "unnamed": "Untitled SubAgent", + "transferPrefix": "transfer_to_{name}", + "switchLabel": "Enable", + "previewTitle": "Preview: handoff tool shown to the main LLM", + "personaChip": "Persona: {id}" + }, + "form": { + "nameLabel": "Agent name (used for transfer_to_{name})", + "nameHint": "Use lowercase letters + underscores; must be globally unique.", + "providerLabel": "Chat Provider (optional)", + "providerHint": "Leave empty to follow the global default provider.", + "personaLabel": "Choose Persona", + "personaHint": "The SubAgent inherits the selected Persona's system settings and tools.", + "descriptionLabel": "Description for the main LLM (used to decide handoff)", + "descriptionHint": "Shown to the main LLM as the transfer_to_* tool description—keep it short and clear." + }, + "messages": { + "loadConfigFailed": "Failed to load config", + "loadPersonaFailed": "Failed to load persona list", + "nameMissing": "A SubAgent is missing a name", + "nameInvalid": "Invalid SubAgent name: only lowercase letters/numbers/underscores, starting with a letter", + "nameDuplicate": "Duplicate SubAgent name: {name}", + "personaMissing": "SubAgent {name} has no persona selected", + "saveSuccess": "Saved successfully", + "saveFailed": "Failed to save" + } +} diff --git a/dashboard/src/i18n/locales/zh-CN/features/cron.json b/dashboard/src/i18n/locales/zh-CN/features/cron.json new file mode 100644 index 000000000..38e2f440e --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/cron.json @@ -0,0 +1,64 @@ +{ + "page": { + "title": "未来任务管理", + "beta": "Beta", + "subtitle": "查看给 AstrBot 布置的未来任务。AstrBot 将会被自动唤醒、执行任务,然后将结果告知任务布置方。", + "proactive": { + "supported": "主动发送结果仅支持以下平台:{platforms}", + "unsupported": "暂无支持主动消息的平台,请在平台设置中开启。" + } + }, + "actions": { + "create": "新建任务", + "refresh": "刷新", + "delete": "删除", + "cancel": "取消", + "submit": "创建" + }, + "table": { + "title": "已注册任务", + "empty": "暂无任务。", + "headers": { + "name": "名称", + "type": "类型", + "cron": "Cron", + "nextRun": "下一次执行", + "lastRun": "最近执行", + "note": "说明", + "actions": "操作" + }, + "type": { + "once": "一次性", + "recurring": "循环", + "activeAgent": "Active Agent", + "workflow": "Workflow", + "unknown": "{type}" + }, + "timezoneLocal": "本地时区", + "notAvailable": "—" + }, + "form": { + "title": "新建任务", + "runOnce": "一次性任务", + "name": "任务名称", + "note": "任务说明", + "cron": "Cron 表达式", + "cronPlaceholder": "0 9 * * *", + "runAt": "执行时间", + "session": "目标 session (platform_id:message_type:session_id)", + "timezone": "时区(可选,如 Asia/Shanghai)", + "enabled": "启用" + }, + "messages": { + "loadFailed": "获取任务失败", + "updateFailed": "更新失败", + "deleteSuccess": "已删除", + "deleteFailed": "删除失败", + "sessionRequired": "请填写 session", + "noteRequired": "请填写说明", + "cronRequired": "请填写 Cron 表达式", + "runAtRequired": "请选择执行时间", + "createSuccess": "创建成功", + "createFailed": "创建失败" + } +} diff --git a/dashboard/src/i18n/locales/zh-CN/features/subagent.json b/dashboard/src/i18n/locales/zh-CN/features/subagent.json new file mode 100644 index 000000000..16533ace4 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/subagent.json @@ -0,0 +1,53 @@ +{ + "page": { + "title": "SubAgent 编排", + "beta": "Beta", + "subtitle": "主 LLM 只负责聊天与分派(handoff),工具挂载在各个 SubAgent 上。" + }, + "actions": { + "refresh": "刷新", + "save": "保存", + "add": "新增 SubAgent", + "delete": "删除" + }, + "switches": { + "enable": "启用 SubAgent 编排", + "dedupe": "主 LLM 去重重复工具(与 SubAgent 重叠的工具将被隐藏)" + }, + "description": { + "disabled": "不启动:SubAgent 关闭;主 LLM 按 persona 规则挂载工具(默认全部),并直接调用。", + "enabled": "启动:主 LLM 会保留自身工具并挂载 transfer_to_* 委派工具。若开启“去重重复工具”,与 SubAgent 指定的工具重叠部分会从主 LLM 工具集中移除。" + }, + "section": { + "title": "SubAgents" + }, + "cards": { + "statusEnabled": "启用", + "statusDisabled": "停用", + "unnamed": "未命名 SubAgent", + "transferPrefix": "transfer_to_{name}", + "switchLabel": "启用", + "previewTitle": "预览:主 LLM 将看到的 handoff 工具", + "personaChip": "Persona: {id}" + }, + "form": { + "nameLabel": "Agent 名称(用于 transfer_to_{name})", + "nameHint": "建议使用英文小写+下划线,且全局唯一", + "providerLabel": "Chat Provider(可选)", + "providerHint": "留空表示跟随全局默认 provider。", + "personaLabel": "选择 Persona", + "personaHint": "SubAgent 将直接继承所选 Persona 的系统设定与工具。", + "descriptionLabel": "对主 LLM 的描述(用于决定是否 handoff)", + "descriptionHint": "这段会作为 transfer_to_* 工具的描述给主 LLM 看,建议简短明确。" + }, + "messages": { + "loadConfigFailed": "获取配置失败", + "loadPersonaFailed": "获取 Persona 列表失败", + "nameMissing": "存在未填写名称的 SubAgent", + "nameInvalid": "SubAgent 名称不合法:仅允许英文小写字母/数字/下划线,且需以字母开头", + "nameDuplicate": "SubAgent 名称重复:{name}", + "personaMissing": "SubAgent {name} 未选择 Persona", + "saveSuccess": "保存成功", + "saveFailed": "保存失败" + } +} diff --git a/dashboard/src/i18n/translations.ts b/dashboard/src/i18n/translations.ts index dd67ca54a..e2c64dcb9 100644 --- a/dashboard/src/i18n/translations.ts +++ b/dashboard/src/i18n/translations.ts @@ -25,6 +25,7 @@ import zhCNSettings from './locales/zh-CN/features/settings.json'; import zhCNAuth from './locales/zh-CN/features/auth.json'; import zhCNChart from './locales/zh-CN/features/chart.json'; import zhCNDashboard from './locales/zh-CN/features/dashboard.json'; +import zhCNCron from './locales/zh-CN/features/cron.json'; import zhCNAlkaidIndex from './locales/zh-CN/features/alkaid/index.json'; import zhCNAlkaidKnowledgeBase from './locales/zh-CN/features/alkaid/knowledge-base.json'; import zhCNAlkaidMemory from './locales/zh-CN/features/alkaid/memory.json'; @@ -34,6 +35,7 @@ import zhCNKnowledgeBaseDocument from './locales/zh-CN/features/knowledge-base/d import zhCNPersona from './locales/zh-CN/features/persona.json'; import zhCNMigration from './locales/zh-CN/features/migration.json'; import zhCNCommand from './locales/zh-CN/features/command.json'; +import zhCNSubagent from './locales/zh-CN/features/subagent.json'; import zhCNErrors from './locales/zh-CN/messages/errors.json'; import zhCNSuccess from './locales/zh-CN/messages/success.json'; @@ -63,6 +65,7 @@ import enUSSettings from './locales/en-US/features/settings.json'; import enUSAuth from './locales/en-US/features/auth.json'; import enUSChart from './locales/en-US/features/chart.json'; import enUSDashboard from './locales/en-US/features/dashboard.json'; +import enUSCron from './locales/en-US/features/cron.json'; import enUSAlkaidIndex from './locales/en-US/features/alkaid/index.json'; import enUSAlkaidKnowledgeBase from './locales/en-US/features/alkaid/knowledge-base.json'; import enUSAlkaidMemory from './locales/en-US/features/alkaid/memory.json'; @@ -72,6 +75,7 @@ import enUSKnowledgeBaseDocument from './locales/en-US/features/knowledge-base/d import enUSPersona from './locales/en-US/features/persona.json'; import enUSMigration from './locales/en-US/features/migration.json'; import enUSCommand from './locales/en-US/features/command.json'; +import enUSSubagent from './locales/en-US/features/subagent.json'; import enUSErrors from './locales/en-US/messages/errors.json'; import enUSSuccess from './locales/en-US/messages/success.json'; @@ -105,6 +109,7 @@ export const translations = { auth: zhCNAuth, chart: zhCNChart, dashboard: zhCNDashboard, + cron: zhCNCron, alkaid: { index: zhCNAlkaidIndex, 'knowledge-base': zhCNAlkaidKnowledgeBase, @@ -117,7 +122,8 @@ export const translations = { }, persona: zhCNPersona, migration: zhCNMigration, - command: zhCNCommand + command: zhCNCommand, + subagent: zhCNSubagent }, messages: { errors: zhCNErrors, @@ -151,6 +157,7 @@ export const translations = { auth: enUSAuth, chart: enUSChart, dashboard: enUSDashboard, + cron: enUSCron, alkaid: { index: enUSAlkaidIndex, 'knowledge-base': enUSAlkaidKnowledgeBase, @@ -163,7 +170,8 @@ export const translations = { }, persona: enUSPersona, migration: enUSMigration, - command: enUSCommand + command: enUSCommand, + subagent: enUSSubagent }, messages: { errors: enUSErrors, diff --git a/dashboard/src/views/CronJobPage.vue b/dashboard/src/views/CronJobPage.vue index 4cf69ee1a..1e8cfb8e2 100644 --- a/dashboard/src/views/CronJobPage.vue +++ b/dashboard/src/views/CronJobPage.vue @@ -3,58 +3,69 @@