|
|
@@ -11,7 +11,7 @@
|
|
|
export type DocsLocale = 'root' | 'en'
|
|
|
|
|
|
/** Sidebar collection rendered for one locale and top-level module. */
|
|
|
-type DocsSidebar =
|
|
|
+export type DocsSidebar =
|
|
|
| 'zh-guide'
|
|
|
| 'zh-develop'
|
|
|
| 'zh-reference'
|
|
|
@@ -133,9 +133,9 @@ const homeAndGuide = pairedPages([
|
|
|
{
|
|
|
source: 'docs/user/guide/python-sdk.md',
|
|
|
route: 'guide/python-sdk.md',
|
|
|
- label: { root: 'Python SDK', en: 'Python SDK' },
|
|
|
+ label: { root: 'Python', en: 'Python' },
|
|
|
sidebar: { root: 'zh-guide', en: 'en-guide' },
|
|
|
- section: { root: '其他接口', en: 'Other interfaces' },
|
|
|
+ section: { root: 'SDK', en: 'SDK' },
|
|
|
order: 1,
|
|
|
},
|
|
|
])
|
|
|
@@ -144,7 +144,7 @@ const develop = pairedPages([
|
|
|
{
|
|
|
source: 'docs/user/develop/basic/index.md',
|
|
|
route: 'develop/basic/index.md',
|
|
|
- label: { root: '第一个插件', en: 'First plugin' },
|
|
|
+ label: { root: '第一个 Harness 插件', en: 'Your first Harness plugin' },
|
|
|
sidebar: { root: 'zh-develop', en: 'en-develop' },
|
|
|
section: { root: '基础', en: 'Basics' },
|
|
|
order: 1,
|
|
|
@@ -219,7 +219,7 @@ const develop = pairedPages([
|
|
|
])
|
|
|
|
|
|
const cordisTutorial = pairedPages(([
|
|
|
- ['index.md', 'Cordis 教程', 'Cordis tutorial'],
|
|
|
+ ['index.md', '总览', 'Overview'],
|
|
|
['01-first-plugin.md', '1. 第一个插件', '1. Your first plugin'],
|
|
|
['02-lifecycle-and-effects.md', '2. 生命周期与副作用', '2. Lifecycle and effects'],
|
|
|
['03-services.md', '3. 服务', '3. Services'],
|
|
|
@@ -232,7 +232,7 @@ const cordisTutorial = pairedPages(([
|
|
|
route: `develop/cordis-tutorial/${file}`,
|
|
|
label: { root: rootLabel, en: enLabel },
|
|
|
sidebar: { root: 'zh-develop', en: 'en-develop' },
|
|
|
- section: { root: 'Cordis 教程', en: 'Cordis tutorial' },
|
|
|
+ section: { root: 'Cordis 框架教程', en: 'Cordis framework tutorial' },
|
|
|
order,
|
|
|
...(file === 'index.md' ? { sourceAliases: ['docs/cordis-tutorial'] } : {}),
|
|
|
})))
|
|
|
@@ -248,55 +248,84 @@ const cordisPrimerReference = pairedPages([
|
|
|
},
|
|
|
])
|
|
|
|
|
|
-const subsystemsReference = pairedPages(([
|
|
|
- ['README.md', '子系统', 'Subsystems', 0],
|
|
|
- ['core.md', '核心', 'Core', 1],
|
|
|
- ['scope.md', '作用域', 'Scopes', 2],
|
|
|
- ['typert.md', 'TypeRT', 'TypeRT', 39],
|
|
|
- ['session.md', '会话', 'Sessions', 3],
|
|
|
- ['session-query.md', '会话查询', 'Session query', 4],
|
|
|
- ['session-reference.md', '会话引用', 'Session references', 5],
|
|
|
- ['session-title.md', '会话标题', 'Session titles', 6],
|
|
|
- ['settings.md', '用户设置', 'User settings', 7],
|
|
|
- ['credentials.md', '用户凭据', 'User credentials', 8],
|
|
|
- ['system-prompt.md', '系统提示词', 'System prompts', 9],
|
|
|
- ['tools.md', '工具', 'Tools', 10],
|
|
|
- ['llm-streaming.md', 'LLM 流式响应', 'LLM streaming', 11],
|
|
|
- ['token-meter.md', 'Token 计量', 'Token metering', 12],
|
|
|
- ['bash.md', 'Bash 执行', 'Bash execution', 13],
|
|
|
- ['subprocess.md', '子进程', 'Subprocesses', 14],
|
|
|
- ['tasks.md', '后台任务', 'Background tasks', 15],
|
|
|
- ['filesystem.md', '文件系统', 'Filesystem', 16],
|
|
|
- ['lsp.md', 'LSP 导航', 'LSP navigation', 17],
|
|
|
- ['code-runtime.md', '代码运行时', 'Code runtime', 18],
|
|
|
- ['compaction.md', '上下文压缩', 'Compaction', 19],
|
|
|
- ['subagent.md', '子代理', 'Subagents', 20],
|
|
|
- ['workflow.md', '工作流', 'Workflows', 21],
|
|
|
- ['skills.md', '技能', 'Skills', 22],
|
|
|
- ['approval.md', '审批', 'Approvals', 23],
|
|
|
- ['permission.md', '权限预设', 'Permission presets', 24],
|
|
|
- ['plan.md', '计划模式', 'Plan mode', 25],
|
|
|
- ['user-interaction.md', '用户交互', 'User interaction', 26],
|
|
|
- ['sandbox.md', '沙箱', 'Sandboxing', 27],
|
|
|
- ['web.md', 'Web 访问', 'Web access', 28],
|
|
|
- ['spill.md', 'Spill 存储', 'Spill storage', 29],
|
|
|
- ['persistence.md', '会话持久化', 'Session persistence', 30],
|
|
|
- ['storage.md', '存储', 'Storage', 31],
|
|
|
- ['workspace.md', '工作区', 'Workspaces', 32],
|
|
|
- ['http-server.md', 'HTTP 服务器', 'HTTP server', 33],
|
|
|
- ['client-modules.md', '客户端模块', 'Client modules', 34],
|
|
|
- ['invariants.md', '运行时不变式', 'Runtime invariants', 36],
|
|
|
- ['session-projection.md', '会话投影', 'Session projections', 37],
|
|
|
- ['telemetry.md', '遥测', 'Telemetry', 38],
|
|
|
-] as const).map(([file, rootLabel, enLabel, order]): PairedPage => ({
|
|
|
- source: `docs/subsystems/${file}`,
|
|
|
- route: file === 'README.md' ? 'reference/subsystems/index.md' : `reference/subsystems/${file}`,
|
|
|
- label: { root: rootLabel, en: enLabel },
|
|
|
- sidebar: { root: 'zh-reference', en: 'en-reference' },
|
|
|
- section: { root: '子系统', en: 'Subsystems' },
|
|
|
- order,
|
|
|
- ...(file === 'README.md' ? { sourceAliases: ['docs/subsystems'] } : {}),
|
|
|
-})))
|
|
|
+/**
|
|
|
+ * Subsystem pages grouped by the concern they document, as `[Chinese section,
|
|
|
+ * English section, pages]`. One flat list of every subsystem pushed the rest of
|
|
|
+ * the reference sidebar below the fold.
|
|
|
+ */
|
|
|
+const subsystemGroups = [
|
|
|
+ ['总览', 'Overview', [
|
|
|
+ ['README.md', '子系统', 'Subsystems'],
|
|
|
+ ]],
|
|
|
+ ['内核与作用域', 'Core and scopes', [
|
|
|
+ ['core.md', '核心', 'Core'],
|
|
|
+ ['scope.md', '作用域', 'Scopes'],
|
|
|
+ ['invariants.md', '运行时不变式', 'Runtime invariants'],
|
|
|
+ ]],
|
|
|
+ ['会话与持久化', 'Sessions and persistence', [
|
|
|
+ ['session.md', '会话', 'Sessions'],
|
|
|
+ ['session-query.md', '会话查询', 'Session query'],
|
|
|
+ ['session-reference.md', '会话引用', 'Session references'],
|
|
|
+ ['session-title.md', '会话标题', 'Session titles'],
|
|
|
+ ['session-projection.md', '会话投影', 'Session projections'],
|
|
|
+ ['persistence.md', '会话持久化', 'Session persistence'],
|
|
|
+ ['spill.md', 'Spill 存储', 'Spill storage'],
|
|
|
+ ['telemetry.md', '遥测', 'Telemetry'],
|
|
|
+ ]],
|
|
|
+ ['模型与上下文', 'Model and context', [
|
|
|
+ ['llm-streaming.md', 'LLM 流式响应', 'LLM streaming'],
|
|
|
+ ['token-meter.md', 'Token 计量', 'Token metering'],
|
|
|
+ ['system-prompt.md', '系统提示词', 'System prompts'],
|
|
|
+ ['compaction.md', '上下文压缩', 'Compaction'],
|
|
|
+ ]],
|
|
|
+ ['执行与工具', 'Execution and tools', [
|
|
|
+ ['tools.md', '工具', 'Tools'],
|
|
|
+ ['bash.md', 'Bash 执行', 'Bash execution'],
|
|
|
+ ['subprocess.md', '子进程', 'Subprocesses'],
|
|
|
+ ['pty.md', 'PTY 会话', 'PTY sessions'],
|
|
|
+ ['tasks.md', '后台任务', 'Background tasks'],
|
|
|
+ ['filesystem.md', '文件系统', 'Filesystem'],
|
|
|
+ ['lsp.md', 'LSP 导航', 'LSP navigation'],
|
|
|
+ ['code-runtime.md', '代码运行时', 'Code runtime'],
|
|
|
+ ['web.md', 'Web 访问', 'Web access'],
|
|
|
+ ['skills.md', '技能', 'Skills'],
|
|
|
+ ['workflow.md', '工作流', 'Workflows'],
|
|
|
+ ['subagent.md', '子代理', 'Subagents'],
|
|
|
+ ]],
|
|
|
+ ['策略与交互', 'Policy and interaction', [
|
|
|
+ ['approval.md', '审批', 'Approvals'],
|
|
|
+ ['permission.md', '权限预设', 'Permission presets'],
|
|
|
+ ['sandbox.md', '沙箱', 'Sandboxing'],
|
|
|
+ ['plan.md', '计划模式', 'Plan mode'],
|
|
|
+ ['user-interaction.md', '用户交互', 'User interaction'],
|
|
|
+ ['commands.md', '命令', 'Human commands'],
|
|
|
+ ['goal.md', '目标', 'Goals'],
|
|
|
+ ['schedule.md', '定时提醒', 'Scheduled reminders'],
|
|
|
+ ]],
|
|
|
+ ['平台与接入', 'Platform and access', [
|
|
|
+ ['http-server.md', 'HTTP 服务器', 'HTTP server'],
|
|
|
+ ['typert.md', 'TypeRT', 'TypeRT'],
|
|
|
+ ['client-modules.md', '客户端模块', 'Client modules'],
|
|
|
+ ['storage.md', '存储', 'Storage'],
|
|
|
+ ['workspace.md', '工作区', 'Workspaces'],
|
|
|
+ ['settings.md', '用户设置', 'User settings'],
|
|
|
+ ['credentials.md', '用户凭据', 'User credentials'],
|
|
|
+ ]],
|
|
|
+] as const
|
|
|
+
|
|
|
+const subsystemsReference = subsystemGroups.flatMap(([rootSection, enSection, files]) => pairedPages(
|
|
|
+ files.map(([file, rootLabel, enLabel], order): PairedPage => ({
|
|
|
+ source: `docs/subsystems/${file}`,
|
|
|
+ route: file === 'README.md' ? 'reference/subsystems/index.md' : `reference/subsystems/${file}`,
|
|
|
+ label: { root: rootLabel, en: enLabel },
|
|
|
+ sidebar: { root: 'zh-reference', en: 'en-reference' },
|
|
|
+ section: { root: rootSection, en: enSection },
|
|
|
+ order,
|
|
|
+ // Subsystem pages carry long third-level sections a two-level outline reaches.
|
|
|
+ outline: [2, 3],
|
|
|
+ ...(file === 'README.md' ? { sourceAliases: ['docs/subsystems'] } : {}),
|
|
|
+ })),
|
|
|
+))
|
|
|
|
|
|
const reference = [
|
|
|
...pairedPages(([
|
|
|
@@ -359,19 +388,6 @@ const reference = [
|
|
|
section: { root: 'Cordis API', en: 'Cordis Core API' },
|
|
|
order: order + 5,
|
|
|
}))),
|
|
|
- ...pairedPages(([
|
|
|
- ['goal.md', '目标', 'Goals', 14],
|
|
|
- ['schedule.md', '定时提醒', 'Scheduled reminders', 15],
|
|
|
- ['pty.md', 'PTY 会话', 'PTY sessions', 26],
|
|
|
- ['commands.md', '命令', 'Human commands', 38],
|
|
|
- ] as const).map(([file, rootLabel, enLabel, order]): PairedPage => ({
|
|
|
- source: `docs/subsystems/${file}`,
|
|
|
- route: `reference/subsystems/${file}`,
|
|
|
- label: { root: rootLabel, en: enLabel },
|
|
|
- sidebar: { root: 'zh-reference', en: 'en-reference' },
|
|
|
- section: { root: '子系统', en: 'Subsystems' },
|
|
|
- order,
|
|
|
- }))),
|
|
|
...pairedPages(([
|
|
|
['adding-a-package.md', '新增 Package', 'Adding a package'],
|
|
|
['adding-a-tool.md', '新增 Tool', 'Adding a tool'],
|
|
|
@@ -395,6 +411,64 @@ const reference = [
|
|
|
}]),
|
|
|
]
|
|
|
|
|
|
+/** A sidebar group, matched to pages by `label`. */
|
|
|
+export interface DocsSection {
|
|
|
+ /** Group heading, equal to the `section` field of every page it holds. */
|
|
|
+ label: string
|
|
|
+ /** Render the group collapsed until it holds the page being read. */
|
|
|
+ collapsed?: boolean
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Every sidebar group, in the order its locale renders it.
|
|
|
+ *
|
|
|
+ * The subsystem groups collapse because together they outnumber the rest of the
|
|
|
+ * reference sidebar; expanded, they push every other group below the fold.
|
|
|
+ */
|
|
|
+const sections: Record<DocsLocale, readonly DocsSection[]> = {
|
|
|
+ root: [
|
|
|
+ { label: '入门' }, { label: 'SDK' },
|
|
|
+ { label: '基础' }, { label: '框架能力' }, { label: '实战' }, { label: 'Cordis 框架教程' },
|
|
|
+ { label: '概念' }, { label: '生成参考' }, { label: 'Cordis API' }, { label: '开发手册' },
|
|
|
+ { label: '总览' },
|
|
|
+ { label: '内核与作用域', collapsed: true },
|
|
|
+ { label: '会话与持久化', collapsed: true },
|
|
|
+ { label: '模型与上下文', collapsed: true },
|
|
|
+ { label: '执行与工具', collapsed: true },
|
|
|
+ { label: '策略与交互', collapsed: true },
|
|
|
+ { label: '平台与接入', collapsed: true },
|
|
|
+ ],
|
|
|
+ en: [
|
|
|
+ { label: 'Guide' }, { label: 'SDK' },
|
|
|
+ { label: 'Basics' }, { label: 'Framework' }, { label: 'Practice' }, { label: 'Cordis framework tutorial' },
|
|
|
+ { label: 'Concepts' }, { label: 'Generated reference' }, { label: 'Cordis Core API' }, { label: 'Cookbook' },
|
|
|
+ { label: 'Overview' },
|
|
|
+ { label: 'Core and scopes', collapsed: true },
|
|
|
+ { label: 'Sessions and persistence', collapsed: true },
|
|
|
+ { label: 'Model and context', collapsed: true },
|
|
|
+ { label: 'Execution and tools', collapsed: true },
|
|
|
+ { label: 'Policy and interaction', collapsed: true },
|
|
|
+ { label: 'Platform and access', collapsed: true },
|
|
|
+ ],
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Placement and collapse behavior of one sidebar group.
|
|
|
+ *
|
|
|
+ * @param locale - Route tree whose sidebar is being built.
|
|
|
+ * @param label - Section label carried by the pages in the group.
|
|
|
+ * @returns The declared group, plus its zero-based position in the locale.
|
|
|
+ * @throws When the locale declares no placement for the label. Ranking by list
|
|
|
+ * membership alone would sort an undeclared group silently ahead of every
|
|
|
+ * declared one.
|
|
|
+ */
|
|
|
+export function sectionSpec(locale: DocsLocale, label: string): DocsSection & { index: number } {
|
|
|
+ const declared = sections[locale]
|
|
|
+ const section = declared.find(candidate => candidate.label === label)
|
|
|
+ if (section === undefined) throw new Error(`Sidebar section "${label}" has no placement in the ${locale} locale.`)
|
|
|
+ return { ...section, index: declared.indexOf(section) }
|
|
|
+}
|
|
|
+
|
|
|
/** Every canonical page published by the documentation website. */
|
|
|
export const docsPages: DocsPage[] = [
|
|
|
...homeAndGuide,
|
|
|
@@ -404,3 +478,47 @@ export const docsPages: DocsPage[] = [
|
|
|
...subsystemsReference,
|
|
|
...reference,
|
|
|
]
|
|
|
+
|
|
|
+/**
|
|
|
+ * Pages of one sidebar collection, in the order the sidebar lists them.
|
|
|
+ *
|
|
|
+ * @param locale - Route tree whose sidebar is being built.
|
|
|
+ * @param collection - Sidebar collection to read.
|
|
|
+ * @returns The collection's pages, ordered by section placement then by `order`.
|
|
|
+ */
|
|
|
+export function orderedPages(locale: DocsLocale, collection: DocsSidebar): DocsPage[] {
|
|
|
+ return docsPages
|
|
|
+ .filter(page => page.locale === locale && page.sidebar === collection)
|
|
|
+ .sort((left, right) => (
|
|
|
+ sectionSpec(locale, left.section).index - sectionSpec(locale, right.section).index
|
|
|
+ || left.order - right.order
|
|
|
+ ))
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Site-relative link for a published route.
|
|
|
+ *
|
|
|
+ * @param route - Manifest route, including its `.md` suffix.
|
|
|
+ * @returns The link VitePress serves the route at.
|
|
|
+ */
|
|
|
+export function routeLink(route: string): string {
|
|
|
+ return `/${route.replace(/(?:index)?\.md$/, '')}`
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Where a top-level navigation item lands.
|
|
|
+ *
|
|
|
+ * The target is derived rather than written down: a collection whose first page
|
|
|
+ * is renamed or reordered would otherwise leave the navigation bar pointing at
|
|
|
+ * a route the manifest no longer publishes.
|
|
|
+ *
|
|
|
+ * @param locale - Route tree the navigation item belongs to.
|
|
|
+ * @param collection - Sidebar collection the item opens.
|
|
|
+ * @returns Site-relative link of the collection's first page.
|
|
|
+ * @throws When the collection publishes no page.
|
|
|
+ */
|
|
|
+export function landingLink(locale: DocsLocale, collection: DocsSidebar): string {
|
|
|
+ const first = orderedPages(locale, collection)[0]
|
|
|
+ if (first === undefined) throw new Error(`Sidebar collection "${collection}" publishes no page.`)
|
|
|
+ return routeLink(first.route)
|
|
|
+}
|