chore(release): 发布 0.7.0 正式版

- 版本号 0.7.0.beta3 → 0.7.0(pyproject ×2 / package.json / docker-compose ×2 / uv.lock ×2 / README ×2 / quick-start / 文档首页)
- changelog 标题更新为 v0.7.0 (2026-06-13),修正版本号描述
- quick-start 版本表更新为当前稳定版
- 修复 package import 排序,同步前端 prettier 格式化
This commit is contained in:
Wenjie Zhang 2026-06-13 01:02:43 +08:00
parent 7f454e64e6
commit a8a933d3dc
21 changed files with 63 additions and 43 deletions

View File

@ -54,7 +54,7 @@ Navigation: [Introduction](https://xerrors.github.io/Yuxi/) [Quick Start](ht
**1. Clone and initialize** **1. Clone and initialize**
```bash ```bash
git clone --branch v0.7.0.beta3 --depth 1 https://github.com/xerrors/Yuxi.git git clone --branch v0.7.0 --depth 1 https://github.com/xerrors/Yuxi.git
cd Yuxi cd Yuxi
# Linux/macOS # Linux/macOS

View File

@ -43,7 +43,7 @@
**1. 克隆代码并初始化** **1. 克隆代码并初始化**
```bash ```bash
git clone --branch v0.7.0.beta3 --depth 1 https://github.com/xerrors/Yuxi.git git clone --branch v0.7.0 --depth 1 https://github.com/xerrors/Yuxi.git
cd Yuxi cd Yuxi
# Linux/macOS # Linux/macOS

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "yuxi" name = "yuxi"
version = "0.7.0.beta3" version = "0.7.0"
description = "Yuxi 智能知识库与知识图谱平台核心后端包" description = "Yuxi 智能知识库与知识图谱平台核心后端包"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12,<3.14" requires-python = ">=3.12,<3.14"

View File

@ -5264,7 +5264,7 @@ wheels = [
[[package]] [[package]]
name = "yuxi" name = "yuxi"
version = "0.7.0.beta3" version = "0.7.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "agent-sandbox" }, { name = "agent-sandbox" },

View File

@ -6,7 +6,6 @@ from yuxi.models.providers.cache import model_cache
from yuxi.utils import get_docker_safe_url from yuxi.utils import get_docker_safe_url
from yuxi.utils.logging_config import logger from yuxi.utils.logging_config import logger
# 这些提供商的 OpenAI 兼容流式接口,在 LangGraph v3 事件流累积工具调用时会丢失 # 这些提供商的 OpenAI 兼容流式接口,在 LangGraph v3 事件流累积工具调用时会丢失
# tool_call 的关键字段siliconflow MiniMax 丢 name、alibaba 百炼丢 id空值会被写入 # tool_call 的关键字段siliconflow MiniMax 丢 name、alibaba 百炼丢 id空值会被写入
# checkpoint导致工具结果无法按 tool_call_id 关联、工具状态永远停留在“进行中”。 # checkpoint导致工具结果无法按 tool_call_id 关联、工具状态永远停留在“进行中”。

View File

@ -1,6 +1,6 @@
[project] [project]
name = "yuxi-workspace" name = "yuxi-workspace"
version = "0.7.0.beta3" version = "0.7.0"
description = "基于大模型的智能知识库与知识图谱智能体开发平台,融合了 RAG 技术与知识图谱技术,基于 LangGraph v1 + Vue.js + FastAPI + LightRAG 架构构建" description = "基于大模型的智能知识库与知识图谱智能体开发平台,融合了 RAG 技术与知识图谱技术,基于 LangGraph v1 + Vue.js + FastAPI + LightRAG 架构构建"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12,<3.14" requires-python = ">=3.12,<3.14"

View File

@ -5489,7 +5489,7 @@ wheels = [
[[package]] [[package]]
name = "yuxi" name = "yuxi"
version = "0.7.0.beta3" version = "0.7.0"
source = { editable = "package" } source = { editable = "package" }
dependencies = [ dependencies = [
{ name = "agent-sandbox" }, { name = "agent-sandbox" },
@ -5646,7 +5646,7 @@ requires-dist = [
[[package]] [[package]]
name = "yuxi-workspace" name = "yuxi-workspace"
version = "0.7.0.beta3" version = "0.7.0"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "arq" }, { name = "arq" },

View File

@ -30,7 +30,7 @@ services:
build: build:
context: . context: .
dockerfile: docker/api.Dockerfile dockerfile: docker/api.Dockerfile
image: yuxi-api:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-api:${YUXI_VERSION:-0.7.0}
container_name: api-prod container_name: api-prod
working_dir: /app working_dir: /app
networks: networks:
@ -68,7 +68,7 @@ services:
build: build:
context: . context: .
dockerfile: docker/api.Dockerfile dockerfile: docker/api.Dockerfile
image: yuxi-api:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-api:${YUXI_VERSION:-0.7.0}
container_name: worker-prod container_name: worker-prod
working_dir: /app working_dir: /app
networks: networks:
@ -145,7 +145,7 @@ services:
context: . context: .
dockerfile: docker/web.Dockerfile dockerfile: docker/web.Dockerfile
target: production target: production
image: yuxi-web:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-web:${YUXI_VERSION:-0.7.0}
container_name: web-prod container_name: web-prod
ports: ports:
- "80:80" - "80:80"

View File

@ -38,7 +38,7 @@ services:
build: build:
context: . context: .
dockerfile: docker/api.Dockerfile dockerfile: docker/api.Dockerfile
image: yuxi-api:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-api:${YUXI_VERSION:-0.7.0}
container_name: api-dev container_name: api-dev
working_dir: /app working_dir: /app
volumes: volumes:
@ -86,7 +86,7 @@ services:
build: build:
context: . context: .
dockerfile: docker/api.Dockerfile dockerfile: docker/api.Dockerfile
image: yuxi-api:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-api:${YUXI_VERSION:-0.7.0}
container_name: worker-dev container_name: worker-dev
working_dir: /app working_dir: /app
volumes: volumes:
@ -125,7 +125,7 @@ services:
build: build:
context: ./docker/sandbox_provisioner context: ./docker/sandbox_provisioner
dockerfile: Dockerfile dockerfile: Dockerfile
image: yuxi-sandbox-provisioner:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-sandbox-provisioner:${YUXI_VERSION:-0.7.0}
container_name: sandbox-provisioner container_name: sandbox-provisioner
volumes: volumes:
- ./docker/volumes/yuxi:/app/saves - ./docker/volumes/yuxi:/app/saves
@ -179,7 +179,7 @@ services:
context: . context: .
dockerfile: docker/web.Dockerfile dockerfile: docker/web.Dockerfile
target: development target: development
image: yuxi-web:${YUXI_VERSION:-0.7.0.beta3} image: yuxi-web:${YUXI_VERSION:-0.7.0}
container_name: web-dev container_name: web-dev
volumes: volumes:
- ./web/src:/app/src - ./web/src:/app/src

View File

@ -453,7 +453,7 @@ const vReveal = {
</header> </header>
<div v-reveal class="yx-quick"> <div v-reveal class="yx-quick">
<pre class="yx-code"><code><span class="yx-c-cmt"># 1. 克隆并初始化</span> <pre class="yx-code"><code><span class="yx-c-cmt"># 1. 克隆并初始化</span>
git clone --branch v0.7.0.beta3 --depth 1 https://github.com/xerrors/Yuxi.git git clone --branch v0.7.0 --depth 1 https://github.com/xerrors/Yuxi.git
cd Yuxi && ./scripts/init.sh cd Yuxi && ./scripts/init.sh
<span class="yx-c-cmt"># 2. 使用 Docker 启动</span> <span class="yx-c-cmt"># 2. 使用 Docker 启动</span>

View File

@ -4,7 +4,7 @@
同一版本的多次功能更新时,应以功能为单位进行更新,比如之前添加了 A 功能的更新,在后续的更新中修复了因 A 功能引入的 bug那么这个修复说明应该和 A 功能描述放在一起,而不是新增一条修复记录,功能更新同理。 同一版本的多次功能更新时,应以功能为单位进行更新,比如之前添加了 A 功能的更新,在后续的更新中修复了因 A 功能引入的 bug那么这个修复说明应该和 A 功能描述放在一起,而不是新增一条修复记录,功能更新同理。
## v0.7.0 (开发中) ## v0.7.0 (2026-06-13)
### 破坏性变更 ### 破坏性变更
@ -18,7 +18,7 @@
### 开发记录 ### 开发记录
- 发布版本号更新至 `0.7.0.beta2`,同步 package、Docker 镜像标签与快速开始分支引用。 - 发布版本号更新至 `0.7.0`,同步 package、Docker 镜像标签与快速开始分支引用。
- 新增内置「深度研究」多智能体:编排器 Agent`deep-research`ChatbotAgent 后端)负责澄清、拆解、并行调度子智能体与综合成稿,配套两个子智能体 `research-explorer`(围绕单个子问题多轮检索网页/知识库并返回带引用发现)和 `fact-verifier`(对抗式核验关键论断、标注冲突与置信度);完整研究方法论沉淀为新增内置 Skill `deep-research`(依赖 `tavily_search`),编排器运行时读取并据此调度。三者随 `lifespan` 启动通过 `AgentRepository.ensure_deep_research_agents` 幂等落库(已存在不覆盖管理员修改)。 - 新增内置「深度研究」多智能体:编排器 Agent`deep-research`ChatbotAgent 后端)负责澄清、拆解、并行调度子智能体与综合成稿,配套两个子智能体 `research-explorer`(围绕单个子问题多轮检索网页/知识库并返回带引用发现)和 `fact-verifier`(对抗式核验关键论断、标注冲突与置信度);完整研究方法论沉淀为新增内置 Skill `deep-research`(依赖 `tavily_search`),编排器运行时读取并据此调度。三者随 `lifespan` 启动通过 `AgentRepository.ensure_deep_research_agents` 幂等落库(已存在不覆盖管理员修改)。
- 新增内置 `general-purpose` 通用任务子智能体:使用 `SubAgentBackend` 与空运行配置,作为 `task` 工具的通用委派目标,由启动初始化自动写入数据库。 - 新增内置 `general-purpose` 通用任务子智能体:使用 `SubAgentBackend` 与空运行配置,作为 `task` 工具的通用委派目标,由启动初始化自动写入数据库。
- 收敛 MCP 创建与编辑入口:前端移除整段配置文本入口和模式切换器,仅保留表单字段提交;后端 MCP 创建/更新请求拒绝额外配置字段,避免绕过表单约束。 - 收敛 MCP 创建与编辑入口:前端移除整段配置文本入口和模式切换器,仅保留表单字段提交;后端 MCP 创建/更新请求拒绝额外配置字段,避免绕过表单约束。

View File

@ -20,7 +20,7 @@
```bash ```bash
# 克隆最新版本 # 克隆最新版本
git clone --branch v0.7.0.beta3 --depth 1 https://github.com/xerrors/Yuxi.git git clone --branch v0.7.0 --depth 1 https://github.com/xerrors/Yuxi.git
cd Yuxi cd Yuxi
``` ```
@ -28,7 +28,7 @@ cd Yuxi
| 版本 | 适用场景 | | 版本 | 适用场景 |
|------|----------| |------|----------|
| v0.7.x | 当前开发版本,包含最新特性 | | v0.7.0 | 当前稳定版本,推荐生产使用 |
| main | 开发版本,包含最新特性(可能不稳定) | | main | 开发版本,包含最新特性(可能不稳定) |
### 步骤二:配置环境变量 ### 步骤二:配置环境变量

View File

@ -1,6 +1,6 @@
{ {
"name": "yuxi-web", "name": "yuxi-web",
"version": "0.7.0.beta3", "version": "0.7.0",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@ -1285,7 +1285,8 @@ const historyConversations = computed(() => {
function getMessageRequestId(message) { function getMessageRequestId(message) {
const metadataRequestId = message?.extra_metadata?.request_id const metadataRequestId = message?.extra_metadata?.request_id
if (typeof metadataRequestId === 'string' && metadataRequestId.trim()) return metadataRequestId.trim() if (typeof metadataRequestId === 'string' && metadataRequestId.trim())
return metadataRequestId.trim()
if (message?.type === 'human' && typeof message.id === 'string' && message.id.trim()) { if (message?.type === 'human' && typeof message.id === 'string' && message.id.trim()) {
return message.id.trim() return message.id.trim()
} }
@ -1341,10 +1342,8 @@ function mergeOngoingUserMessageIntoHistory(historyConvs, ongoingMessages) {
const conversations = computed(() => { const conversations = computed(() => {
const historyConvs = historyConversations.value const historyConvs = historyConversations.value
const { const { historyConvs: mergedHistoryConvs, ongoingMessages: mergedOngoingMessages } =
historyConvs: mergedHistoryConvs, mergeOngoingUserMessageIntoHistory(historyConvs, onGoingConvMessages.value)
ongoingMessages: mergedOngoingMessages
} = mergeOngoingUserMessageIntoHistory(historyConvs, onGoingConvMessages.value)
// 线 // 线
if (mergedOngoingMessages.length > 0) { if (mergedOngoingMessages.length > 0) {

View File

@ -1,9 +1,9 @@
<template> <template>
<div <div v-if="message.type === 'human' && message.image_content" class="message-image">
v-if="message.type === 'human' && message.image_content" <img
class="message-image" :src="`data:${messageImageMimeType};base64,${message.image_content}`"
> alt="用户上传的图片"
<img :src="`data:${messageImageMimeType};base64,${message.image_content}`" alt="用户上传的图片" /> />
</div> </div>
<div <div
class="message-box" class="message-box"

View File

@ -82,7 +82,9 @@ const avatarSizeStyle = computed(() => {
} }
}) })
const resolvedAlt = computed(() => props.alt || props.name || (props.kind === 'agent' ? '智能体头像' : '用户头像')) const resolvedAlt = computed(
() => props.alt || props.name || (props.kind === 'agent' ? '智能体头像' : '用户头像')
)
const handleImageError = () => { const handleImageError = () => {
if (failedImageCount.value < imageCandidates.value.length) { if (failedImageCount.value < imageCandidates.value.length) {

View File

@ -221,7 +221,8 @@ const loadFeedbacks = async () => {
} }
} }
const getFeedbackDefaultAvatarSrc = (feedback) => (feedback.uid ? generatePixelAvatar(feedback.uid) : '') const getFeedbackDefaultAvatarSrc = (feedback) =>
feedback.uid ? generatePixelAvatar(feedback.uid) : ''
// //
const formatFullDate = (dateString) => formatFullDateTime(dateString) const formatFullDate = (dateString) => formatFullDateTime(dateString)

View File

@ -59,7 +59,11 @@ const run = () => {
} }
{ {
assert.equal(getAvatarInitials('张三丰', 'user'), '张三', 'Chinese initials use first two chars') assert.equal(
getAvatarInitials('张三丰', 'user'),
'张三',
'Chinese initials use first two chars'
)
assert.equal(getAvatarInitials('Alice', 'user'), 'Al', 'ASCII initials use first two chars') assert.equal(getAvatarInitials('Alice', 'user'), 'Al', 'ASCII initials use first two chars')
assert.equal(getAvatarInitials('', 'user'), '用户', 'User fallback should be localized') assert.equal(getAvatarInitials('', 'user'), '用户', 'User fallback should be localized')
assert.equal(getAvatarInitials('', 'agent'), '智能', 'Agent fallback should be localized') assert.equal(getAvatarInitials('', 'agent'), '智能', 'Agent fallback should be localized')

View File

@ -6,7 +6,13 @@ const AUTO_START_KEY = 'oidc_auto_start_attempted'
// - 不能以 // 或 \ 开头(协议相对 URL / 非标准路径) // - 不能以 // 或 \ 开头(协议相对 URL / 非标准路径)
// 不合法或缺失时返回 "/" // 不合法或缺失时返回 "/"
export function sanitizeRedirect(value) { export function sanitizeRedirect(value) {
if (typeof value === 'string' && value.length > 0 && value[0] === '/' && value[1] !== '/' && value[1] !== '\\') { if (
typeof value === 'string' &&
value.length > 0 &&
value[0] === '/' &&
value[1] !== '/' &&
value[1] !== '\\'
) {
return value return value
} }
return '/' return '/'

View File

@ -2,10 +2,22 @@ const DICEBEAR_GLYPHS_AVATAR_BASE_URL = 'https://api.dicebear.com/10.x/glyphs/sv
export const AVATAR_BACKGROUND_TOKENS = [ export const AVATAR_BACKGROUND_TOKENS = [
{ background: 'linear-gradient(135deg, var(--main-600), var(--color-info-500))', color: '#fff' }, { background: 'linear-gradient(135deg, var(--main-600), var(--color-info-500))', color: '#fff' },
{ background: 'linear-gradient(135deg, var(--chart-palette-5), var(--chart-palette-9))', color: '#fff' }, {
{ background: 'linear-gradient(135deg, var(--chart-palette-7), var(--chart-palette-3))', color: '#fff' }, background: 'linear-gradient(135deg, var(--chart-palette-5), var(--chart-palette-9))',
{ background: 'linear-gradient(135deg, var(--color-accent-500), var(--chart-palette-6))', color: '#fff' }, color: '#fff'
{ background: 'linear-gradient(135deg, var(--chart-palette-4), var(--color-error-500))', color: '#fff' } },
{
background: 'linear-gradient(135deg, var(--chart-palette-7), var(--chart-palette-3))',
color: '#fff'
},
{
background: 'linear-gradient(135deg, var(--color-accent-500), var(--chart-palette-6))',
color: '#fff'
},
{
background: 'linear-gradient(135deg, var(--chart-palette-4), var(--color-error-500))',
color: '#fff'
}
] ]
const normalizeSeed = (id) => { const normalizeSeed = (id) => {

View File

@ -642,10 +642,7 @@ onMounted(async () => {
// OIDC OIDC // OIDC OIDC
const config = await checkOIDCConfig() const config = await checkOIDCConfig()
if (config && config.enabled) { if (config && config.enabled) {
const autoStarted = await tryAutoStartOIDC( const autoStarted = await tryAutoStartOIDC(async () => await authApi.getOIDCLoginUrl(), config)
async () => await authApi.getOIDCLoginUrl(),
config
)
// OIDC // OIDC
if (autoStarted) return if (autoStarted) return
} }