From 96e61a4a92832c66fdb9bef636cf496fd2e68f2f Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Tue, 3 Feb 2026 22:08:29 +0800 Subject: [PATCH] chore: bump version to 4.14.0 --- astrbot/cli/__init__.py | 2 +- astrbot/core/config/default.py | 2 +- changelogs/v4.14.0.md | 72 +++++ .../src/i18n/locales/en-US/features/cron.json | 1 + .../src/i18n/locales/zh-CN/features/cron.json | 1 + .../i18n/locales/zh-CN/features/subagent.json | 4 +- dashboard/src/views/CronJobPage.vue | 10 +- pyproject.toml | 2 +- scripts/generate_changelog.py | 253 ++++++++++++++++++ 9 files changed, 341 insertions(+), 6 deletions(-) create mode 100644 changelogs/v4.14.0.md create mode 100755 scripts/generate_changelog.py diff --git a/astrbot/cli/__init__.py b/astrbot/cli/__init__.py index 13398e442..9c8b8e07d 100644 --- a/astrbot/cli/__init__.py +++ b/astrbot/cli/__init__.py @@ -1 +1 @@ -__version__ = "4.13.2" +__version__ = "4.14.0" diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index f421d2438..774cb97ce 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -5,7 +5,7 @@ from typing import Any, TypedDict from astrbot.core.utils.astrbot_path import get_astrbot_data_path -VERSION = "4.13.2" +VERSION = "4.14.0" DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db") WEBHOOK_SUPPORTED_PLATFORMS = [ diff --git a/changelogs/v4.14.0.md b/changelogs/v4.14.0.md new file mode 100644 index 000000000..810247b61 --- /dev/null +++ b/changelogs/v4.14.0.md @@ -0,0 +1,72 @@ +## What's Changed - BIG AND BEAUTIFUL VERSION + +> 如果在之前版本使用了 Skill,这次更新之后**需要重新配置** Skill Runtime 相关选项。 + +### 新增 +- 🔥 新增未来任务系统(Future Tasks)。给 AstrBot 布置的未来任务,让 AstrBot 能够在某一时刻自动唤醒,帮你完成任务。详见 [主动任务](https://docs.astrbot.app/use/proactive-agent.html) 。(实验性) ([#4697](https://github.com/AstrBotDevs/AstrBot/issues/4831)) +- 🔥 新增子代理(SubAgent)编排器。(实验性)([#4697](https://github.com/AstrBotDevs/AstrBot/issues/4831)) +- 🔥 AstrBot 目前可以直接通过调用 tool 将图片 / 文件推送给用户,大大提高交互效果。 +- 新增 Computer Use 运行时配置,以融合 Skill 和 Sandbox 配置 ([#4831](https://github.com/AstrBotDevs/AstrBot/issues/4831)) +- 新增主题自定义功能,可设置主色与辅色 +- 支持在配置页下人格对话框的编辑人格 ([#4826](https://github.com/AstrBotDevs/AstrBot/issues/4826)) +- 支持开关 “追踪” 功能;支持在系统配置中设置是否将日志写入 log 文件 ([#4822](https://github.com/AstrBotDevs/AstrBot/issues/4822)) + +### 修复 +- ‼️ 修复 ChatUI 图片、思考等显示异常问题。 +- ‼️ 修复 Skill 上传到 Sandbox 后未自动解压导致 Agent 无法读取的问题。 +- ‼️ 修复配置特定插件集时 MCP 工具被过滤的问题 ([#4825](https://github.com/AstrBotDevs/AstrBot/issues/4825)) +- ‼️ 移除 ChatUI 自带的让 LLM 最后提出问题的 prompt ([#4824](https://github.com/AstrBotDevs/AstrBot/issues/4824)) +- ‼️ 修复 WebUI 在上传 Skill 失败后仍显示成功消息的 bug ([#4768](https://github.com/AstrBotDevs/AstrBot/issues/4768)) +- 修复 MCP 服务器无法重命名的问题 ([#4766](https://github.com/AstrBotDevs/AstrBot/issues/4766)) +- 修复插件的 tool 无法在 WebUI 管理行为中看到来源的问题 ([#4776](https://github.com/AstrBotDevs/AstrBot/issues/4776)) +- ‼️ 修复 skill-like 的 tool 模式下,调用 tool 失败的问题 ([#4775](https://github.com/AstrBotDevs/AstrBot/issues/4775)) + +### 优化 + +- WebUI 整体 UI 效果优化 +- 部分 Dialog 标题样式统一 + +## What's Changed (EN) + +### New Features +- Introduce CronJob system with one-time tasks and enhanced dashboard management +- Add theme customization with primary & secondary color options +- Add computer-use runtime config for skills sandbox execution ([#4831](https://github.com/AstrBotDevs/AstrBot/issues/4831)) +- Add edit button to persona selector dialog ([#4826](https://github.com/AstrBotDevs/AstrBot/issues/4826)) +- Add trace logging toggle and configuration UI ([#4822](https://github.com/AstrBotDevs/AstrBot/issues/4822)) +- Add proactive-messaging capability with cron-tool trigger +- Implement SubAgent orchestrator with configurable tool-management policies +- Support resolving sandbox file paths and auto-download when necessary +- Add embedded image & audio styles in MessagePartsRenderer +- Introduce i18n foundation +- Persist agent-interaction history +- Add user notifications for file-download success/removal + +### Bug Fixes +- Improve ghost-plugin detection accuracy +- Add error handling to prevent ghost-plugin crashes +- Prevent skills bundle from overwriting existing files +- Fix skills bundle unzip failure inside sandbox +- Fix MCP tools being filtered when specific plugin set configured ([#4825](https://github.com/AstrBotDevs/AstrBot/issues/4825)) +- Merge ChatUI persona pop-up into default persona ([#4824](https://github.com/AstrBotDevs/AstrBot/issues/4824)) +- Fix reasoning block style +- Add missing comma in truncate_and_compress hint +- Fix frontend still showing success message ([#4768](https://github.com/AstrBotDevs/AstrBot/issues/4768)) +- Fix unable to rename MCP server ([#4766](https://github.com/AstrBotDevs/AstrBot/issues/4766)) +- Remove leftover sandbox runtime handling in skill upload ([#4798](https://github.com/AstrBotDevs/AstrBot/issues/4798)) +- Fix handler module path construction ([#4776](https://github.com/AstrBotDevs/AstrBot/issues/4776)) +- Fix skill-like tool invocation error ([#4775](https://github.com/AstrBotDevs/AstrBot/issues/4775)) + +### Improvements +- Runtime hints & refined UI in skills management +- Performance and UX improvements on cron-job page +- General WebUI performance boost +- Group tools by plugin in dropdown +- Consistent dialog titles with padding and text styles +- Code formatting unified (ruff format) +- Bump version to 4.13.2 + +### Others +- Remove obsolete reminder code +- Extract main-agent module for better architecture +- Merge AstrBot_skill branch changes \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/cron.json b/dashboard/src/i18n/locales/en-US/features/cron.json index 5f1565812..fdb20243a 100644 --- a/dashboard/src/i18n/locales/en-US/features/cron.json +++ b/dashboard/src/i18n/locales/en-US/features/cron.json @@ -22,6 +22,7 @@ "name": "Name", "type": "Type", "cron": "Cron", + "session": "Session ID", "nextRun": "Next Run", "lastRun": "Last Run", "note": "Note", diff --git a/dashboard/src/i18n/locales/zh-CN/features/cron.json b/dashboard/src/i18n/locales/zh-CN/features/cron.json index 1c73356ac..05df8aa63 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/cron.json +++ b/dashboard/src/i18n/locales/zh-CN/features/cron.json @@ -22,6 +22,7 @@ "name": "名称", "type": "类型", "cron": "Cron", + "session": "会话 ID", "nextRun": "下一次执行", "lastRun": "最近执行", "note": "说明", diff --git a/dashboard/src/i18n/locales/zh-CN/features/subagent.json b/dashboard/src/i18n/locales/zh-CN/features/subagent.json index a54a873bd..f9df1d000 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/subagent.json +++ b/dashboard/src/i18n/locales/zh-CN/features/subagent.json @@ -35,8 +35,8 @@ "nameHint": "建议使用英文小写+下划线,且全局唯一", "providerLabel": "Chat Provider(可选)", "providerHint": "留空表示跟随全局默认 provider。", - "personaLabel": "选择 Persona", - "personaHint": "SubAgent 将直接继承所选 Persona 的系统设定与工具。", + "personaLabel": "选择人格设定", + "personaHint": "SubAgent 将直接继承所选 Persona 的系统设定与工具。在人格设定页管理和新建人格。", "descriptionLabel": "对主 LLM 的描述(用于决定是否 handoff)", "descriptionHint": "这段会作为 transfer_to_* 工具的描述给主 LLM 看,建议简短明确。" }, diff --git a/dashboard/src/views/CronJobPage.vue b/dashboard/src/views/CronJobPage.vue index 6d04d7721..1bc72b508 100644 --- a/dashboard/src/views/CronJobPage.vue +++ b/dashboard/src/views/CronJobPage.vue @@ -48,6 +48,9 @@
{{ item.timezone || tm('table.timezoneLocal') }}
+ @@ -129,6 +132,7 @@ const headers = computed(() => [ { title: tm('table.headers.name'), key: 'name', minWidth: '200px' }, { title: tm('table.headers.type'), key: 'type', width: 110 }, { title: tm('table.headers.cron'), key: 'cron_expression', minWidth: '160px' }, + { title: tm('table.headers.session'), key: 'session', minWidth: '200px' }, { title: tm('table.headers.nextRun'), key: 'next_run_time', minWidth: '160px' }, { title: tm('table.headers.lastRun'), key: 'last_run_at', minWidth: '160px' }, { title: tm('table.headers.note'), key: 'note', minWidth: '220px' }, @@ -163,7 +167,11 @@ async function loadJobs() { try { const res = await axios.get('/api/cron/jobs') if (res.data.status === 'ok') { - jobs.value = Array.isArray(res.data.data) ? res.data.data : [] + const data = Array.isArray(res.data.data) ? res.data.data : [] + jobs.value = data.map((job: any) => ({ + ...job, + session: job?.payload?.session || job?.session || '' + })) } else { toast(res.data.message || tm('messages.loadFailed'), 'error') } diff --git a/pyproject.toml b/pyproject.toml index 530bd56cd..97b3b4cf6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "AstrBot" -version = "4.13.2" +version = "4.14.0" description = "Easy-to-use multi-platform LLM chatbot and development framework" readme = "README.md" requires-python = ">=3.10" diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py new file mode 100755 index 000000000..446e0bc56 --- /dev/null +++ b/scripts/generate_changelog.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python3 +""" +Auto-generate changelog from git commits using LLM. +Usage: python scripts/generate_changelog.py [--version VERSION] +""" + +import argparse +import os +import re +import subprocess +import sys +from pathlib import Path + + +def get_latest_tag(): + """Get the latest git tag.""" + result = subprocess.run( + ["git", "describe", "--tags", "--abbrev=0"], + capture_output=True, + text=True, + check=True, + ) + return result.stdout.strip() + + +def get_commits_since_tag(tag): + """Get all commit messages since the specified tag.""" + result = subprocess.run( + ["git", "log", f"{tag}..HEAD", "--pretty=format:%H|%s|%b"], + capture_output=True, + text=True, + check=True, + ) + commits = [] + for line in result.stdout.strip().split("\n"): + if not line: + continue + parts = line.split("|", 2) + if len(parts) >= 2: + commit_hash = parts[0] + subject = parts[1] + body = parts[2] if len(parts) > 2 else "" + commits.append({"hash": commit_hash[:7], "subject": subject, "body": body}) + return commits + + +def extract_issue_number(text): + """Extract issue number from commit message.""" + # Match #1234 or (#1234) + match = re.search(r"#(\d+)", text) + return match.group(1) if match else None + + +def call_llm_for_changelog(commits, version): + """Call LLM to generate changelog from commits.""" + try: + # Try to use OpenAI API or other LLM providers + import openai + + # Build prompt + commits_text = "\n".join([f"- {c['subject']}" for c in commits]) + + prompt = f"""Based on the following git commit messages, generate a changelog document in BOTH Chinese and English. + +Commit messages: +{commits_text} + +Please organize the changes into these categories: +- 新增 (New Features) +- 修复 (Bug Fixes) +- 优化 (Improvements) +- 其他 (Others) + +Format requirements: +1. Start with Chinese version under "## What's Changed" +2. Follow with English version under "## What's Changed (EN)" +3. Use markdown format with proper bullet points +4. Keep descriptions concise and user-friendly +5. If a commit mentions an issue number (#1234), include it in the format ([#1234](https://github.com/AstrBotDevs/AstrBot/issues/1234)) + +Example format: +## What's Changed + +### 新增 +- 支持某某功能 ([#1234](https://github.com/AstrBotDevs/AstrBot/issues/1234)) + +### 修复 +- 修复某某问题 + +## What's Changed (EN) + +### New Features +- Add support for something ([#1234](https://github.com/AstrBotDevs/AstrBot/issues/1234)) + +### Bug Fixes +- Fix something +""" + + client = openai.OpenAI( + api_key=os.getenv("OPENAI_API_KEY"), + base_url=os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"), + ) + + response = client.chat.completions.create( + model=os.getenv("OPENAI_MODEL", "gpt-4"), + messages=[ + { + "role": "system", + "content": "You are a helpful assistant that generates well-structured changelogs.", + }, + {"role": "user", "content": prompt}, + ], + temperature=0.3, + ) + + return response.choices[0].message.content + + except ImportError: + print( + "Warning: openai package not installed. Install it with: pip install openai" + ) + return generate_simple_changelog(commits) + except Exception as e: + print(f"Warning: Failed to call LLM API: {e}") + print("Falling back to simple changelog generation...") + return generate_simple_changelog(commits) + + +def generate_simple_changelog(commits): + """Generate a simple changelog without LLM.""" + sections = { + "feat": ("新增", "New Features", []), + "fix": ("修复", "Bug Fixes", []), + "perf": ("优化", "Improvements", []), + "docs": ("文档", "Documentation", []), + "refactor": ("重构", "Refactoring", []), + "test": ("测试", "Tests", []), + "chore": ("其他", "Chore", []), + "other": ("其他", "Others", []), + } + + # Categorize commits by conventional commit type + for commit in commits: + subject = commit["subject"] + issue_num = extract_issue_number(subject) + issue_link = ( + f" ([#{issue_num}](https://github.com/AstrBotDevs/AstrBot/issues/{issue_num}))" + if issue_num + else "" + ) + + # Detect conventional commit type + matched = False + for prefix in ["feat", "fix", "perf", "docs", "refactor", "test", "chore"]: + if subject.lower().startswith(f"{prefix}:") or subject.lower().startswith( + f"{prefix}(" + ): + # Remove prefix for display + clean_subject = re.sub( + r"^[a-z]+(\([^)]+\))?:\s*", "", subject, flags=re.IGNORECASE + ) + sections[prefix][2].append(f"- {clean_subject}{issue_link}") + matched = True + break + + if not matched: + sections["other"][2].append(f"- {subject}{issue_link}") + + # Build Chinese version + changelog_zh = "## What's Changed\n\n" + for section_key in ["feat", "fix", "perf", "docs", "refactor", "test", "other"]: + zh_title, _, items = sections[section_key] + if items: + changelog_zh += f"### {zh_title}\n\n" + changelog_zh += "\n".join(items) + "\n\n" + + # Build English version + changelog_en = "## What's Changed (EN)\n\n" + for section_key in ["feat", "fix", "perf", "docs", "refactor", "test", "other"]: + _, en_title, items = sections[section_key] + if items: + changelog_en += f"### {en_title}\n\n" + changelog_en += "\n".join(items) + "\n\n" + + return changelog_zh + changelog_en + + +def main(): + parser = argparse.ArgumentParser(description="Generate changelog from git commits") + parser.add_argument( + "--version", help="Version number for the changelog (e.g., v4.13.3)" + ) + parser.add_argument( + "--use-llm", + action="store_true", + help="Use LLM to generate changelog (requires OpenAI API key)", + ) + args = parser.parse_args() + + # Get latest tag + try: + latest_tag = get_latest_tag() + print(f"Latest tag: {latest_tag}") + except subprocess.CalledProcessError: + print("Error: No tags found in repository") + sys.exit(1) + + # Get commits since tag + commits = get_commits_since_tag(latest_tag) + if not commits: + print(f"No commits found since {latest_tag}") + sys.exit(0) + + print(f"Found {len(commits)} commits since {latest_tag}") + + # Determine version + if args.version: + version = args.version + else: + # Auto-increment patch version + match = re.match(r"v(\d+)\.(\d+)\.(\d+)", latest_tag) + if match: + major, minor, patch = map(int, match.groups()) + version = f"v{major}.{minor}.{patch + 1}" + else: + print(f"Warning: Could not parse version from tag {latest_tag}") + version = "vX.X.X" + + print(f"Generating changelog for {version}...") + + # Generate changelog + if args.use_llm: + changelog_content = call_llm_for_changelog(commits, version) + else: + changelog_content = generate_simple_changelog(commits) + + # Save to file + changelog_dir = Path(__file__).parent.parent / "changelogs" + changelog_dir.mkdir(exist_ok=True) + changelog_file = changelog_dir / f"{version}.md" + + with open(changelog_file, "w", encoding="utf-8") as f: + f.write(changelog_content) + + print(f"\n✓ Changelog generated: {changelog_file}") + print("\nPreview:") + print("=" * 80) + print(changelog_content) + print("=" * 80) + + +if __name__ == "__main__": + main()