Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/05-more/12-damo-solver-changelog/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "达摩院AgentOS更新日志",
"position": 10
}
17 changes: 17 additions & 0 deletions docs/05-more/12-damo-solver-changelog/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "达摩院AgentOS更新日志"
description: "达摩院AgentOS版本更新历史记录"
keywords: [更新日志, 版本历史, changelog]
draft: true
---

# 达摩院AgentOS更新日志

本页记录达摩院AgentOS各版本的重要变更。

## 版本索引

<!-- 版本行由发布流程插入到表格分隔行之后:分隔行必须与 DesireCore 更新日志章节保持一致。 -->

| 版本 | 日期 | 概要 |
|------|------|------|
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "达摩院AgentOS Changelog",
"position": 10
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "达摩院AgentOS Changelog"
description: "达摩院AgentOS version changelog"
keywords: [changelog, version history, release notes]
draft: true
---

# 达摩院AgentOS Changelog

This page records important changes in each version of 达摩院AgentOS.

## Version Index

<!-- Version rows are inserted by the release workflow right after the table separator; keep the separator identical to the DesireCore changelog. -->

| Version | Date | Summary |
|---------|------|---------|
15 changes: 13 additions & 2 deletions plugins/changelog-editions.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"description": "更新日志章节配置:每个条目是一个产品发行版的独立更新日志。plugins/changelog-json-plugin.ts 按条目读取 zhSourceDir 下的 v<X.Y.Z>.md,构建时生成站点 /api/<outputFile>(客户端按发行版拉取);scripts/generate-changelog-cover.mjs <version> --edition <id> 按条目生成封面。DesireCore 发布流程只写 desirecore 章节;OEM 发布流程按 id 读取本文件定位章节目录,条目缺失时拒绝写入。新增发行版时追加条目并创建中英文两个章节目录(_category_.json 与 index.md,index.md 的表格分隔行与 desirecore 章节一致,发布流程据此插入版本行)。",
"description": "更新日志章节配置:每个条目是一个产品发行版的独立更新日志。plugins/changelog-json-plugin.ts 按条目读取 zhSourceDir 下的 v<X.Y.Z>.md,构建时生成站点 /api/<outputFile>(客户端按发行版拉取);scripts/generate-changelog-cover.mjs <version> --edition <id> 按条目生成封面。DesireCore 发布流程只写 desirecore 章节;OEM 发布流程按 id 读取本文件定位章节目录,条目缺失时拒绝写入。新增发行版时追加条目并创建中英文两个章节目录(_category_.json 与 index.md,index.md 的表格分隔行与 desirecore 章节一致,发布流程据此插入版本行)。草稿:front matter 含 draft: true 的版本页面只在开发环境可见——生产构建不生成页面、不进 /api/<outputFile>(该文件仍会生成,版本列表为空)、其封面图也不随站点发布(见插件)。OEM 发布流程写入的版本页面一律带 draft: true,OEM 章节的 index.md 也应带 draft: true 且不在其他页面加入口链接(指向草稿页面的链接在生产构建中是死链);要公开某个版本,把该页面(中英)的 draft 改为 false 或删除该行。",
"fields": {
"id": "发行版更新日志 id(desirecore 仓库 editions/<id>/edition.json#distribution.changelogEdition)",
"zhSourceDir": "中文章节目录(相对仓库根):版本页面 v<X.Y.Z>.md 与 index.md 所在目录",
"enSourceDir": "英文章节目录(相对仓库根)",
"outputFile": "构建输出到站点 api/ 下的 JSON 文件名",
"urlPrefix": "版本页面路由前缀(Docusaurus 去掉目录数字前缀后的路径);JSON 中 url = 站点地址 + urlPrefix + /v<X.Y.Z>",
"coverImageDir": "封面图片输出目录(相对仓库根)",
"coverImageDir": "封面图片输出目录(相对仓库根);草稿页面引用的封面在生产构建中会从站点输出移除",
"coverImageUrlPrefix": "版本页面中引用封面图片的路径前缀",
"coverBrandText": "封面左上角的品牌字样",
"coverWebsite": "封面右下角的网址;null 表示不显示"
Expand All @@ -22,6 +22,17 @@
"coverImageUrlPrefix": "/img/changelog",
"coverBrandText": "DESIRECORE",
"coverWebsite": "www.desirecore.cn"
},
{
"id": "damo-solver",
"zhSourceDir": "docs/05-more/12-damo-solver-changelog",
"enSourceDir": "i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog",
"outputFile": "changelog-damo-solver.json",
"urlPrefix": "/more/damo-solver-changelog",
"coverImageDir": "static/img/changelog/damo-solver",
"coverImageUrlPrefix": "/img/changelog/damo-solver",
"coverBrandText": "达摩院AgentOS",
"coverWebsite": null
}
]
}
96 changes: 86 additions & 10 deletions plugins/changelog-json-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
* 按 plugins/changelog-editions.json 的每个发行版条目读取 <zhSourceDir>/v*.md,解析 frontmatter 和 markdown sections,
* 输出结构化 JSON 到 static/api/<outputFile>(开发+构建均可用)。
* desirecore 条目的源目录、输出名与 url 前缀与改为配置之前相同(api/changelog.json);OEM 发行版条目输出 api/changelog-<id>.json。
*
* 草稿:front matter 声明 draft: true 的版本页面,与 Docusaurus 对页面的处理一致——只在开发环境可见。
* 生产构建时:
* - 草稿版本不进 JSON(条目仍输出合法的空列表:客户端拿到「没有版本」而不是 404);
* - 草稿页面(中英)引用的封面图从站点输出中移除——static/ 会原样复制进站点,不处理就能凭 URL 直接访问。
* OEM 发行版的版本页面由发布流程一律写入 draft: true;公开某个版本 = 人工把该页面(中英)的 draft 改为 false 或删除该行。
*/

import type { LoadContext, Plugin } from '@docusaurus/types'
Expand Down Expand Up @@ -37,6 +43,8 @@ interface ChangelogJson {
interface ChangelogEditionConfig {
id: string
zhSourceDir: string
/** 可选:草稿封面清理需要同时扫描英文章节;缺省只扫中文章节 */
enSourceDir?: string
outputFile: string
urlPrefix: string
}
Expand All @@ -50,6 +58,23 @@ const SECTION_MAP: Record<string, ChangelogSection['type']> = {

const SITE_URL = 'https://docs.desirecore.com'

/** 版本页面文件名(v10.0.16.md) */
const VERSION_FILE_PATTERN = /^v\d+\.\d+\.\d+\.md$/

/** 版本页面中的配图(![...](/img/changelog/v10.0.17.png) 格式);JSON 的 coverImage 与草稿封面清理共用这一条规则 */
const COVER_IMAGE_PATTERN = /!\[.*?\]\((\/img\/changelog\/[^)]+)\)/

/** 生产构建(docusaurus build)不发布草稿;开发环境(docusaurus start)草稿可见,与 Docusaurus 自身行为一致 */
function isProduction(): boolean {
return process.env.NODE_ENV === 'production'
}

/** front matter 是否声明 draft: true(Docusaurus 只认布尔 true) */
function isDraft(content: string): boolean {
const frontMatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)
return frontMatter !== null && /^draft:\s*true\s*$/m.test(frontMatter[1])
}

/**
* 从 markdown 文件内容中解析版本信息
*/
Expand All @@ -63,8 +88,8 @@ function parseChangelogMd(content: string, fileName: string, urlPrefix: string):
const dateMatch = content.match(/\*\*发布日期\*\*[::]\s*(\d{4}-\d{2}-\d{2})/)
const date = dateMatch ? dateMatch[1] : ''

// 提取配图(![...](/img/changelog/v10.0.17.png) 格式)
const imageMatch = content.match(/!\[.*?\]\((\/img\/changelog\/[^)]+)\)/)
// 提取配图
const imageMatch = content.match(COVER_IMAGE_PATTERN)
const coverImage = imageMatch ? `${SITE_URL}${imageMatch[1]}` : undefined

// 按 ## 标题分段解析
Expand Down Expand Up @@ -107,17 +132,26 @@ function parseChangelogMd(content: string, fileName: string, urlPrefix: string):
}

/**
* 生成 changelog.json 内容
* 生成 changelog.json 内容;includeDrafts 为 false 时跳过草稿版本并返回跳过的个数
*/
function generateChangelogJson(changelogDir: string, urlPrefix: string): ChangelogJson {
function generateChangelogJson(
changelogDir: string,
urlPrefix: string,
includeDrafts: boolean,
): { data: ChangelogJson; skippedDrafts: number } {
// 章节目录尚不存在时输出空列表:客户端拿到「没有版本」而不是 404
const files = fs.existsSync(changelogDir)
? fs.readdirSync(changelogDir).filter((f) => /^v\d+\.\d+\.\d+\.md$/.test(f))
? fs.readdirSync(changelogDir).filter((f) => VERSION_FILE_PATTERN.test(f))
: []

const versions: ChangelogVersion[] = []
let skippedDrafts = 0
for (const file of files) {
const content = fs.readFileSync(path.join(changelogDir, file), 'utf-8')
if (!includeDrafts && isDraft(content)) {
skippedDrafts++
continue
}
const parsed = parseChangelogMd(content, file, urlPrefix)
if (parsed) {
versions.push(parsed)
Expand All @@ -134,8 +168,11 @@ function generateChangelogJson(changelogDir: string, urlPrefix: string): Changel
})

return {
generatedAt: new Date().toISOString(),
versions,
data: {
generatedAt: new Date().toISOString(),
versions,
},
skippedDrafts,
}
}

Expand All @@ -148,6 +185,31 @@ function writeChangelogJson(targetDir: string, outputFile: string, data: Changel
fs.writeFileSync(path.join(apiDir, outputFile), JSON.stringify(data, null, 2), 'utf-8')
}

/**
* 从站点输出目录移除草稿页面引用的封面图,返回移除的张数。
* 封面路径来自页面正文,必须仍落在输出目录之内才会删除。
*/
function removeDraftCovers(outDir: string, sourceDirs: string[]): number {
const root = path.resolve(outDir)
let removed = 0
for (const dir of sourceDirs) {
if (!fs.existsSync(dir)) continue
for (const file of fs.readdirSync(dir).filter((f) => VERSION_FILE_PATTERN.test(f))) {
const content = fs.readFileSync(path.join(dir, file), 'utf-8')
if (!isDraft(content)) continue
const image = content.match(COVER_IMAGE_PATTERN)?.[1]
if (!image) continue
const target = path.resolve(root, `.${image}`)
if (!target.startsWith(root + path.sep)) continue
if (fs.existsSync(target)) {
fs.rmSync(target)
removed++
}
}
}
return removed
}

/**
* 读取并校验 plugins/changelog-editions.json;配置错误直接让构建失败
*/
Expand Down Expand Up @@ -179,11 +241,17 @@ export default function changelogJsonPlugin(context: LoadContext): Plugin {

/** 为每个发行版生成并写入 JSON */
function generateAll(targetDir: string, label: string): Record<string, ChangelogJson> {
const includeDrafts = !isProduction()
const results: Record<string, ChangelogJson> = {}
for (const edition of editions) {
const data = generateChangelogJson(path.join(context.siteDir, edition.zhSourceDir), edition.urlPrefix)
const { data, skippedDrafts } = generateChangelogJson(
path.join(context.siteDir, edition.zhSourceDir),
edition.urlPrefix,
includeDrafts,
)
writeChangelogJson(targetDir, edition.outputFile, data)
console.log(`[changelog-json-plugin] 已生成 ${label}/api/${edition.outputFile}(${data.versions.length} 个版本)`)
const skipped = skippedDrafts > 0 ? `,${skippedDrafts} 个草稿未收录` : ''
console.log(`[changelog-json-plugin] 已生成 ${label}/api/${edition.outputFile}(${data.versions.length} 个版本${skipped})`)
results[edition.id] = data
}
return results
Expand All @@ -197,9 +265,17 @@ export default function changelogJsonPlugin(context: LoadContext): Plugin {
return generateAll(path.join(context.siteDir, 'static'), 'static')
},

// 构建模式:复制到 build 输出目录
// 构建模式:复制到 build 输出目录;生产构建再移除草稿页面的封面(static/ 已被原样复制进输出目录)
async postBuild({ outDir }) {
generateAll(outDir, 'build')
if (!isProduction()) return
for (const edition of editions) {
const sourceDirs = [edition.zhSourceDir, edition.enSourceDir]
.filter((dir): dir is string => typeof dir === 'string' && dir !== '')
.map((dir) => path.join(context.siteDir, dir))
const removed = removeDraftCovers(outDir, sourceDirs)
if (removed > 0) console.log(`[changelog-json-plugin] 已从 build 移除 ${edition.id} 的草稿封面 ${removed} 张`)
}
},
}
}
Loading