diff --git a/.github/workflows/_build-docs.yml b/.github/workflows/_build-docs.yml
index 8bc9691d..338c0ec6 100644
--- a/.github/workflows/_build-docs.yml
+++ b/.github/workflows/_build-docs.yml
@@ -28,6 +28,7 @@ jobs:
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
+ fetch-depth: 0
persist-credentials: false
- name: Set up Node
diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml
index d506b005..88f7eb59 100644
--- a/.github/workflows/ci-docs.yml
+++ b/.github/workflows/ci-docs.yml
@@ -11,11 +11,15 @@ on:
- 'README_ZH.md'
- 'docs/**'
- 'github-pages/**'
+ - 'reme/config/default.yaml'
+ - 'integrations/claude_code/README.md'
+ - 'integrations/hermes_agent/README.md'
- 'reme_studio/README*.md'
- 'reme_studio/public/og.jpg'
- 'typescript/README*.md'
- 'plugins/*/README*.md'
- 'benchmark/*/README*.md'
+ - 'benchmark/toolmemory/gitcha.png'
pull_request:
branches: [main, master, dev, develop]
paths:
@@ -26,11 +30,15 @@ on:
- 'README_ZH.md'
- 'docs/**'
- 'github-pages/**'
+ - 'reme/config/default.yaml'
+ - 'integrations/claude_code/README.md'
+ - 'integrations/hermes_agent/README.md'
- 'reme_studio/README*.md'
- 'reme_studio/public/og.jpg'
- 'typescript/README*.md'
- 'plugins/*/README*.md'
- 'benchmark/*/README*.md'
+ - 'benchmark/toolmemory/gitcha.png'
workflow_dispatch:
concurrency:
diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
index fe81de3d..488f086d 100644
--- a/.github/workflows/deploy-docs.yml
+++ b/.github/workflows/deploy-docs.yml
@@ -6,6 +6,9 @@ on:
paths:
- "github-pages/**"
- "docs/**"
+ - "reme/config/default.yaml"
+ - "integrations/claude_code/README.md"
+ - "integrations/hermes_agent/README.md"
- "README.md"
- "README_ZH.md"
- "reme_studio/README*.md"
@@ -13,6 +16,7 @@ on:
- "typescript/README*.md"
- "plugins/*/README*.md"
- "benchmark/*/README*.md"
+ - "benchmark/toolmemory/gitcha.png"
- "AGENTS.md"
- ".github/workflows/deploy-docs.yml"
- ".github/workflows/_build-docs.yml"
diff --git a/AGENTS.md b/AGENTS.md
index 7718891a..ba8ae6ac 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -62,6 +62,8 @@ and concise documentation together.
conventions.
- `benchmark/` and `cookbook/`: runnable evaluations and example workflows.
- `docs/`: README-linked supporting pages and figures.
+- `github-pages/`: VitePress build shell, generated-content assembly, documentation checks, and GitHub Pages output. The
+ canonical theme and guides remain under `docs/`; `.generated/` and `dist/` are disposable.
## Development Setup
@@ -195,6 +197,9 @@ Integration tests may contact real model providers, services, or agent subproces
run credentialed or externally mutating tests automatically; run them only when the task requires them and the necessary
environment has been supplied or authorized. Mock network, model, and subprocess boundaries in unit tests.
+If documentation or the documentation theme changes, run `npm test` and `npm run build` from `github-pages/`. The Job
+reference is generated from `reme/config/default.yaml`; do not edit generated pages directly.
+
## Change Guardrails
- Preserve unrelated user changes in a dirty working tree.
diff --git a/README.md b/README.md
index dc0c18ce..bf855dae 100644
--- a/README.md
+++ b/README.md
@@ -51,12 +51,12 @@ users retain control of the durable files.
- [2026.08] - Published [`@agentscope-ai/reme`](https://www.npmjs.com/package/@agentscope-ai/reme), providing native
ReMe memory integrations for DeepSeek Harness and OpenClaw plus a shared TypeScript HTTP client.
-- [2026.08] - Published the [ReMe blog](https://agentscope-ai.github.io/ReMe/?doc=en-reme-blog), an end-to-end introduction to its local-first memory
+- [2026.08] - Published the [ReMe blog](https://reme.agentscope.io/en/reme-blog), an end-to-end introduction to its local-first memory
architecture, self-evolving workflows, hybrid search, proactive discovery, and benchmark results.
-- [2026.08] - [Experience-driven enhancement method](https://reme.agentscope.io/?doc=toolmemory-en) of agent tool-use execution built
+- [2026.08] - [Experience-driven enhancement method](https://reme.agentscope.io/en/benchmarks/toolmemory) of agent tool-use execution built
on ReMe is available on [arXiv:2608.03403](https://arxiv.org/abs/2608.03403).
-- [2026.07] - Introduced optional plugins: [Daily Paper](https://reme.agentscope.io/?doc=daily-paper-en) for paper discovery and
- analysis, and [Auto Fin](https://reme.agentscope.io/?doc=auto-fin-en) for researching the latest 24 hours of topic-related CLS news
+- [2026.07] - Introduced optional plugins: [Daily Paper](https://reme.agentscope.io/en/plugins/daily-paper) for paper discovery and
+ analysis, and [Auto Fin](https://reme.agentscope.io/en/plugins/auto-fin) for researching the latest 24 hours of topic-related CLS news
with local-memory search and validated historical wikilinks.
- [2026.07] - Our
paper [Remember Me, Refine Me: A Dynamic Procedural Memory Framework for Experience-Driven Agent Evolution](https://aclanthology.org/2026.findings-acl.829/)
@@ -171,7 +171,7 @@ Related: [[digest/wiki/memory-as-file.md]]
The `core` installation includes Studio. After starting ReMe, open to browse, edit, and search
the workspace. To add Studio to a base installation, use `pip install "reme-ai[web]"`. See the
-[ReMe Studio guide](https://reme.agentscope.io/?doc=studio-en) for source builds, configuration, and development.
+[ReMe Studio guide](https://reme.agentscope.io/en/workspace/studio) for source builds, configuration, and development.
## 🤝 Use ReMe with Your Agent
@@ -308,12 +308,12 @@ benchmark.
| Benchmark | Setting | Sample size | Agentic score | Focus |
| --------------------------------------------------------------------------- | ------------ | -----------------------: | ------------: | ------------------------------------------------------------------ |
-| **[LongMemEval cleaned-s](https://reme.agentscope.io/?doc=longmemeval-en)** | **Overall** | **500 questions** | **89.4%** | Cross-session retrieval, knowledge updates, and temporal reasoning |
-| [BEAM](https://reme.agentscope.io/?doc=beam-en) | 100K context | 20 cases / 400 questions | 66.1% | Ten types of long-context memory tasks |
-| [BEAM](https://reme.agentscope.io/?doc=beam-en) | 1M context | 35 cases / 700 questions | 65.0% | Ultra-long conversation settings |
+| **[LongMemEval cleaned-s](https://reme.agentscope.io/en/benchmarks/longmemeval)** | **Overall** | **500 questions** | **89.4%** | Cross-session retrieval, knowledge updates, and temporal reasoning |
+| [BEAM](https://reme.agentscope.io/en/benchmarks/beam) | 100K context | 20 cases / 400 questions | 66.1% | Ten types of long-context memory tasks |
+| [BEAM](https://reme.agentscope.io/en/benchmarks/beam) | 1M context | 35 cases / 700 questions | 65.0% | Ultra-long conversation settings |
ReMe also achieved a **0.580 PROC score across five user personas** in the repository's
-[π-Bench evaluation](https://reme.agentscope.io/?doc=pibench-en), 2.4% above NanoBot under the same test-model configuration. PROC
+[π-Bench evaluation](https://reme.agentscope.io/en/benchmarks/pibench), 2.4% above NanoBot under the same test-model configuration. PROC
measures proactive handling of hidden intent, clarification, cross-session preferences and conventions, task
dependencies, and underspecified requests.
@@ -326,8 +326,8 @@ plugins; see the source distributions and their documentation for [Daily Paper](
| Plugin | Capability |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
-| [Daily Paper](https://reme.agentscope.io/?doc=daily-paper-en) | Discover and rank papers, analyze PDFs with an agent, and generate file-native notes and a five-minute brief. |
-| [Auto Fin](https://reme.agentscope.io/?doc=auto-fin-en) | Fetch topic-related CLS news, search ReMe history, and generate wikilink-backed Markdown reports. |
+| [Daily Paper](https://reme.agentscope.io/en/plugins/daily-paper) | Discover and rank papers, analyze PDFs with an agent, and generate file-native notes and a five-minute brief. |
+| [Auto Fin](https://reme.agentscope.io/en/plugins/auto-fin) | Fetch topic-related CLS news, search ReMe history, and generate wikilink-backed Markdown reports. |
See [Plugin Management](docs/en/plugin_management.md) to install, inspect, validate, enable, and uninstall ReMe plugins.
@@ -338,6 +338,8 @@ These guides cover the main user workflows and the runtime contracts implemented
| Guide | What you will learn |
| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| [Quick Start](docs/en/quick_start.md) | Install ReMe, start the service, and run the first file and memory operations. |
+| [Configuration](docs/en/configuration.md) | Configure the workspace, models, Service, Jobs, Components, plugins, and CLI overrides. |
+| [Services and Deployment](docs/en/services.md) | Use HTTP, SSE, MCP, and Studio while respecting the default security boundary. |
| [Memory as File](docs/en/memory_as_file.md) | Understand workspace layers, frontmatter, wikilinks, chunks, and the file-as-source-of-truth model. |
| [Auto Memory](docs/en/auto_memory.md) | Preserve source conversations and distill reusable daily memory cards. |
| [Auto Resource](docs/en/auto_resource.md) | Import supported text resources and turn them into source-linked daily cards. |
@@ -347,7 +349,9 @@ These guides cover the main user workflows and the runtime contracts implemented
| [Application Scenarios](docs/en/reme_scene.md) | Follow concrete financial research, coding-memory, and personal knowledge-base examples. |
| [Framework](docs/en/framework.md) | Understand Application, Job, Step, Component, service, configuration, and lifecycle boundaries. |
| [TypeScript integrations](typescript/README.md) | Configure the shared client and native DeepSeek Harness and OpenClaw adapters. |
-| [ReMe Blog](https://agentscope-ai.github.io/ReMe/?doc=en-reme-blog) | Read the product story, design rationale, examples, and benchmark summary. |
+| [CLI and Job API](docs/en/reference/cli.md) | Learn command syntax and use the generated default Job parameter reference. |
+| [Operations and Recovery](docs/en/operations.md) | Diagnose services, maintain indexes, and back up, migrate, or recover a workspace. |
+| [ReMe Blog](https://reme.agentscope.io/en/reme-blog) | Read the product story, design rationale, examples, and benchmark summary. |
## 🛠️ Common Commands
diff --git a/README_ZH.md b/README_ZH.md
index 7583e4f7..059d6ff6 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -49,13 +49,13 @@
- [2026.08] - 发布 [`@agentscope-ai/reme`](https://www.npmjs.com/package/@agentscope-ai/reme),提供统一 TypeScript HTTP
client,以及 DeepSeek Harness 和 OpenClaw 的原生 ReMe 记忆集成。
-- [2026.08] - 发布 [ReMe 博客](https://agentscope-ai.github.io/ReMe/?doc=zh-reme-blog),系统介绍本地优先的记忆架构、自进化工作流、混合检索、
+- [2026.08] - 发布 [ReMe 博客](https://reme.agentscope.io/zh/reme-blog),系统介绍本地优先的记忆架构、自进化工作流、混合检索、
主动发现与评测结果。
- [2026.08] - 基于 ReMe 的智能体工具使用
- [经验驱动增强方法](https://reme.agentscope.io/?doc=toolmemory-zh)已发布,见
+ [经验驱动增强方法](https://reme.agentscope.io/zh/benchmarks/toolmemory)已发布,见
[arXiv:2608.03403](https://arxiv.org/abs/2608.03403)。
-- [2026.07] - 新增可选插件:[每日论文](https://reme.agentscope.io/?doc=daily-paper-zh)用于论文发现与解析,
- [Auto Fin](https://reme.agentscope.io/?doc=auto-fin-zh)用于研究最近 24 小时的主题相关财联社新闻,通过本地记忆搜索回顾历史材料并构建
+- [2026.07] - 新增可选插件:[每日论文](https://reme.agentscope.io/zh/plugins/daily-paper)用于论文发现与解析,
+ [Auto Fin](https://reme.agentscope.io/zh/plugins/auto-fin)用于研究最近 24 小时的主题相关财联社新闻,通过本地记忆搜索回顾历史材料并构建
wikilink。
- [2026.07] -
我们的论文 [Remember Me, Refine Me: A Dynamic Procedural Memory Framework for Experience-Driven Agent Evolution](https://aclanthology.org/2026.findings-acl.829/)
@@ -170,7 +170,7 @@ ReMe 会把 Agent 记忆保存为可读的 Markdown。
上面的 `core` 安装已包含 Studio。启动 ReMe 后,打开 即可浏览、编辑和搜索 workspace。
如需为基础安装单独添加 Studio,可使用 `pip install "reme-ai[web]"`。源码构建、配置和开发说明见
-[ReMe Studio 指南](https://reme.agentscope.io/?doc=studio-zh)。
+[ReMe Studio 指南](https://reme.agentscope.io/zh/workspace/studio)。
## 🤝 将 ReMe 接入你的 Agent
@@ -301,11 +301,11 @@ ReMe 通过 Agent 多轮搜索与读取的方式,评测多会话和超长上
| 基准 | 设置 | 样本量 | Agentic 得分 | 主要检验内容 |
| --------------------------------------------------------------------------- | ----------- | ----------------: | -----------: | ------------------------------ |
-| **[LongMemEval cleaned-s](https://reme.agentscope.io/?doc=longmemeval-zh)** | **整体** | **500 题** | **89.4%** | 跨会话检索、知识更新与时间推理 |
-| [BEAM](https://reme.agentscope.io/?doc=beam-zh) | 100K 上下文 | 20 cases / 400 题 | 66.1% | 十类长上下文记忆任务 |
-| [BEAM](https://reme.agentscope.io/?doc=beam-zh) | 1M 上下文 | 35 cases / 700 题 | 65.0% | 超长对话设置 |
+| **[LongMemEval cleaned-s](https://reme.agentscope.io/zh/benchmarks/longmemeval)** | **整体** | **500 题** | **89.4%** | 跨会话检索、知识更新与时间推理 |
+| [BEAM](https://reme.agentscope.io/zh/benchmarks/beam) | 100K 上下文 | 20 cases / 400 题 | 66.1% | 十类长上下文记忆任务 |
+| [BEAM](https://reme.agentscope.io/zh/benchmarks/beam) | 1M 上下文 | 35 cases / 700 题 | 65.0% | 超长对话设置 |
-在仓库的 [π-Bench 评测](https://reme.agentscope.io/?doc=pibench-zh)中,ReMe Agent 在 5 种用户角色上的平均 **PROC 得分为 0.580**
+在仓库的 [π-Bench 评测](https://reme.agentscope.io/zh/benchmarks/pibench)中,ReMe Agent 在 5 种用户角色上的平均 **PROC 得分为 0.580**
,比相同测试模型配置的 NanoBot 高 2.4%。PROC 用于评估隐藏意图完成、针对性澄清、跨会话偏好和规范复用、跨任务依赖推断以及欠规格请求推进等主动性能力。
## 🧩 扩展与插件
@@ -316,8 +316,8 @@ ReMe 通过 Agent 多轮搜索与读取的方式,评测多会话和超长上
| 插件 | 能力 |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------ |
-| [每日论文](https://reme.agentscope.io/?doc=daily-paper-zh) | 发现并排序论文,使用 Agent 解读 PDF,生成文件化论文笔记和五分钟简报。 |
-| [Auto Fin](https://reme.agentscope.io/?doc=auto-fin-zh) | 拉取主题相关财联社新闻,搜索 ReMe 历史材料并生成带 wikilink 的 Markdown 报告。 |
+| [每日论文](https://reme.agentscope.io/zh/plugins/daily-paper) | 发现并排序论文,使用 Agent 解读 PDF,生成文件化论文笔记和五分钟简报。 |
+| [Auto Fin](https://reme.agentscope.io/zh/plugins/auto-fin) | 拉取主题相关财联社新闻,搜索 ReMe 历史材料并生成带 wikilink 的 Markdown 报告。 |
安装、查看、校验、启用和卸载 ReMe 插件的方法见[插件管理](docs/zh/plugin_management.md)。
@@ -328,6 +328,8 @@ ReMe 通过 Agent 多轮搜索与读取的方式,评测多会话和超长上
| 文档 | 主要内容 |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| [快速开始](docs/zh/quick_start.md) | 安装 ReMe、启动服务,并执行首次文件和记忆操作。 |
+| [基础配置](docs/zh/configuration.md) | 配置 workspace、模型、Service、Job、Component、插件和命令行覆盖。 |
+| [服务与部署](docs/zh/services.md) | 使用 HTTP、SSE、MCP 和 Studio,并理解默认安全边界。 |
| [Memory as File](docs/zh/memory_as_file.md) | 理解 workspace 分层、frontmatter、wikilink、chunk 和文件事实来源模型。 |
| [Auto Memory](docs/zh/auto_memory.md) | 保留过滤后的对话来源记录,并提炼可复用的 daily 记忆卡片。 |
| [Auto Resource](docs/zh/auto_resource.md) | 导入支持的文本资料,转换为可追溯来源的 daily 卡片。 |
@@ -337,7 +339,9 @@ ReMe 通过 Agent 多轮搜索与读取的方式,评测多会话和超长上
| [应用场景](docs/zh/reme_scene.md) | 查看金融研究、研发记忆和个人知识库的完整使用示例。 |
| [框架说明](docs/zh/framework.md) | 理解 Application、Job、Step、Component、service、配置和生命周期边界。 |
| [TypeScript 集成](typescript/README_ZH.md) | 配置统一 client,以及 DeepSeek Harness 和 OpenClaw 原生适配器。 |
-| [ReMe 博客](https://agentscope-ai.github.io/ReMe/?doc=zh-reme-blog) | 了解完整产品故事、设计动机、使用示例和评测摘要。 |
+| [CLI 与 Job API](docs/zh/reference/cli.md) | 查询命令语法,以及由默认配置自动生成的 Job 参数参考。 |
+| [运维与恢复](docs/zh/operations.md) | 诊断服务、维护索引,并备份、迁移和恢复 workspace。 |
+| [ReMe 博客](https://reme.agentscope.io/zh/reme-blog) | 了解完整产品故事、设计动机、使用示例和评测摘要。 |
## 🛠️ 常用命令
diff --git a/benchmark/toolmemory/README.md b/benchmark/toolmemory/README.md
index 7f358018..40ac47fe 100644
--- a/benchmark/toolmemory/README.md
+++ b/benchmark/toolmemory/README.md
@@ -6,7 +6,7 @@
> Code: [https://github.com/WangCan1178/ExpG](https://github.com/WangCan1178/ExpG)
-
+
### Overview
diff --git a/benchmark/toolmemory/README_ZH.md b/benchmark/toolmemory/README_ZH.md
index b0c5b89b..0d247385 100644
--- a/benchmark/toolmemory/README_ZH.md
+++ b/benchmark/toolmemory/README_ZH.md
@@ -6,7 +6,7 @@
> 代码:[https://github.com/WangCan1178/ExpG](https://github.com/WangCan1178/ExpG)
-
+
### 简介
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
new file mode 100644
index 00000000..17411bae
--- /dev/null
+++ b/docs/.vitepress/config.mts
@@ -0,0 +1,342 @@
+import fs from "node:fs";
+import path from "node:path";
+import { execFileSync } from "node:child_process";
+import { fileURLToPath } from "node:url";
+import { defineConfig, type DefaultTheme } from "vitepress";
+import { legacyRoutes } from "./legacy-routes.mjs";
+
+const sourceRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
+const repositoryRoot = path.resolve(sourceRoot, "../../..");
+const repository = "https://github.com/agentscope-ai/ReMe";
+const base = process.env.DOCS_BASE || "/";
+
+function readSourceMap(): Record {
+ try {
+ return JSON.parse(fs.readFileSync(path.join(sourceRoot, ".source-map.json"), "utf8"));
+ } catch {
+ return {};
+ }
+}
+
+const sourceMap = readSourceMap();
+
+function collectMarkdown(directory: string, root = directory): string[] {
+ const files: string[] = [];
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
+ if (entry.name.startsWith(".") || entry.name === "public" || entry.name === "figure") continue;
+ const absolute = path.join(directory, entry.name);
+ if (entry.isDirectory()) files.push(...collectMarkdown(absolute, root));
+ else if (entry.name.endsWith(".md")) files.push(path.relative(root, absolute).replaceAll(path.sep, "/"));
+ }
+ return files.sort();
+}
+
+function buildLlmsFiles(outDir: string) {
+ const pages = collectMarkdown(sourceRoot);
+ const index = [
+ "# ReMe Documentation",
+ "",
+ "> Local-first, file-native memory for agents.",
+ "",
+ ...pages.map((relativePath) => {
+ const source = fs.readFileSync(path.join(sourceRoot, relativePath), "utf8");
+ const title = source.match(/^#\s+(.+)$/m)?.[1]
+ || source.match(/^title:\s*(.+)$/m)?.[1]
+ || path.basename(relativePath, ".md");
+ const route = relativePath.replace(/(?:^|\/)index\.md$/, "").replace(/\.md$/, "");
+ return `- [${title}](https://reme.agentscope.io/${route})`;
+ }),
+ "",
+ ];
+ fs.writeFileSync(path.join(outDir, "llms.txt"), index.join("\n"), "utf8");
+
+ const full = ["# ReMe Documentation", ""];
+ for (const relativePath of pages) {
+ const source = fs.readFileSync(path.join(sourceRoot, relativePath), "utf8");
+ full.push(``, "", source, "", "---", "");
+ const pageDir = path.join(outDir, relativePath.replace(/\.md$/, ""));
+ fs.mkdirSync(pageDir, { recursive: true });
+ fs.writeFileSync(path.join(pageDir, "llms.txt"), source, "utf8");
+ }
+ fs.writeFileSync(path.join(outDir, "llms-full.txt"), full.join("\n"), "utf8");
+}
+
+function sourcePathFor(relativePath: string) {
+ return sourceMap[relativePath] || `docs/${relativePath}`;
+}
+
+function sourceLastUpdated(relativePath: string): number | undefined {
+ const sourcePath = sourcePathFor(relativePath);
+ try {
+ const timestamp = execFileSync("git", ["log", "-1", "--format=%ct", "--", sourcePath], {
+ cwd: repositoryRoot,
+ encoding: "utf8",
+ }).trim();
+ if (timestamp) return Number(timestamp) * 1000;
+ } catch {
+ // Fall back to the canonical file timestamp outside a Git checkout.
+ }
+ try {
+ return fs.statSync(path.join(repositoryRoot, sourcePath)).mtimeMs;
+ } catch {
+ return undefined;
+ }
+}
+
+const legacyRedirectScript = `(() => {
+ const routes = ${JSON.stringify(legacyRoutes)};
+ const id = new URLSearchParams(window.location.search).get("doc");
+ const target = id && routes[id];
+ const base = ${JSON.stringify(base)};
+ if (target) {
+ const destination = /^https?:/.test(target)
+ ? target
+ : base.replace(/\\/$/, "") + target;
+ window.location.replace(destination + window.location.hash);
+ return;
+ }
+ const root = base.endsWith("/") ? base : base + "/";
+ if (window.location.pathname === root) {
+ window.location.replace(root + "zh/" + window.location.hash);
+ }
+})();`;
+
+function nav(language: "zh" | "en"): DefaultTheme.NavItem[] {
+ const zh = language === "zh";
+ return [
+ { text: zh ? "开始使用" : "Get Started", link: `/${language}/quick_start` },
+ { text: zh ? "核心概念" : "Concepts", link: `/${language}/memory_as_file` },
+ { text: zh ? "指南" : "Guides", link: `/${language}/auto_memory` },
+ { text: zh ? "集成" : "Integrations", link: `/${language}/integrations` },
+ { text: zh ? "API 参考" : "API Reference", link: `/${language}/reference/cli` },
+ { text: zh ? "常见问题" : "FAQ", link: `/${language}/faq` },
+ ];
+}
+
+function sidebar(language: "zh" | "en"): DefaultTheme.SidebarItem[] {
+ const zh = language === "zh";
+ return [
+ {
+ text: zh ? "开始使用" : "Get Started",
+ collapsed: false,
+ items: [
+ { text: zh ? "项目介绍" : "Introduction", link: `/${language}/` },
+ { text: zh ? "快速开始" : "Quick Start", link: `/${language}/quick_start` },
+ { text: zh ? "基础配置" : "Configuration", link: `/${language}/configuration` },
+ { text: zh ? "服务与部署" : "Services and Deployment", link: `/${language}/services` },
+ ],
+ },
+ {
+ text: zh ? "核心概念" : "Core Concepts",
+ collapsed: false,
+ items: [
+ { text: zh ? "文件即记忆" : "Memory as File", link: `/${language}/memory_as_file` },
+ { text: zh ? "记忆检索" : "Memory Search", link: `/${language}/memory_search` },
+ { text: zh ? "自动关联" : "Auto Link", link: `/${language}/auto_link` },
+ { text: zh ? "应用场景" : "Application Scenarios", link: `/${language}/reme_scene` },
+ ],
+ },
+ {
+ text: zh ? "记忆工作流" : "Memory Workflows",
+ collapsed: false,
+ items: [
+ { text: "Auto Memory", link: `/${language}/auto_memory` },
+ { text: "Auto Resource", link: `/${language}/auto_resource` },
+ { text: "Auto Dream", link: `/${language}/auto_dream` },
+ { text: "Proactive", link: `/${language}/proactive` },
+ ],
+ },
+ {
+ text: zh ? "Agent 集成" : "Agent Integrations",
+ collapsed: true,
+ items: [
+ { text: zh ? "集成总览" : "Overview", link: `/${language}/integrations` },
+ { text: "Claude Code", link: `/${language}/integrations/claude-code` },
+ { text: "Hermes Agent", link: `/${language}/integrations/hermes` },
+ { text: "TypeScript / OpenClaw / DSH", link: `/${language}/integrations/typescript` },
+ ],
+ },
+ {
+ text: zh ? "工作区与插件" : "Workspace and Plugins",
+ collapsed: true,
+ items: [
+ { text: "ReMe Studio", link: `/${language}/workspace/studio` },
+ { text: zh ? "插件管理" : "Plugin Management", link: `/${language}/plugin_management` },
+ { text: zh ? "插件开发" : "Plugin Development", link: `/${language}/plugin_development` },
+ { text: zh ? "每日论文" : "Daily Paper", link: `/${language}/plugins/daily-paper` },
+ { text: "Auto Fin", link: `/${language}/plugins/auto-fin` },
+ { text: "LME", link: `/${language}/plugins/lme` },
+ { text: "BEAM", link: `/${language}/plugins/beam` },
+ ],
+ },
+ {
+ text: zh ? "API 参考" : "API Reference",
+ collapsed: true,
+ items: [
+ { text: "CLI", link: `/${language}/reference/cli` },
+ { text: zh ? "Job API" : "Job API", link: `/${language}/reference/jobs` },
+ { text: "HTTP / MCP", link: `/${language}/services#http-api` },
+ ],
+ },
+ {
+ text: zh ? "运维" : "Operations",
+ collapsed: true,
+ items: [
+ { text: zh ? "诊断、备份与恢复" : "Diagnostics, Backup, and Recovery", link: `/${language}/operations` },
+ { text: zh ? "常见问题" : "FAQ", link: `/${language}/faq` },
+ ],
+ },
+ {
+ text: zh ? "开发者" : "Development",
+ collapsed: true,
+ items: [
+ { text: zh ? "代码框架" : "Framework", link: `/${language}/framework` },
+ { text: zh ? "开源与贡献" : "Contributing", link: `/${language}/contributing` },
+ ],
+ },
+ {
+ text: zh ? "评测" : "Benchmarks",
+ collapsed: true,
+ items: [
+ { text: "BEAM", link: `/${language}/benchmarks/beam` },
+ { text: "LongMemEval", link: `/${language}/benchmarks/longmemeval` },
+ { text: "π-Bench", link: `/${language}/benchmarks/pibench` },
+ { text: "Tool Memory / ExpG", link: `/${language}/benchmarks/toolmemory` },
+ ],
+ },
+ ];
+}
+
+function configureRepositoryLinks(md: any) {
+ for (const ruleName of ["link_open", "image"] as const) {
+ const original = md.renderer.rules[ruleName];
+ md.renderer.rules[ruleName] = (tokens: any[], index: number, options: any, env: any, self: any) => {
+ const attribute = ruleName === "image" ? "src" : "href";
+ const token = tokens[index];
+ const attributeIndex = token.attrIndex(attribute);
+ const target = attributeIndex >= 0 ? token.attrs[attributeIndex][1] : "";
+ if (target && !/^(?:[a-z]+:|#|\/)/i.test(target)) {
+ const cleanTarget = target.split("#")[0].split("?")[0];
+ const generatedTarget = path.resolve(sourceRoot, path.dirname(env.relativePath), cleanTarget);
+ if (!fs.existsSync(generatedTarget)) {
+ const originalPage = sourcePathFor(env.relativePath);
+ const originalTarget = path.posix.normalize(path.posix.join(path.posix.dirname(originalPage), cleanTarget));
+ const suffix = target.slice(cleanTarget.length);
+ const url = ruleName === "image"
+ ? `https://raw.githubusercontent.com/agentscope-ai/ReMe/main/${originalTarget}${suffix}`
+ : `${repository}/blob/main/${originalTarget}${suffix}`;
+ token.attrs[attributeIndex][1] = url;
+ }
+ }
+ return original ? original(tokens, index, options, env, self) : self.renderToken(tokens, index, options);
+ };
+ }
+}
+
+export default defineConfig({
+ lang: "zh-CN",
+ title: "ReMe",
+ description: "Local-first, file-native memory for agents",
+ base,
+ cleanUrls: true,
+ lastUpdated: true,
+ ignoreDeadLinks: [/^http:\/\/localhost(?::\d+)?(?:\/|$)/],
+ sitemap: {
+ hostname: "https://reme.agentscope.io",
+ transformItems(items) {
+ const isRoot = (url: string) => url.replace(/^\/+|\/+$/g, "") === "";
+ return items.filter((item) => !isRoot(item.url)).map((item) => {
+ const route = item.url.replace(/^\/+/, "");
+ const relativePath = !route || route.endsWith("/") ? `${route}index.md` : `${route}.md`;
+ const links = item.links?.filter((link) => !isRoot(link.url));
+ return { ...item, links, lastmod: sourceLastUpdated(relativePath) };
+ });
+ },
+ },
+ head: [
+ ["link", { rel: "icon", type: "image/svg+xml", href: `${base}favicon.svg` }],
+ ["meta", { name: "theme-color", content: "#087f6a" }],
+ ["script", {}, legacyRedirectScript],
+ ],
+ markdown: {
+ config: configureRepositoryLinks,
+ },
+ transformPageData(pageData, { siteConfig }) {
+ const sourcePath = path.join(siteConfig.srcDir, pageData.relativePath);
+ pageData.frontmatter._sourcePath = sourcePathFor(pageData.relativePath);
+ pageData.lastUpdated = sourceLastUpdated(pageData.relativePath);
+ try {
+ pageData.frontmatter._rawMarkdown = fs.readFileSync(sourcePath, "utf8");
+ } catch {
+ pageData.frontmatter._rawMarkdown = "";
+ }
+ },
+ buildEnd(siteConfig) {
+ buildLlmsFiles(siteConfig.outDir);
+ },
+ themeConfig: {
+ logo: "/favicon.svg",
+ siteTitle: "ReMe",
+ nav: [
+ ...nav("zh"),
+ {
+ text: "语言",
+ items: [
+ { text: "简体中文", link: "/zh/" },
+ { text: "English", link: "/en/" },
+ ],
+ },
+ ],
+ outline: { label: "页面导航", level: [2, 3] },
+ search: {
+ provider: "local",
+ options: {
+ locales: {
+ zh: {
+ translations: {
+ button: { buttonText: "搜索文档", buttonAriaLabel: "搜索文档" },
+ modal: {
+ noResultsText: "没有找到相关内容",
+ resetButtonTitle: "清除查询",
+ footer: { selectText: "选择", navigateText: "切换", closeText: "关闭" },
+ },
+ },
+ },
+ },
+ },
+ },
+ socialLinks: [{ icon: "github", link: repository }],
+ footer: {
+ message: "Released under the Apache-2.0 License.",
+ copyright: "Copyright ReMe contributors",
+ },
+ },
+ locales: {
+ zh: {
+ label: "简体中文",
+ lang: "zh-CN",
+ link: "/zh/",
+ themeConfig: {
+ nav: nav("zh"),
+ sidebar: { "/zh/": sidebar("zh") },
+ outline: { label: "页面导航", level: [2, 3] },
+ docFooter: { prev: "上一页", next: "下一页" },
+ darkModeSwitchLabel: "外观",
+ sidebarMenuLabel: "菜单",
+ returnToTopLabel: "返回顶部",
+ langMenuLabel: "切换语言",
+ },
+ },
+ en: {
+ label: "English",
+ lang: "en-US",
+ link: "/en/",
+ themeConfig: {
+ nav: nav("en"),
+ sidebar: { "/en/": sidebar("en") },
+ outline: { label: "On this page", level: [2, 3] },
+ docFooter: { prev: "Previous page", next: "Next page" },
+ },
+ },
+ },
+});
diff --git a/docs/.vitepress/legacy-routes.mjs b/docs/.vitepress/legacy-routes.mjs
new file mode 100644
index 00000000..bdf3607e
--- /dev/null
+++ b/docs/.vitepress/legacy-routes.mjs
@@ -0,0 +1,47 @@
+export const legacyRoutes = {
+ "readme-zh": "/zh/",
+ "readme-en": "/en/",
+ "zh-quick_start": "/zh/quick_start",
+ "en-quick_start": "/en/quick_start",
+ "zh-plugin_management": "/zh/plugin_management",
+ "en-plugin_management": "/en/plugin_management",
+ "zh-memory_as_file": "/zh/memory_as_file",
+ "en-memory_as_file": "/en/memory_as_file",
+ "zh-memory_search": "/zh/memory_search",
+ "en-memory_search": "/en/memory_search",
+ "zh-auto_memory": "/zh/auto_memory",
+ "en-auto_memory": "/en/auto_memory",
+ "zh-auto_resource": "/zh/auto_resource",
+ "en-auto_resource": "/en/auto_resource",
+ "zh-auto_link": "/zh/auto_link",
+ "en-auto_link": "/en/auto_link",
+ "zh-auto_dream": "/zh/auto_dream",
+ "en-auto_dream": "/en/auto_dream",
+ "zh-proactive": "/zh/proactive",
+ "en-proactive": "/en/proactive",
+ "zh-reme_scene": "/zh/reme_scene",
+ "en-reme_scene": "/en/reme_scene",
+ "zh-framework": "/zh/framework",
+ "en-framework": "/en/framework",
+ "zh-reme-blog": "/zh/reme-blog",
+ "en-reme-blog": "/en/reme-blog",
+ "zh-contributing": "/zh/contributing",
+ "en-contributing": "/en/contributing",
+ "typescript-zh": "/zh/integrations/typescript",
+ "typescript-en": "/en/integrations/typescript",
+ "studio-zh": "/zh/workspace/studio",
+ "studio-en": "/en/workspace/studio",
+ "daily-paper-zh": "/zh/plugins/daily-paper",
+ "daily-paper-en": "/en/plugins/daily-paper",
+ "auto-fin-zh": "/zh/plugins/auto-fin",
+ "auto-fin-en": "/en/plugins/auto-fin",
+ "beam-zh": "/zh/benchmarks/beam",
+ "beam-en": "/en/benchmarks/beam",
+ "longmemeval-zh": "/zh/benchmarks/longmemeval",
+ "longmemeval-en": "/en/benchmarks/longmemeval",
+ "pibench-zh": "/zh/benchmarks/pibench",
+ "pibench-en": "/en/benchmarks/pibench",
+ "toolmemory-zh": "/zh/benchmarks/toolmemory",
+ "toolmemory-en": "/en/benchmarks/toolmemory",
+ "agents-guide": "https://github.com/agentscope-ai/ReMe/blob/main/AGENTS.md",
+};
diff --git a/docs/.vitepress/theme/CopyMarkdownButton.vue b/docs/.vitepress/theme/CopyMarkdownButton.vue
new file mode 100644
index 00000000..b3805638
--- /dev/null
+++ b/docs/.vitepress/theme/CopyMarkdownButton.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/SourceLink.vue b/docs/.vitepress/theme/SourceLink.vue
new file mode 100644
index 00000000..cebc353e
--- /dev/null
+++ b/docs/.vitepress/theme/SourceLink.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css
new file mode 100644
index 00000000..5f4974ac
--- /dev/null
+++ b/docs/.vitepress/theme/custom.css
@@ -0,0 +1,224 @@
+:root {
+ --vp-layout-max-width: 1560px;
+ --vp-c-brand-1: #087f6a;
+ --vp-c-brand-2: #086554;
+ --vp-c-brand-3: #19a98f;
+ --vp-c-brand-soft: rgba(8, 127, 106, 0.14);
+ --vp-c-bg: #ffffff;
+ --vp-c-bg-alt: #f4f7f5;
+ --vp-c-bg-elv: #ffffff;
+ --vp-c-bg-soft: #f1f6f3;
+ --vp-c-text-1: #17221d;
+ --vp-c-text-2: #526159;
+ --vp-c-text-3: #718078;
+ --vp-c-divider: #dce5e0;
+ --vp-font-family-base: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+ --vp-font-family-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
+ --reme-blue: #3156d9;
+ --reme-green: #087f6a;
+}
+
+.dark {
+ --vp-c-brand-1: #57dfc3;
+ --vp-c-brand-2: #35c6a9;
+ --vp-c-brand-3: #087f6a;
+ --vp-c-brand-soft: rgba(87, 223, 195, 0.14);
+ --vp-c-bg: #0d1512;
+ --vp-c-bg-alt: #09100d;
+ --vp-c-bg-elv: #14201b;
+ --vp-c-bg-soft: #17251f;
+ --vp-c-text-1: #edf7f3;
+ --vp-c-text-2: #bacbc4;
+ --vp-c-text-3: #91a49c;
+ --vp-c-divider: #283a33;
+}
+
+body {
+ background:
+ radial-gradient(circle at 8% 8%, rgba(25, 201, 176, 0.055), transparent 28rem),
+ var(--vp-c-bg);
+}
+
+.VPNav {
+ border-bottom: 1px solid color-mix(in srgb, var(--vp-c-divider) 84%, transparent);
+ background: color-mix(in srgb, var(--vp-c-bg) 88%, transparent);
+ backdrop-filter: blur(18px) saturate(140%);
+}
+
+.VPNavBarTitle .logo {
+ width: 30px;
+ height: 30px;
+}
+
+.VPNavBarTitle .title {
+ font-weight: 780;
+ letter-spacing: -0.02em;
+}
+
+.VPNavBarSearch .DocSearch-Button,
+.VPNavBarSearch button {
+ min-width: 190px;
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 10px;
+ background: var(--vp-c-bg-alt);
+}
+
+.VPSidebar {
+ border-right: 1px solid var(--vp-c-divider);
+ background: color-mix(in srgb, var(--vp-c-bg-alt) 82%, transparent);
+}
+
+.VPSidebarItem .text {
+ font-size: 14px;
+}
+
+.VPSidebarItem.level-0 > .item > .text {
+ color: var(--vp-c-text-1);
+ font-weight: 750;
+}
+
+.VPSidebarItem.is-active > .item .link > .text {
+ color: var(--vp-c-brand-1);
+}
+
+.VPDocAsideOutline {
+ border-left-color: var(--vp-c-divider);
+}
+
+.VPDoc .container > .content {
+ min-width: 0;
+}
+
+.VPDoc .content-container {
+ max-width: 900px !important;
+}
+
+.vp-doc {
+ color: var(--vp-c-text-1);
+ font-size: 16px;
+ line-height: 1.78;
+}
+
+.vp-doc h1 {
+ margin-bottom: 28px;
+ font-size: clamp(36px, 5vw, 52px);
+ line-height: 1.08;
+ letter-spacing: -0.045em;
+}
+
+.vp-doc h2 {
+ margin-top: 52px;
+ border-top-color: var(--vp-c-divider);
+ font-size: 27px;
+ letter-spacing: -0.025em;
+}
+
+.vp-doc h3 {
+ margin-top: 34px;
+ font-size: 20px;
+}
+
+.vp-doc :not(pre) > code {
+ border-radius: 5px;
+ color: color-mix(in srgb, var(--vp-c-brand-1) 82%, var(--vp-c-text-1));
+}
+
+.vp-doc div[class*="language-"] {
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 12px;
+ box-shadow: inset 3px 0 0 color-mix(in srgb, var(--vp-c-brand-1) 62%, transparent);
+}
+
+.copy-markdown-wrap {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 18px;
+}
+
+.copy-markdown {
+ display: inline-flex;
+ align-items: center;
+ gap: 7px;
+ min-height: 34px;
+ padding: 6px 12px;
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 9px;
+ color: var(--vp-c-text-2);
+ background: var(--vp-c-bg-soft);
+ cursor: pointer;
+ font-size: 13px;
+ font-weight: 650;
+}
+
+.copy-markdown:hover,
+.copy-markdown.copied {
+ border-color: var(--vp-c-brand-1);
+ color: var(--vp-c-brand-1);
+}
+
+.copy-markdown svg {
+ width: 15px;
+ height: 15px;
+ fill: none;
+ stroke: currentColor;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ stroke-width: 2;
+}
+
+.source-link-wrap {
+ margin-top: 48px;
+ padding-top: 20px;
+ border-top: 1px solid var(--vp-c-divider);
+ font-size: 13px;
+}
+
+.source-link-wrap a {
+ color: var(--vp-c-text-3);
+ text-decoration: none;
+}
+
+.source-link-wrap a:hover {
+ color: var(--vp-c-brand-1);
+}
+
+.VPHome {
+ background:
+ radial-gradient(circle at 14% 14%, rgba(25, 201, 176, 0.14), transparent 30rem),
+ radial-gradient(circle at 86% 10%, rgba(49, 86, 217, 0.11), transparent 28rem);
+}
+
+.VPHero .name {
+ background: linear-gradient(120deg, var(--reme-green), var(--reme-blue));
+ background-clip: text;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.VPHero .name,
+.VPHero .text {
+ letter-spacing: -0.05em;
+}
+
+.VPHero .image-bg {
+ background: linear-gradient(135deg, rgba(25, 201, 176, 0.28), rgba(49, 86, 217, 0.2));
+ filter: blur(46px);
+}
+
+.VPFeature {
+ border-color: color-mix(in srgb, var(--vp-c-brand-1) 18%, var(--vp-c-divider));
+ border-radius: 16px;
+ background: linear-gradient(150deg, var(--vp-c-bg-elv), var(--vp-c-bg-soft));
+ transition: transform 160ms ease, box-shadow 160ms ease;
+}
+
+.VPFeature:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 16px 34px rgba(21, 58, 43, 0.1);
+}
+
+@media (max-width: 768px) {
+ .vp-doc h1 { font-size: 34px; }
+ .vp-doc h2 { margin-top: 44px; font-size: 24px; }
+ .copy-markdown-wrap { margin-top: -8px; }
+}
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
new file mode 100644
index 00000000..5edbc9e7
--- /dev/null
+++ b/docs/.vitepress/theme/index.ts
@@ -0,0 +1,15 @@
+import { h } from "vue";
+import DefaultTheme from "vitepress/theme";
+import CopyMarkdownButton from "./CopyMarkdownButton.vue";
+import SourceLink from "./SourceLink.vue";
+import "./custom.css";
+
+export default {
+ extends: DefaultTheme,
+ Layout() {
+ return h(DefaultTheme.Layout, null, {
+ "doc-before": () => h(CopyMarkdownButton),
+ "doc-after": () => h(SourceLink),
+ });
+ },
+};
diff --git a/docs/en/configuration.md b/docs/en/configuration.md
new file mode 100644
index 00000000..49e84bc1
--- /dev/null
+++ b/docs/en/configuration.md
@@ -0,0 +1,157 @@
+---
+title: Configuration
+description: ReMe configuration files, environment expansion, command-line overrides, and core components.
+---
+
+# Configuration
+
+ReMe uses YAML or JSON to describe its Service, Jobs, and Components. The built-in default is `reme/config/default.yaml`. Select another configuration at startup and apply command-line overrides when needed.
+
+## Precedence
+
+Configuration is merged in this order, with later values winning:
+
+1. `application_defaults` from enabled plugins.
+2. The selected file; `default` is used when none is specified.
+3. CLI dot-notation overrides.
+
+```bash
+reme start
+reme start config=demo
+reme start config=/absolute/path/to/app.yaml
+reme start service.port=8181 workspace_dir=/data/reme
+```
+
+`config` accepts a built-in name or a `.yaml`, `.yml`, or `.json` file. Overrides are deep-merged, so changing `service.port` preserves sibling service settings.
+
+## CLI values
+
+Arguments use `key=value`; leading `-` or `--` is accepted:
+
+```bash
+reme start --service.port=8181 --service.web_enabled=false
+```
+
+Values support null, booleans, numbers, JSON arrays and objects, quoted JSON strings, and plain strings. Numeric-looking values with leading zeroes, such as `007`, remain strings. Quote values such as `"true"` in JSON when they must remain strings.
+
+## Environment variables
+
+Configuration recursively expands:
+
+```yaml
+api_key: ${LLM_API_KEY}
+base_url: ${LLM_BASE_URL:-https://example.com/v1}
+```
+
+`${VAR}` fails when undefined; `${VAR:-default}` uses its fallback. ReMe also searches for `.env` from the command's working directory through at most five parents.
+
+Keep secrets in `.env` or the process environment, never in committed configuration.
+
+## Application fields
+
+| Field | Default | Purpose |
+|---|---|---|
+| `app_name` | `ReMe` | Display name |
+| `workspace_dir` | `.reme` | User-owned workspace root, normalized to an absolute path |
+| `metadata_dir` | `metadata` | Rebuildable indexes, graphs, and catalogs |
+| `session_dir` | `session` | Agent sessions; standard transcripts use `session/dialog` |
+| `mem_session_dir` | `mem_session` | Agent-wrapper sessions and configuration |
+| `resource_dir` | `resource` | External resources |
+| `daily_dir` | `daily` | Daily memory |
+| `digest_dir` | `digest` | Consolidated long-term memory |
+| `timezone` | `Asia/Shanghai` | IANA timezone used for dates and cron jobs |
+| `language` | empty | Default language for LLM interactions |
+| `plugins` | `[]` | Installed plugins enabled for this Application |
+| `service` | HTTP | Service configuration |
+| `jobs` | default Jobs | Job configurations by name |
+| `components` | defaults | Components grouped by type and name |
+
+`session_dir` must remain workspace-relative.
+
+## LLM
+
+The default LLM uses an OpenAI-compatible interface:
+
+```yaml
+components:
+ as_llm:
+ default:
+ backend: openai
+ model: qwen3.7-plus
+ context_size: 200000
+ credential:
+ api_key: ${LLM_API_KEY:-}
+ base_url: ${LLM_BASE_URL:-}
+```
+
+Built-in registrations include `openai`, `anthropic`, `dashscope`, `deepseek`, `gemini`, `moonshot`, `ollama`, and `xai`. Their detailed model fields follow the corresponding AgentScope wrappers.
+
+File operations, BM25 search, and wikilink traversal do not require an LLM. Evolution workflows such as `auto_memory`, `auto_resource`, and `auto_dream` do.
+
+## Embeddings
+
+Vector retrieval is disabled by default. Credentials alone do not enable it: configure `as_embedding`, `embedding_store`, and connect the store to `file_store`.
+
+```yaml
+components:
+ as_embedding:
+ default:
+ backend: openai
+ model: text-embedding-v4
+ dimensions: 1024
+ credential:
+ api_key: ${EMBEDDING_API_KEY}
+ base_url: ${EMBEDDING_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}
+ embedding_store:
+ default:
+ backend: local
+ as_embedding: default
+ file_store:
+ default:
+ backend: local
+ embedding_store: default
+ keyword_index: default
+ file_graph: default
+```
+
+Rebuild the embedding index after changing the model or dimensions.
+
+## Service and Jobs
+
+Minimal HTTP configuration:
+
+```yaml
+service:
+ backend: http
+ host: 127.0.0.1
+ port: 2333
+ web_enabled: true
+ mcp_enabled: true
+ mcp_path: /mcp
+```
+
+A Job declares a backend, parameter schema, and ordered Steps:
+
+```yaml
+jobs:
+ example:
+ backend: base
+ description: Example job
+ parameters:
+ type: object
+ properties:
+ text: { type: string }
+ required: [text]
+ steps:
+ - backend: example_step
+```
+
+Set `enable_serve: false` to keep a Job internal. Background and cron Jobs are never service-exposed.
+
+## Inspect the effective configuration
+
+```bash
+reme app_config
+```
+
+The result is the merged, validated configuration with secrets redacted. Use it when diagnosing plugin or override precedence. The authoritative contracts remain `reme/schema/application_config.py` and `reme/config/default.yaml`.
diff --git a/docs/en/contributing.md b/docs/en/contributing.md
index ad962169..99c9fac1 100644
--- a/docs/en/contributing.md
+++ b/docs/en/contributing.md
@@ -209,6 +209,13 @@ Documentation lives under:
docs/
```
+User guides should have matching `docs/zh/` and `docs/en/` versions and appear in the corresponding navigation in
+`docs/.vitepress/config.mts`. The ReMe Studio, TypeScript, plugin, and benchmark READMEs remain canonical in their own
+directories; `github-pages/scripts/generate-content.mjs` mirrors them during builds. Never edit `.generated/` or `dist/`.
+
+The Job API reference is generated from `reme/config/default.yaml`. Update that YAML and its tests when a default Job
+contract changes rather than editing generated pages.
+
Documentation should:
- Use clear titles that directly identify a capability or flow.
@@ -216,6 +223,15 @@ Documentation should:
- Use real repository paths such as `reme/config/default.yaml`, `reme/steps/`, and `tests/unit/`.
- Describe default behavior according to the current code, `pyproject.toml`, and default configuration.
+Validate the documentation site with:
+
+```bash
+cd github-pages
+npm ci
+npm test
+npm run build
+```
+
---
## Getting Help
diff --git a/docs/en/faq.md b/docs/en/faq.md
new file mode 100644
index 00000000..6aeb113a
--- /dev/null
+++ b/docs/en/faq.md
@@ -0,0 +1,71 @@
+---
+title: Frequently Asked Questions
+description: Quick answers for ReMe installation, services, models, retrieval, files, and plugins.
+---
+
+# Frequently Asked Questions
+
+## Do basic file operations require a model API key?
+
+No. `write`, `read`, `list`, `stat`, BM25 search, and wikilink traversal work without model credentials. `auto_memory`, `auto_resource`, and `auto_dream` require an LLM.
+
+## Why is search still BM25-only after setting an embedding key?
+
+Embeddings are disabled by default. Configure `as_embedding` and `embedding_store`, then connect `file_store.default.embedding_store` to that component. See [Configuration](./configuration.md#embeddings).
+
+## Why did `reme reindex` not discover a new file?
+
+`reindex` rebuilds indexes from current `file_chunks`; it does not scan the workspace. Check `index_update_loop`, the watched directory and extension, and `health_check`.
+
+## How do I use another workspace?
+
+```bash
+reme start workspace_dir=/absolute/path/to/memory
+```
+
+Ordinary CLI calls discover the running service, so they do not need the workspace argument again.
+
+## What if port 2333 is occupied?
+
+Do not stop an unknown listener. Select another port:
+
+```bash
+reme start service.port=8181
+```
+
+Then confirm it with `reme find_reme`.
+
+## Why is an installed plugin missing its Jobs?
+
+Installation only makes the distribution discoverable in the active Python environment. Enable it for the Application:
+
+```bash
+reme start plugins='["auto-fin"]'
+```
+
+Restart a running service after changing package or enablement state.
+
+## May I edit workspace Markdown directly?
+
+Yes. Files are the source of truth and watchers ingest changes. Keep frontmatter valid, use complete workspace-relative wikilinks, and avoid unconditional concurrent saves.
+
+## May I expose ReMe publicly?
+
+Not with the default configuration alone. Jobs can write and delete, HTTP CORS is permissive, and there is no general authentication layer. Use a controlled network or authenticated TLS reverse proxy and restrict `service.jobs`.
+
+## How should I back up and migrate memory?
+
+Stop writes and back up the complete workspace. `session/`, `resource/`, `daily/`, and `digest/` are the key sources; `metadata/` can be backed up or rebuilt. See [Diagnostics, Backup, and Recovery](./operations.md).
+
+## Why is Studio unavailable?
+
+The base `reme-ai` package has no frontend assets. Install `reme-ai[web]` or `reme-ai[core]`, or set `service.web_static_dir`. Missing Studio assets do not disable the Job API.
+
+## Which capabilities does the running service expose?
+
+```bash
+reme help
+reme app_config
+```
+
+Static documentation describes defaults; plugins and custom configuration may change the active service.
diff --git a/docs/en/index.md b/docs/en/index.md
new file mode 100644
index 00000000..a1b925c8
--- /dev/null
+++ b/docs/en/index.md
@@ -0,0 +1,36 @@
+---
+layout: home
+title: ReMe Documentation
+titleTemplate: false
+hero:
+ name: ReMe
+ text: Memory that works for agents
+ tagline: Files remain yours. ReMe turns conversations and resources into readable, editable, searchable, interconnected local files.
+ image:
+ src: /favicon.svg
+ alt: ReMe
+ actions:
+ - theme: brand
+ text: Quick Start
+ link: /en/quick_start
+ - theme: alt
+ text: Configuration
+ link: /en/configuration
+features:
+ - icon: 📁
+ title: Memory as files
+ details: Workspace files are the durable source of truth; indexes, graphs, and caches remain rebuildable.
+ link: /en/memory_as_file
+ - icon: 🧠
+ title: Memory workflows
+ details: Turn conversations and resources into daily notes, then consolidate them into connected long-term digests.
+ link: /en/auto_memory
+ - icon: 🔎
+ title: Search and graph
+ details: Combine keyword and optional vector retrieval with wikilink graph expansion.
+ link: /en/memory_search
+ - icon: 🔌
+ title: Agent integrations
+ details: Connect existing agents through the CLI, HTTP, MCP, and host adapters.
+ link: /en/integrations
+---
diff --git a/docs/en/integrations.md b/docs/en/integrations.md
new file mode 100644
index 00000000..03b2cf0a
--- /dev/null
+++ b/docs/en/integrations.md
@@ -0,0 +1,63 @@
+---
+title: Agent Integrations
+description: Connect ReMe to agents through the CLI, HTTP, MCP, Skills, and host adapters.
+---
+
+# Agent Integrations
+
+ReMe keeps memory in an independent service and a user-owned workspace. Multiple agents can call the same memory system without binding storage to one model or host.
+
+## Choose an interface
+
+| Scenario | Recommended interface |
+|---|---|
+| Local script or hook | ReMe CLI |
+| Application backend | HTTP Client |
+| Tool-protocol host | MCP |
+| TypeScript agent | `@agentscope-ai/reme` |
+| Claude Code | MCP + Skill + Stop Hook |
+| Hermes Agent | Memory provider adapter |
+| Codex or another coding agent | `reme_memory` Skill or MCP |
+
+## General memory loop
+
+1. Before answering, call `search` for relevant memory.
+2. Use `read` on high-value results and `traverse` when relationships matter.
+3. Retain workspace-relative source paths in the answer.
+4. At session end, pass source messages to `auto_memory`.
+5. Let background or scheduled workflows consolidate daily notes into digest memory.
+
+An empty search result must remain empty; do not present model inference as recalled history.
+
+## MCP
+
+The default HTTP service exposes streamable HTTP MCP at `http://127.0.0.1:2333/mcp`. Common tools include `search`, `read`, `traverse`, `list`, `auto_memory`, and `proactive`.
+
+Use `service.jobs` to expose a read-only subset or keep write tools in a separate configuration.
+
+## CLI and Skill
+
+`skills/reme_memory/SKILL.md` defines a general workflow for agents that can run local commands: installation checks, service discovery, retrieval, reading, and persistence boundaries.
+
+It deliberately avoids silently modifying Python environments, stopping unknown processes on port conflicts, writing recalled tool output back as conversation source, or persisting credentials.
+
+## TypeScript, OpenClaw, and DeepSeek Harness
+
+See [TypeScript Agent Integrations](./integrations/typescript.md) for the shared HTTP client, DeepSeek Harness adapter, OpenClaw adapter, and package validation.
+
+## Claude Code
+
+`integrations/claude_code/` provides streamable HTTP MCP configuration, a `reme-memory` Skill, and a Stop hook that calls `auto_memory_cc`. Follow that directory's README for installation.
+
+## Hermes Agent
+
+`integrations/hermes_agent/` provides a memory provider that recalls context before model calls and asynchronously invokes `auto_memory` after each turn.
+
+## Production guidance
+
+- choose a stable absolute `workspace_dir`;
+- reuse a service discovered by `reme find_reme`;
+- treat `reme help` as the active Job contract;
+- apply timeouts and failure logging to writes;
+- do not block the host's core response path when memory is temporarily unavailable;
+- use authentication, TLS, and a minimal Job allowlist for remote access.
diff --git a/docs/en/operations.md b/docs/en/operations.md
new file mode 100644
index 00000000..50160661
--- /dev/null
+++ b/docs/en/operations.md
@@ -0,0 +1,102 @@
+---
+title: Diagnostics, Backup, and Recovery
+description: ReMe health checks, logs, index maintenance, workspace backup, migration, and recovery.
+---
+
+# Diagnostics, Backup, and Recovery
+
+ReMe recovery protects user-owned workspace files and rebuilds catalogs, indexes, and graphs from those sources. Never delete or rewrite user memory merely to repair derived state.
+
+## Quick diagnosis
+
+Run these in order:
+
+```bash
+reme find_reme
+reme version
+reme health_check
+reme status
+reme app_config
+```
+
+- `find_reme` confirms the actual host, port, and PID;
+- `version` verifies that the CLI reaches the service;
+- `health_check` reports component health;
+- `status` estimates stateful component memory and process RSS;
+- `app_config` returns the effective configuration with secrets redacted.
+
+## Logs and common symptoms
+
+`log_to_console` and `log_to_file` control logging. For startup failures, inspect the first exception rather than later client connection errors.
+
+| Symptom | Check first |
+|---|---|
+| CLI cannot find ReMe | `reme find_reme`, process state, startup directory, and port |
+| Automatic memory fails | LLM backend, model, API key, and base URL |
+| Search is BM25-only | Whether an embedding store is connected to `file_store` |
+| New files are absent | Directory, extension, watcher, and `health_check` |
+| Studio fails but API works | Installed web extra, static path, and browser console |
+| Installed plugin is unavailable | Python interpreter, `plugins` configuration, and service restart |
+
+## Index maintenance
+
+```bash
+reme reindex scope=all
+reme reindex scope=bm25
+reme reindex scope=embedding
+```
+
+`reindex` rebuilds BM25 and/or embedding indexes from the current `file_chunks`. It does not scan the workspace, rechunk files, or rebuild the wikilink graph. Diagnose the watcher first when ingestion is the problem.
+
+Rebuild a daily index page separately:
+
+```bash
+reme daily_reindex date=2026-09-04
+```
+
+## Backup
+
+Stop writes or stop the service, then back up the complete workspace. The most important sources are:
+
+- `session/` for conversation sources;
+- `resource/` for external resources;
+- `daily/` for daily memory;
+- `digest/` for consolidated memory.
+
+`metadata/` contains indexes, graphs, and catalogs. Backing it up accelerates restoration, but it is not the sole source of truth.
+
+Use an explicit, stable absolute `workspace_dir` for durable deployments rather than relying on an incidental `.reme/` under the current directory.
+
+## Migrate a workspace
+
+1. Stop the old service to prevent writes during the copy.
+2. Copy the complete workspace while preserving timestamps.
+3. Start with the new absolute path:
+
+```bash
+reme start workspace_dir=/new/location/reme-memory
+```
+
+4. Run `health_check`, `status`, and a representative `search`.
+5. Rebuild embeddings if their model or dimensions changed.
+
+Do not push a workspace containing private conversations to a public repository.
+
+## Recover derived state
+
+Do not remove anything until a backup exists. Then:
+
+1. preserve `session/`, `resource/`, `daily/`, and `digest/`;
+2. record the effective configuration and component backends;
+3. verify that the failure is limited to `metadata/`;
+4. move suspect derived state to an isolated backup location;
+5. restart with the same configuration and let watchers rebuild;
+6. validate search, graph traversal, and daily indexes.
+
+The internal layout of metadata files is not a public automation contract.
+
+## Concurrent editing
+
+When Studio or an editor saves a complete file, pass the mtime from `stat` as `save.expected_mtime`. A save then fails if another actor changed the file after it was opened, avoiding silent overwrites.
+
+File Jobs enforce workspace containment and per-path locking. Do not bypass them to write arbitrary absolute paths.
diff --git a/docs/en/plugin_development.md b/docs/en/plugin_development.md
new file mode 100644
index 00000000..074033c3
--- /dev/null
+++ b/docs/en/plugin_development.md
@@ -0,0 +1,101 @@
+---
+title: Plugin Development
+description: Create, register, configure, test, and publish a ReMe plugin.
+---
+
+# Plugin Development
+
+A ReMe plugin is a regular Python distribution exposed through the `reme.plugins` entry-point group. Its package-level `plugin.yaml` can register Step and Component backends and provide default Application configuration.
+
+## Minimal structure
+
+```text
+my-plugin/
+├── pyproject.toml
+└── src/my_plugin/
+ ├── __init__.py
+ ├── plugin.yaml
+ └── steps.py
+```
+
+`pyproject.toml`:
+
+```toml
+[project.entry-points."reme.plugins"]
+my-plugin = "my_plugin"
+```
+
+`plugin.yaml`:
+
+```yaml
+name: my-plugin
+backends:
+ my_step: my_plugin.steps:MyStep
+application_defaults:
+ jobs:
+ my_action:
+ backend: base
+ description: Run my plugin action
+ parameters:
+ type: object
+ properties:
+ text: { type: string }
+ required: [text]
+ steps:
+ - backend: my_step
+```
+
+## Implement a Step
+
+```python
+from reme.components.component_registry import R
+from reme.steps.base_step import BaseStep
+
+
+@R.register("my_step")
+class MyStep(BaseStep):
+ async def execute(self):
+ self.context.response.answer = self.context.data["text"]
+```
+
+Step instances belong to one Job invocation. Put shared in-memory state under a narrow `app_context.metadata` key. Promote state that needs lifecycle, locking, or persistence to a Component or workspace file.
+
+## Configuration merge
+
+`application_defaults` is a partial `ApplicationConfig`:
+
+```text
+plugin defaults < selected/default config < CLI overrides
+```
+
+Plugins must not rewrite user configuration. Their backends enter an Application-local registry only when the plugin appears in that Application's `plugins` list.
+
+## Local validation
+
+```bash
+reme plugins validate ./path/to/my-plugin
+reme plugins install ./path/to/my-plugin --editable
+reme plugins list
+reme plugins show my-plugin
+reme start plugins='["my-plugin"]'
+reme my_action text=hello
+```
+
+Validation imports plugin code, so run it only for trusted sources.
+
+## Test boundaries
+
+- create workspaces with `tmp_path`;
+- mock network, model, and subprocess boundaries;
+- verify disabled plugins do not mutate the built-in registry;
+- verify plugin defaults and explicit configuration precedence;
+- keep tasks, clients, and executors under Component lifecycle;
+- never delete or rewrite user source files to repair derived state.
+
+The repository's Daily Paper, Auto Fin, LME, and BEAM plugins are complete examples.
+
+## Compatibility
+
+Legacy Python Plugin descriptors and the `reme.configs` entry point remain supported during migration, but new plugins should use `plugin.yaml`. Enablement always belongs to an Application rather than a process-global switch.
+
+See [Plugin Management](./plugin_management.md) for installation, upgrades, and removal.
diff --git a/docs/en/quick_start.md b/docs/en/quick_start.md
index a15edef2..f946ac39 100644
--- a/docs/en/quick_start.md
+++ b/docs/en/quick_start.md
@@ -1,5 +1,12 @@
+---
+title: Quick Start
+description: Install and start ReMe, then complete a first file, retrieval, and automatic-memory workflow.
+---
+
# Quick Start
+This page gets one working loop running. See [Configuration](./configuration.md) for the full configuration contract and [Services and Deployment](./services.md) for HTTP or MCP integration.
+
## Installation
ReMe requires Python 3.11+.
@@ -237,3 +244,5 @@ You can also specify a YAML or JSON configuration file:
```bash
reme start config=/path/to/custom.yaml
```
+
+Continue with the [CLI Reference](./reference/cli.md), [Job API Reference](./reference/jobs.md), or [Diagnostics, Backup, and Recovery](./operations.md).
diff --git a/docs/en/reference/cli.md b/docs/en/reference/cli.md
new file mode 100644
index 00000000..5a3c372d
--- /dev/null
+++ b/docs/en/reference/cli.md
@@ -0,0 +1,87 @@
+---
+title: CLI Reference
+description: ReMe command syntax, service invocation, configuration overrides, and plugin commands.
+---
+
+# CLI Reference
+
+The basic syntax is:
+
+```text
+reme ACTION key=value ...
+```
+
+## Start an Application
+
+```bash
+reme start
+reme start config=demo
+reme start workspace_dir=/data/reme service.port=8181
+reme start job=search query="keywords" limit=5
+```
+
+`start job=` runs one Job through a one-shot service; plain `start` runs the configured Service.
+
+## Call Jobs
+
+Once a service is running, each action name is a Job name:
+
+```bash
+reme help
+reme health_check
+reme search query="project decision" limit=10
+reme read path=digest/wiki/project.md start_line=1 end_line=80
+```
+
+Use JSON for structured values:
+
+```bash
+reme auto_memory \
+ session_id=example \
+ messages='[{"role":"user","content":"Remember this preference"}]'
+```
+
+Client-selection arguments—`backend`, `transport`, `host`, `port`, `timeout`, `command`, `args`, and `show_metadata`—configure the client and never leak into the Job payload.
+
+## Configuration overrides
+
+```bash
+reme start \
+ config=/path/to/custom.yaml \
+ service.port=8181 \
+ service.web_enabled=false \
+ plugins='["auto-fin"]'
+```
+
+Leading `-` or `--` is optional. Use dots for nested keys and JSON for arrays and objects.
+
+## Service discovery
+
+```bash
+reme find_reme
+```
+
+This reports a discovered service but never starts or replaces a process.
+
+## Plugin commands
+
+Package management runs locally rather than through HTTP or MCP:
+
+```bash
+reme plugins list
+reme plugins show auto-fin
+reme plugins validate auto-fin
+reme plugins install reme-auto-fin
+reme plugins uninstall auto-fin
+```
+
+See [Plugin Management](../plugin_management.md) for the complete workflow.
+
+## Discover active capabilities
+
+The [Job API Reference](./jobs.md) describes the default configuration. Plugins and custom YAML may change the running service, so automation should prefer:
+
+```bash
+reme help
+reme app_config
+```
diff --git a/docs/en/services.md b/docs/en/services.md
new file mode 100644
index 00000000..c0be01a0
--- /dev/null
+++ b/docs/en/services.md
@@ -0,0 +1,115 @@
+---
+title: Services and Deployment
+description: Run ReMe through HTTP, SSE, MCP, the CLI, and ReMe Studio while respecting its local security boundary.
+---
+
+# Services and Deployment
+
+ReMe can run as a local HTTP service, a standalone MCP server, or a one-shot CLI Job. The default starts HTTP on `127.0.0.1:2333` and serves JSON, SSE, streamable HTTP MCP, and optional ReMe Studio from one process.
+
+## HTTP API
+
+```bash
+reme start
+reme start service.host=127.0.0.1 service.port=8181
+```
+
+Regular Jobs become `POST /`:
+
+```bash
+curl -s http://127.0.0.1:2333/search \
+ -H 'Content-Type: application/json' \
+ -d '{"query":"user preferences","limit":5}'
+```
+
+Job arguments live at the request body's top level. A regular response follows the `Response` schema:
+
+```json
+{"success": true, "answer": "...", "metadata": {}}
+```
+
+Unhandled Step failures become unsuccessful responses.
+
+## Streaming and SSE
+
+Jobs with `backend: stream` also use `POST /`, returning `text/event-stream`. Error paths emit an error chunk and always terminate the stream. The default `chat` Job is streaming:
+
+```bash
+curl -N http://127.0.0.1:2333/chat \
+ -H 'Content-Type: application/json' \
+ -d '{"query":"Summarize my long-term preferences"}'
+```
+
+MCP does not expose Stream Jobs.
+
+## MCP
+
+The default HTTP service mounts streamable HTTP MCP at `/mcp`:
+
+```yaml
+service:
+ backend: http
+ mcp_enabled: true
+ mcp_path: /mcp
+ mcp_stateless_http: false
+```
+
+For a standalone MCP service:
+
+```bash
+reme start service.backend=mcp service.transport=stdio
+reme start service.backend=mcp service.transport=sse service.port=2333
+reme start service.backend=mcp service.transport=streamable-http service.port=2333
+```
+
+MCP tools come from non-stream Jobs with `enable_serve: true`. Use `service.jobs` as an allowlist. `injected_job_kwargs` adds server-managed values that callers cannot override.
+
+```yaml
+service:
+ backend: http
+ jobs: [search, read, traverse, auto_memory]
+ injected_job_kwargs:
+ tenant_id: local-user
+ tool_error_on_failure: true
+```
+
+## ReMe Studio
+
+After installing `reme-ai[web]` or `reme-ai[core]`, the default HTTP origin also serves Studio:
+
+```text
+http://127.0.0.1:2333/
+```
+
+Disable it with `service.web_enabled=false` or select a build with `service.web_static_dir`. Missing static assets do not prevent the Job API from starting.
+
+## One-shot Jobs
+
+```bash
+reme start job=search query="user preferences" limit=5
+```
+
+This selects the one-shot CLI Service while retaining the normal Application, Component, and Job lifecycle.
+
+## Service discovery
+
+```bash
+reme find_reme
+```
+
+Ordinary `reme ` commands prefer the running service's actual backend, host, port, and transport. They fall back to local configuration only when no service is discovered.
+
+## Security boundary
+
+ReMe is local-first:
+
+- the default binds to `127.0.0.1`;
+- HTTP CORS allows any origin;
+- Jobs may write, move, or delete files;
+- the service layer has no general-purpose user authentication.
+
+Do not expose the default service directly to the public internet. For remote access, place it on a controlled network or behind an authenticated TLS reverse proxy, apply access controls and request-size limits, and expose only necessary Jobs.
+
+## OpenAPI
+
+FastAPI exposes the active endpoints through `/docs`, `/redoc`, and `/openapi.json`. The Studio SPA fallback preserves these reserved paths.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..6ed2b528
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,43 @@
+---
+layout: home
+title: ReMe Documentation
+titleTemplate: false
+head:
+ - - meta
+ - http-equiv: refresh
+ content: "0; url=/zh/"
+ - - link
+ - rel: canonical
+ href: https://reme.agentscope.io/zh/
+hero:
+ name: ReMe
+ text: 让 Agent 真正记住
+ tagline: 文件属于你,记忆服务于 Agent。ReMe 将对话和资料沉淀为可读、可编辑、可检索、相互链接的本地文件。
+ image:
+ src: /favicon.svg
+ alt: ReMe
+ actions:
+ - theme: brand
+ text: 快速开始
+ link: /zh/quick_start
+ - theme: alt
+ text: 核心概念
+ link: /zh/memory_as_file
+features:
+ - icon: 📁
+ title: Local-first
+ details: Workspace 文件是持久事实源;索引、图谱和缓存都可以重新构建。
+ link: /zh/memory_as_file
+ - icon: 🧠
+ title: Memory workflows
+ details: 将对话和资料写入 daily,自动整理为互相关联的长期 digest。
+ link: /zh/auto_memory
+ - icon: 🔎
+ title: Search and graph
+ details: 结合关键词、可选向量检索与 wikilink 图谱,渐进式展开上下文。
+ link: /zh/memory_search
+ - icon: 🔌
+ title: Agent integrations
+ details: 通过 CLI、HTTP、MCP 和宿主适配器接入已有 Agent。
+ link: /zh/integrations
+---
diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg
new file mode 100644
index 00000000..aeb6a94e
--- /dev/null
+++ b/docs/public/favicon.svg
@@ -0,0 +1,5 @@
+
diff --git a/docs/zh/configuration.md b/docs/zh/configuration.md
new file mode 100644
index 00000000..6fdeb191
--- /dev/null
+++ b/docs/zh/configuration.md
@@ -0,0 +1,168 @@
+---
+title: 基础配置
+description: ReMe 配置文件、环境变量、命令行覆盖和核心组件配置。
+---
+
+# 基础配置
+
+ReMe 使用 YAML 或 JSON 描述 Service、Job 和 Component。默认配置位于 `reme/config/default.yaml`;启动时可以选择其他配置,再用命令行覆盖其中的字段。
+
+## 配置优先级
+
+配置按下面的顺序合并,靠后的值优先:
+
+1. 已启用插件提供的 `application_defaults`。
+2. 选中的配置文件;未指定时使用内置 `default`。
+3. 命令行 dot notation 覆盖。
+
+```bash
+reme start
+reme start config=demo
+reme start config=/absolute/path/to/app.yaml
+reme start service.port=8181 workspace_dir=/data/reme
+```
+
+`config` 支持内置配置名以及 `.yaml`、`.yml`、`.json` 文件。覆盖采用深度合并,不会因为修改 `service.port` 而丢失 `service` 下的其他字段。
+
+## 值的解析
+
+CLI 参数使用 `key=value`,前导 `-` 或 `--` 也会被接受:
+
+```bash
+reme start --service.port=8181 --service.web_enabled=false
+```
+
+值支持:
+
+- `null`、布尔值、整数和浮点数;
+- JSON 数组和对象;
+- JSON 引号字符串;
+- 普通字符串。
+
+类似 `007` 的前导零字符串不会被转换成数字。需要保留 `true`、`false` 等字面字符串时,使用 JSON 引号:`value='"true"'`。
+
+## 环境变量
+
+配置文件会递归展开两种表达式:
+
+```yaml
+api_key: ${LLM_API_KEY}
+base_url: ${LLM_BASE_URL:-https://example.com/v1}
+```
+
+`${VAR}` 在变量未定义时会报错;`${VAR:-default}` 使用默认值。ReMe 还会从命令启动目录向上查找 `.env`,最多检查五级父目录。
+
+不要把密钥提交到配置文件或 Git。推荐把密钥放在 `.env` 或进程环境中。
+
+## Application 字段
+
+| 字段 | 默认值 | 作用 |
+|---|---|---|
+| `app_name` | `ReMe` | 应用显示名称 |
+| `workspace_dir` | `.reme` | 用户拥有的 workspace 根目录,会规范化为绝对路径 |
+| `metadata_dir` | `metadata` | 索引、图谱和 catalog 等派生状态 |
+| `session_dir` | `session` | Agent 对话记录;标准 transcript 位于 `session/dialog` |
+| `mem_session_dir` | `mem_session` | Agent wrapper 的会话和配置 |
+| `resource_dir` | `resource` | 外部资料 |
+| `daily_dir` | `daily` | Daily memory |
+| `digest_dir` | `digest` | 长期整理后的记忆 |
+| `timezone` | `Asia/Shanghai` | Cron、日期和梦境流程使用的 IANA 时区 |
+| `language` | 空 | LLM 交互默认语言 |
+| `plugins` | `[]` | 为当前 Application 启用的已安装插件 |
+| `service` | HTTP | 服务端配置 |
+| `jobs` | 默认 Job | Job 名到 Job 配置的映射 |
+| `components` | 默认组件 | 按类型和名称组织的组件配置 |
+
+`session_dir` 必须保持 workspace-relative。其他 workspace 子目录也应使用清晰、稳定的相对名称。
+
+## LLM 配置
+
+默认 LLM 使用 OpenAI-compatible 接口:
+
+```yaml
+components:
+ as_llm:
+ default:
+ backend: openai
+ model: qwen3.7-plus
+ context_size: 200000
+ credential:
+ api_key: ${LLM_API_KEY:-}
+ base_url: ${LLM_BASE_URL:-}
+```
+
+可注册的内置 backend 包括 `openai`、`anthropic`、`dashscope`、`deepseek`、`gemini`、`moonshot`、`ollama` 和 `xai`。实际字段由对应 AgentScope model wrapper 决定。
+
+基础文件操作、BM25 检索、wikilink 遍历不需要 LLM。`auto_memory`、`auto_resource`、`auto_dream` 等演化流程需要可用 LLM。
+
+## Embedding 配置
+
+向量检索默认关闭。只设置 `EMBEDDING_API_KEY` 不会自动启用它;还需要同时启用 `as_embedding`、`embedding_store`,并把它连接到 `file_store`:
+
+```yaml
+components:
+ as_embedding:
+ default:
+ backend: openai
+ model: text-embedding-v4
+ dimensions: 1024
+ credential:
+ api_key: ${EMBEDDING_API_KEY}
+ base_url: ${EMBEDDING_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}
+ embedding_store:
+ default:
+ backend: local
+ as_embedding: default
+ file_store:
+ default:
+ backend: local
+ embedding_store: default
+ keyword_index: default
+ file_graph: default
+```
+
+修改 embedding 模型或维度后,应重新构建 embedding 索引。
+
+## Service 和 Job
+
+最小 HTTP 配置:
+
+```yaml
+service:
+ backend: http
+ host: 127.0.0.1
+ port: 2333
+ web_enabled: true
+ mcp_enabled: true
+ mcp_path: /mcp
+```
+
+Job 由 backend、参数 schema 和顺序执行的 Step 组成:
+
+```yaml
+jobs:
+ example:
+ backend: base
+ description: Example job
+ parameters:
+ type: object
+ properties:
+ text: { type: string }
+ required: [text]
+ steps:
+ - backend: example_step
+```
+
+设置 `enable_serve: false` 可以保留内部 Job、禁止 Service 暴露。后台和 Cron Job始终不会作为请求端点暴露。
+
+## 查看生效配置
+
+服务启动后运行:
+
+```bash
+reme app_config
+```
+
+返回的是已合并、已校验并隐藏密钥后的配置。排查覆盖顺序或插件配置时,应以它为准,而不是只查看某一个 YAML 文件。
+
+完整字段定义以 `reme/schema/application_config.py` 和 `reme/config/default.yaml` 为准。
diff --git a/docs/zh/contributing.md b/docs/zh/contributing.md
index 2b5c65e0..e2cdbdfc 100644
--- a/docs/zh/contributing.md
+++ b/docs/zh/contributing.md
@@ -190,6 +190,12 @@ pytest tests/unit/test_reme_cli.py
docs/
```
+用户指南应同时提供 `docs/zh/` 与 `docs/en/` 版本,并在 `docs/.vitepress/config.mts` 的对应导航中注册。ReMe Studio、
+TypeScript、插件和评测的 README 是各自目录中的规范源文件;`github-pages/scripts/generate-content.mjs` 会在构建时镜像它们,
+不要编辑 `.generated/` 或 `dist/`。
+
+`Job API 参考`由 `reme/config/default.yaml` 自动生成。修改默认 Job 参数时更新 YAML 和测试,不要手工维护生成页。
+
建议文档保持:
- 标题明确,直接说明能力或流程。
@@ -197,6 +203,15 @@ docs/
- 涉及路径时使用仓库内真实路径,例如 `reme/config/default.yaml`、`reme/steps/`、`tests/unit/`。
- 涉及默认行为时,以当前代码和 `pyproject.toml`、默认配置为准。
+文档站检查:
+
+```bash
+cd github-pages
+npm ci
+npm test
+npm run build
+```
+
---
## 获取帮助
diff --git a/docs/zh/faq.md b/docs/zh/faq.md
new file mode 100644
index 00000000..563a93bc
--- /dev/null
+++ b/docs/zh/faq.md
@@ -0,0 +1,75 @@
+---
+title: 常见问题
+description: ReMe 安装、服务、模型、检索、文件和插件问题的快速答案。
+---
+
+# 常见问题
+
+## 基础文件操作需要模型 API Key 吗?
+
+不需要。`write`、`read`、`list`、`stat`、BM25 搜索和 wikilink 遍历可以在没有模型凭据时运行。`auto_memory`、`auto_resource` 和 `auto_dream` 需要 LLM。
+
+## 为什么配置了 Embedding Key 仍然只有 BM25?
+
+Embedding 默认未启用。除了凭据,还必须配置 `as_embedding`、`embedding_store`,并让 `file_store.default.embedding_store` 指向该组件。参见[基础配置](./configuration.md#embedding-配置)。
+
+## 为什么 `reme reindex` 没有发现新文件?
+
+`reindex` 只从当前 `file_chunks` 重建 BM25 或 embedding 索引,不扫描 workspace。检查 `index_update_loop` watcher、文件目录、后缀和 `health_check`。
+
+## 怎样使用另一个 workspace?
+
+启动时传入稳定的绝对路径:
+
+```bash
+reme start workspace_dir=/absolute/path/to/memory
+```
+
+普通 CLI 调用会发现运行服务,不必重复 workspace 参数。
+
+## 端口 2333 被占用怎么办?
+
+不要停止未知监听者。选择另一个端口:
+
+```bash
+reme start service.port=8181
+```
+
+然后用 `reme find_reme` 确认发现结果。
+
+## 为什么插件安装后仍然没有对应 Job?
+
+安装只让 distribution 在当前 Python 环境中可见。还需要在应用配置中启用:
+
+```bash
+reme start plugins='["auto-fin"]'
+```
+
+修改安装或启用状态后需要重启已运行的服务。
+
+## 可以直接编辑 workspace 中的 Markdown 吗?
+
+可以。文件是事实源,watcher 会摄取修改。应保留有效 frontmatter、使用完整 workspace-relative wikilink,并避免同时由多个编辑器无条件覆盖同一文件。
+
+## 可以把服务暴露到公网吗?
+
+默认配置不适合直接公网暴露。服务包含写入和删除 Job,HTTP CORS 宽松,且没有通用认证层。请使用受控网络或带 TLS、认证、访问控制的反向代理,并限制 `service.jobs`。
+
+## 怎样备份和迁移?
+
+停止写入后备份整个 workspace。`session/`、`resource/`、`daily/` 和 `digest/` 是最重要的用户数据;`metadata/` 可以随同备份,也可以从源文件重建。详见[诊断、备份与恢复](./operations.md)。
+
+## Studio 找不到怎么办?
+
+基础 `reme-ai` 包不包含前端资源。安装 `reme-ai[web]` 或 `reme-ai[core]`,或通过 `service.web_static_dir` 指向构建产物。Studio 缺失不会影响 Job API。
+
+## 当前服务到底开放了哪些能力?
+
+运行:
+
+```bash
+reme help
+reme app_config
+```
+
+静态文档描述默认配置;运行服务可能由自定义配置和插件改变。
diff --git a/docs/zh/index.md b/docs/zh/index.md
new file mode 100644
index 00000000..f06269c9
--- /dev/null
+++ b/docs/zh/index.md
@@ -0,0 +1,36 @@
+---
+layout: home
+title: ReMe 文档
+titleTemplate: false
+hero:
+ name: ReMe
+ text: 让 Agent 真正记住
+ tagline: 文件属于你,记忆服务于 Agent。ReMe 将对话和资料沉淀为可读、可编辑、可检索、相互链接的本地文件。
+ image:
+ src: /favicon.svg
+ alt: ReMe
+ actions:
+ - theme: brand
+ text: 快速开始
+ link: /zh/quick_start
+ - theme: alt
+ text: 查看配置
+ link: /zh/configuration
+features:
+ - icon: 📁
+ title: 文件即记忆
+ details: Workspace 文件是持久事实源;索引、图谱和缓存都可以重新构建。
+ link: /zh/memory_as_file
+ - icon: 🧠
+ title: 自动记忆
+ details: 将对话和资料写入 daily,自动整理为互相关联的长期 digest。
+ link: /zh/auto_memory
+ - icon: 🔎
+ title: 检索与图谱
+ details: 结合关键词、可选向量检索与 wikilink 图谱,渐进式展开上下文。
+ link: /zh/memory_search
+ - icon: 🔌
+ title: Agent 集成
+ details: 通过 CLI、HTTP、MCP 和宿主适配器接入已有 Agent。
+ link: /zh/integrations
+---
diff --git a/docs/zh/integrations.md b/docs/zh/integrations.md
new file mode 100644
index 00000000..ab239c15
--- /dev/null
+++ b/docs/zh/integrations.md
@@ -0,0 +1,88 @@
+---
+title: Agent 集成
+description: 通过 CLI、HTTP、MCP、Skill 和宿主适配器把 ReMe 接入 Agent。
+---
+
+# Agent 集成
+
+ReMe 把记忆能力放在独立服务和用户拥有的 workspace 中。Agent 可以通过标准接口调用同一套记忆,而不必把存储逻辑绑定到某一个模型或宿主。
+
+## 选择接入方式
+
+| 场景 | 推荐方式 |
+|---|---|
+| 本机脚本或 Hook | ReMe CLI |
+| 应用后端 | HTTP Client |
+| 支持工具协议的 Agent | MCP |
+| TypeScript Agent | `@agentscope-ai/reme` |
+| Claude Code | MCP + Skill + Stop Hook |
+| Hermes Agent | Memory provider adapter |
+| Codex 或其他 coding agent | `reme_memory` Skill 或 MCP |
+
+## 通用接入循环
+
+一个完整但可控的 Agent 记忆循环通常包含:
+
+1. 会话开始或回答前,用 `search` 找到相关记忆;
+2. 对高价值结果使用 `read`,必要时用 `traverse` 展开关系;
+3. 在回答中保留 workspace-relative 来源路径;
+4. 会话结束后,把原始消息交给 `auto_memory`;
+5. 由后台或定时任务把 daily 内容整理到 digest。
+
+搜索不到内容时应明确返回空结果,不应把模型推测当成历史记忆。
+
+## MCP
+
+默认 HTTP 服务在 `http://127.0.0.1:2333/mcp` 提供 streamable HTTP MCP。常用工具包括:
+
+- `search`
+- `read`
+- `traverse`
+- `list`
+- `auto_memory`
+- `proactive`
+
+根据宿主风险模型,可以用 `service.jobs` 只暴露只读工具,或将写入工具放在单独配置中。
+
+## CLI 和 Skill
+
+仓库中的 `skills/reme_memory/SKILL.md` 描述了一个通用 Agent 工作流,包括安装检查、服务发现、检索、读取和写入边界。它适合能够执行本地命令的 Agent。
+
+Skill 不应:
+
+- 未经允许安装或升级 Python 环境;
+- 发现端口冲突后停止未知进程;
+- 把召回的工具结果再次写入对话来源;
+- 将密钥或敏感信息写入记忆。
+
+## TypeScript、OpenClaw 与 DeepSeek Harness
+
+统一 TypeScript 客户端和宿主适配器见 [TypeScript Agent 集成](./integrations/typescript.md)。它包含:
+
+- HTTP Client;
+- DeepSeek Harness adapter;
+- OpenClaw adapter;
+- 构建与发布检查。
+
+## Claude Code
+
+仓库的 `integrations/claude_code/` 提供:
+
+- streamable HTTP MCP 配置;
+- `reme-memory` Skill;
+- 会话停止时调用 `auto_memory_cc` 的 Hook。
+
+完整安装步骤以仓库中的 `integrations/claude_code/README.md` 为准。
+
+## Hermes Agent
+
+`integrations/hermes_agent/` 提供 memory provider:模型调用前检索相关记忆,每轮结束后异步调用 `auto_memory`。完整配置见该目录 README。
+
+## 生产接入建议
+
+- 明确选择稳定、绝对的 `workspace_dir`;
+- 启动前复用 `reme find_reme` 发现的服务;
+- 以 `reme help` 为当前 Job 契约;
+- 为写入动作设置超时和失败日志;
+- 不因记忆服务暂时不可用而阻塞宿主的核心回答流程;
+- 对远程访问使用认证、TLS 和最小 Job allowlist。
diff --git a/docs/zh/integrations/claude-code.md b/docs/zh/integrations/claude-code.md
new file mode 100644
index 00000000..17f78ab4
--- /dev/null
+++ b/docs/zh/integrations/claude-code.md
@@ -0,0 +1,67 @@
+---
+title: Claude Code 集成
+description: 通过 MCP、reme-memory Skill 和 Stop Hook 将 Claude Code 连接到 ReMe。
+---
+
+# Claude Code 集成
+
+ReMe 的 Claude Code 插件提供长期记忆召回,并在每次会话结束后异步记录对话。Daily 到 digest 的整理仍由共享的 ReMe 服务负责。
+
+## 能力
+
+- 通过 MCP 使用 `search`、`traverse`、`daily_list`、`frontmatter_read`、`read`、`auto_memory_cc` 等工具;
+- `reme-memory` Skill 在回答前召回长期记忆并保留来源路径;
+- Stop Hook 只把 Claude Code `session_id` 传给服务端,服务端从本地 transcript 解析会话;
+- 记录在脱离 Claude Code 的后台进程中进行,不延迟退出;服务不可用时记录日志并结束。
+
+## 部署模型
+
+插件连接到用户预先启动的共享 HTTP MCP 服务,不为每个 Claude Code 窗口创建 ReMe。这样所有窗口共享一个 workspace、一组 watcher 和一次 dream cron。
+
+## 准备 ReMe
+
+```bash
+pip install "reme-ai[core]"
+```
+
+在稳定目录配置 LLM 环境,然后启动:
+
+```bash
+reme start service.backend=http
+```
+
+默认 JSON Job API 和 MCP 地址分别位于同一个 `127.0.0.1:2333` 服务,MCP 路径是 `/mcp`。使用其他端口时,必须同步修改插件的 `.mcp.json`。
+
+默认搜索使用 BM25;只有启用向量检索时才需要 Embedding 配置。
+
+## 安装插件
+
+在 Claude Code 中运行:
+
+```text
+/plugin marketplace add ./integrations/claude_code
+/plugin install reme@reme-marketplace
+```
+
+重启 Claude Code,再运行 `/mcp`,确认 `reme` server 和工具已经连接。
+
+## Hook 与路径
+
+- MCP 配置:`integrations/claude_code/reme/.mcp.json`;
+- 自动记忆 Hook:`integrations/claude_code/reme/hooks/auto_memory.py`;
+- Hook 日志:`integrations/claude_code/reme/logs/auto_memory_hook.log`;
+- 默认 transcript 根目录:`~/.claude/projects`;
+- 可通过 `CLAUDE_CONFIG_DIR` 修改 transcript 根目录;
+- 可通过 `REME_HOST`、`REME_PORT` 覆盖 Hook 使用的服务地址。
+
+Hook 需要 `python3` 位于 `PATH`。MCP 工具名前缀可能随 Claude Code 版本包含 server segment;Skill 使用 `mcp__reme__*` 匹配这一差异。
+
+## 验证
+
+1. `reme health_check` 返回健康;
+2. Claude Code `/mcp` 显示 ReMe;
+3. `reme-memory` 能召回一条已存在记忆;
+4. 完成测试会话后,Hook 日志没有错误;
+5. 对应内容出现在当天 daily note 中。
+
+英文原始部署说明位于 `integrations/claude_code/README.md`。
diff --git a/docs/zh/integrations/hermes.md b/docs/zh/integrations/hermes.md
new file mode 100644
index 00000000..2371b1f8
--- /dev/null
+++ b/docs/zh/integrations/hermes.md
@@ -0,0 +1,59 @@
+---
+title: Hermes Agent 集成
+description: 使用 ReMe memory provider 在 Hermes 调用模型前召回、每轮结束后异步记录。
+---
+
+# Hermes Agent 集成
+
+Hermes memory provider 连接到一个已经运行的 ReMe HTTP 服务,在每次模型调用前召回相关记忆,并在用户/助手回合完成后异步调用 `auto_memory`。
+
+## Workspace 隔离
+
+ReMe 的搜索范围是一个完整 workspace。多个 Hermes profile 指向同一个 workspace 时会共享召回结果;需要隔离时,为每个 profile 使用独立 workspace 和端点。
+
+```bash
+reme start \
+ workspace_dir="/absolute/path/to/reme-hermes-default" \
+ service.backend=http \
+ service.host=127.0.0.1 \
+ service.port=2333
+```
+
+自动记忆需要 LLM;默认 BM25 搜索不需要 Embedding。
+
+## 安装与配置
+
+```bash
+hermes plugins install agentscope-ai/ReMe/integrations/hermes_agent
+hermes memory setup
+```
+
+选择 `reme`,接受默认的 `http://127.0.0.1:2333`,或输入上一步使用的端点。Setup 会先调用 `health_check`,只有新端点健康时才替换现有 provider 配置。
+
+配置存放在 `$HERMES_HOME/reme.json`:
+
+```json
+{
+ "endpoint": "http://127.0.0.1:2333",
+ "request_timeout": 600.0,
+ "recall_timeout": 5.0,
+ "health_timeout": 2.0,
+ "health_retry_seconds": 30.0,
+ "shutdown_timeout": 30.0,
+ "recall_limit": 5
+}
+```
+
+运行 `hermes memory status` 检查安装和配置。新的 Hermes 会话还会重新检查端点健康状态。
+
+## 生命周期和失败行为
+
+- `prefetch` 调用 ReMe `search`,Hermes 将结果放入受保护的 memory context;
+- `sync_turn` 把完成的回合加入串行后台写队列,再调用 `auto_memory`;
+- cron、flush 和 subagent context 不写入对话记忆;
+- 健康检查失败后,在 cooldown 结束前暂停召回和记录;
+- 召回与写入有独立 cooldown,单项失败不会关闭另一项;
+- 召回使用较短超时,避免慢搜索长期阻塞模型调用;
+- shutdown 会在有限时间内排空写队列,ReMe 服务仍由用户独立管理。
+
+英文权威安装说明位于 `integrations/hermes_agent/README.md`。
diff --git a/docs/zh/operations.md b/docs/zh/operations.md
new file mode 100644
index 00000000..43e4bcbd
--- /dev/null
+++ b/docs/zh/operations.md
@@ -0,0 +1,106 @@
+---
+title: 诊断、备份与恢复
+description: ReMe 服务健康检查、日志、索引维护、备份迁移和常见恢复流程。
+---
+
+# 诊断、备份与恢复
+
+ReMe 的恢复原则是:保护 workspace 中的用户文件,通过源文件重建索引、图谱和 catalog。不要为了修复索引而删除或改写用户记忆。
+
+## 快速诊断
+
+依次执行:
+
+```bash
+reme find_reme
+reme version
+reme health_check
+reme status
+reme app_config
+```
+
+- `find_reme`:服务是否存在,以及实际 host、port、PID;
+- `version`:CLI 能否成功访问服务;
+- `health_check`:组件健康状态;
+- `status`:状态组件的内存估算和进程 RSS;
+- `app_config`:隐藏密钥后的实际生效配置。
+
+## 日志
+
+`log_to_console` 和 `log_to_file` 控制日志目标。排查启动失败时先查看第一条异常,而不是后续客户端连接错误。
+
+常见类别:
+
+| 现象 | 优先检查 |
+|---|---|
+| CLI 找不到服务 | `reme find_reme`、启动目录、端口和进程状态 |
+| 自动记忆失败 | LLM backend、model、API key、base URL |
+| 只有 BM25 结果 | embedding 组件是否真正接入 `file_store` |
+| 新文件没有进入搜索 | 文件所在目录、后缀、watcher 和 `health_check` |
+| Studio 空白但 API 正常 | web extra、静态构建路径和浏览器控制台 |
+| 插件安装后不可用 | 当前 Python 解释器、`plugins` 配置、服务重启 |
+
+## 索引维护
+
+```bash
+reme reindex scope=all
+reme reindex scope=bm25
+reme reindex scope=embedding
+```
+
+`reindex` 从当前 `file_chunks` 重建 BM25 和/或 embedding 派生索引。它不会扫描 workspace、重新分块或重建 wikilink 图谱。
+
+如果问题发生在文件摄取阶段,应先确认后台 watcher 正常运行;不能把 `reindex` 当成通用“重新扫描”命令。
+
+Daily 索引页可单独重建:
+
+```bash
+reme daily_reindex date=2026-09-04
+```
+
+## 备份
+
+停止写入或停止服务后,优先备份整个 workspace。最重要的目录是:
+
+- `session/`:原始对话来源;
+- `resource/`:外部资料;
+- `daily/`:每日记忆;
+- `digest/`:长期记忆。
+
+`metadata/` 包含索引、图谱和 file catalog。一起备份可以加速恢复,但它不是唯一事实源。
+
+不要只备份进程目录下偶然生成的 `.reme/`;生产使用应明确设置稳定的绝对 `workspace_dir`。
+
+## 迁移 workspace
+
+1. 停止旧服务,避免迁移期间继续写入。
+2. 复制完整 workspace,并保留文件时间信息。
+3. 使用新的绝对路径启动:
+
+```bash
+reme start workspace_dir=/new/location/reme-memory
+```
+
+4. 运行 `health_check`、`status` 和一次代表性 `search`。
+5. 如果 embedding 模型或维度发生变化,再重建 embedding 索引。
+
+普通 Markdown 和资源文件可以使用版本控制或同步工具;包含敏感对话的 workspace 不应推送到公开仓库。
+
+## 从派生状态故障恢复
+
+在确认备份可用前,不要删除任何内容。恢复顺序应为:
+
+1. 保留 `session/`、`resource/`、`daily/` 和 `digest/`;
+2. 记录当前配置和组件 backend;
+3. 确认故障只发生在 `metadata/`;
+4. 将有问题的派生状态移到隔离备份位置;
+5. 用同一配置启动 ReMe,让 watcher 从源文件重建;
+6. 验证搜索、图谱和 Daily 索引。
+
+具体 metadata 文件属于实现细节,不应在自动化脚本里依赖其内部格式。
+
+## 并发编辑
+
+Studio 或其他编辑器保存完整文件时,应使用 `stat` 返回的 mtime 作为 `save.expected_mtime`。如果文件在打开后被外部修改,保存会失败,从而避免静默覆盖。
+
+文件 Job 会校验 workspace containment,并对同一路径加锁。不要绕过这些 Job 直接向不受控制的绝对路径写入。
diff --git a/docs/zh/plugin_development.md b/docs/zh/plugin_development.md
new file mode 100644
index 00000000..67a6d10b
--- /dev/null
+++ b/docs/zh/plugin_development.md
@@ -0,0 +1,101 @@
+---
+title: 插件开发
+description: 创建、注册、配置、测试和发布 ReMe 插件。
+---
+
+# 插件开发
+
+ReMe 插件是一个普通 Python distribution,通过 `reme.plugins` entry-point group 暴露 package-level `plugin.yaml`。插件可以注册新的 Step、Component backend,并提供默认 Application 配置。
+
+## 最小结构
+
+```text
+my-plugin/
+├── pyproject.toml
+└── src/my_plugin/
+ ├── __init__.py
+ ├── plugin.yaml
+ └── steps.py
+```
+
+`pyproject.toml`:
+
+```toml
+[project.entry-points."reme.plugins"]
+my-plugin = "my_plugin"
+```
+
+`plugin.yaml`:
+
+```yaml
+name: my-plugin
+backends:
+ my_step: my_plugin.steps:MyStep
+application_defaults:
+ jobs:
+ my_action:
+ backend: base
+ description: Run my plugin action
+ parameters:
+ type: object
+ properties:
+ text: { type: string }
+ required: [text]
+ steps:
+ - backend: my_step
+```
+
+## 实现 Step
+
+```python
+from reme.components.component_registry import R
+from reme.steps.base_step import BaseStep
+
+
+@R.register("my_step")
+class MyStep(BaseStep):
+ async def execute(self):
+ self.context.response.answer = self.context.data["text"]
+```
+
+Step 实例属于单次 Job 调用。跨调用的内存状态应放在带命名空间的 `app_context.metadata`;需要生命周期、锁或持久化时,应升级为 Component 或 workspace 文件。
+
+## 配置合并
+
+`application_defaults` 是不完整的 `ApplicationConfig`。合并顺序为:
+
+```text
+插件默认值 < 选中/default 配置 < CLI 覆盖
+```
+
+插件不应自动修改用户的配置文件。只有在 Application 的 `plugins` 列表中显式启用后,插件 backend 才会加入该 Application 的局部 registry。
+
+## 本地验证
+
+```bash
+reme plugins validate ./path/to/my-plugin
+reme plugins install ./path/to/my-plugin --editable
+reme plugins list
+reme plugins show my-plugin
+reme start plugins='["my-plugin"]'
+reme my_action text=hello
+```
+
+校验会导入插件代码,因此只应对可信源码执行。
+
+## 测试边界
+
+- 使用 `tmp_path` 创建 workspace;
+- Mock 网络、模型和子进程;
+- 验证插件未启用时不会污染 built-in registry;
+- 验证默认配置与显式配置的合并优先级;
+- 验证后台任务、客户端和 executor 都由 Component 生命周期关闭;
+- 验证失败不会删除或重写用户源文件。
+
+仓库中的 `plugins/daily_paper`、`plugins/auto-fin`、`plugins/lme` 和 `plugins/beam` 是完整参考实现。
+
+## 兼容性
+
+迁移期间仍兼容旧的 Python Plugin descriptor 和 `reme.configs` entry point,但新插件应使用 `plugin.yaml`。不要依赖进程级全局 enable/disable 状态;插件启用始终属于具体 Application 配置。
+
+包管理命令、升级与卸载行为见[插件管理](./plugin_management.md)。
diff --git a/docs/zh/quick_start.md b/docs/zh/quick_start.md
index ee41626a..d7f7a43c 100644
--- a/docs/zh/quick_start.md
+++ b/docs/zh/quick_start.md
@@ -1,5 +1,12 @@
+---
+title: 快速开始
+description: 安装并启动 ReMe,完成文件写入、检索和自动记忆的第一个闭环。
+---
+
# 快速开始
+本页用于完成第一次可运行闭环。需要完整配置字段时查看[基础配置](./configuration.md);接入 HTTP 或 MCP 时查看[服务与部署](./services.md)。
+
## 安装
ReMe 要求 Python 3.11+。
@@ -228,3 +235,5 @@ reme start \
```bash
reme start config=/path/to/custom.yaml
```
+
+下一步可以查看 [CLI 参考](./reference/cli.md)、[Job API 参考](./reference/jobs.md)和[诊断、备份与恢复](./operations.md)。
diff --git a/docs/zh/reference/cli.md b/docs/zh/reference/cli.md
new file mode 100644
index 00000000..3caa7cde
--- /dev/null
+++ b/docs/zh/reference/cli.md
@@ -0,0 +1,87 @@
+---
+title: CLI 参考
+description: ReMe 命令行语法、服务调用、配置覆盖与插件命令。
+---
+
+# CLI 参考
+
+ReMe 的基本语法是:
+
+```text
+reme ACTION key=value ...
+```
+
+## 启动应用
+
+```bash
+reme start
+reme start config=demo
+reme start workspace_dir=/data/reme service.port=8181
+reme start job=search query="关键词" limit=5
+```
+
+`start job=` 运行一次性 Job;普通 `start` 启动配置中的 Service。
+
+## 调用 Job
+
+服务运行后,Action 名就是 Job 名:
+
+```bash
+reme help
+reme health_check
+reme search query="项目决策" limit=10
+reme read path=digest/wiki/project.md start_line=1 end_line=80
+```
+
+复杂值使用 JSON:
+
+```bash
+reme auto_memory \
+ session_id=example \
+ messages='[{"role":"user","content":"记住这条偏好"}]'
+```
+
+服务选择参数 `backend`、`transport`、`host`、`port`、`timeout`、`command`、`args` 和 `show_metadata` 只用于构造客户端,不会泄漏到 Job 参数。
+
+## 配置覆盖
+
+```bash
+reme start \
+ config=/path/to/custom.yaml \
+ service.port=8181 \
+ service.web_enabled=false \
+ plugins='["auto-fin"]'
+```
+
+参数前的 `-` 或 `--` 可以省略。嵌套键使用点号,数组和对象使用 JSON。
+
+## 服务发现
+
+```bash
+reme find_reme
+```
+
+成功时输出可复用的服务信息;找不到服务时不会自动启动新进程。
+
+## 插件命令
+
+插件包管理是本地命令,不经过 HTTP 或 MCP:
+
+```bash
+reme plugins list
+reme plugins show auto-fin
+reme plugins validate auto-fin
+reme plugins install reme-auto-fin
+reme plugins uninstall auto-fin
+```
+
+完整说明见[插件管理](../plugin_management.md)。
+
+## 发现当前能力
+
+默认 Job 参数见 [Job API 参考](./jobs.md)。运行配置可能由插件和自定义 YAML 改变,因此自动化程序应优先调用:
+
+```bash
+reme help
+reme app_config
+```
diff --git a/docs/zh/services.md b/docs/zh/services.md
new file mode 100644
index 00000000..9cfea053
--- /dev/null
+++ b/docs/zh/services.md
@@ -0,0 +1,131 @@
+---
+title: 服务与部署
+description: 使用 ReMe 的 HTTP、SSE、MCP 和 Studio 服务,并理解默认安全边界。
+---
+
+# 服务与部署
+
+ReMe 可以作为本地 HTTP 服务、独立 MCP Server 或一次性 CLI Job 运行。默认模式是在 `127.0.0.1:2333` 启动 HTTP 服务,并在同一进程中提供 JSON API、SSE、MCP 与可选的 ReMe Studio。
+
+## HTTP 服务
+
+```bash
+reme start
+reme start service.host=127.0.0.1 service.port=8181
+```
+
+普通 Job 暴露为 `POST /`:
+
+```bash
+curl -s http://127.0.0.1:2333/search \
+ -H 'Content-Type: application/json' \
+ -d '{"query":"用户偏好","limit":5}'
+```
+
+请求体允许 Job 参数位于顶层。响应遵循 `Response`:
+
+```json
+{
+ "success": true,
+ "answer": "...",
+ "metadata": {}
+}
+```
+
+未被 Step 捕获的错误会转换成 `success: false` 的响应。
+
+## Streaming 与 SSE
+
+`backend: stream` 的 Job 仍使用 `POST /`,但响应类型是 `text/event-stream`。每个 chunk 使用统一的 streaming schema;失败时会发出错误 chunk,并以终止事件结束。
+
+默认 `chat` 是 Stream Job:
+
+```bash
+curl -N http://127.0.0.1:2333/chat \
+ -H 'Content-Type: application/json' \
+ -d '{"query":"总结我的长期偏好"}'
+```
+
+MCP 不暴露 Stream Job。
+
+## MCP
+
+默认 HTTP 服务会在 `/mcp` 挂载 streamable HTTP MCP:
+
+```yaml
+service:
+ backend: http
+ mcp_enabled: true
+ mcp_path: /mcp
+ mcp_stateless_http: false
+```
+
+也可以改用独立 MCP Service:
+
+```bash
+reme start service.backend=mcp service.transport=stdio
+reme start service.backend=mcp service.transport=sse service.port=2333
+reme start service.backend=mcp service.transport=streamable-http service.port=2333
+```
+
+MCP tool 来自 `enable_serve: true` 的非流式 Job。`service.jobs` 可以设置允许列表;`injected_job_kwargs` 可以注入服务端管理、调用方不能覆盖的参数。
+
+```yaml
+service:
+ backend: http
+ jobs: [search, read, traverse, auto_memory]
+ injected_job_kwargs:
+ tenant_id: local-user
+ tool_error_on_failure: true
+```
+
+## ReMe Studio
+
+安装 `reme-ai[web]` 或 `reme-ai[core]` 后,默认 HTTP 地址同时提供 ReMe Studio:
+
+```text
+http://127.0.0.1:2333/
+```
+
+可通过配置关闭或指定自定义构建:
+
+```yaml
+service:
+ web_enabled: false
+ # web_static_dir: /absolute/path/to/static
+```
+
+静态资源缺失不会阻止 Job API 启动。
+
+## 一次性 Job
+
+需要脚本式执行而不常驻服务时:
+
+```bash
+reme start job=search query="用户偏好" limit=5
+```
+
+它会切换到一次性 CLI Service,但仍经过正常的 Application、Component 和 Job 生命周期。
+
+## 服务发现
+
+```bash
+reme find_reme
+```
+
+ReMe 会记录本机运行服务的启动参数。普通 `reme ` 优先使用实际运行服务的 backend、host、port 和 transport;找不到运行服务时才回退到本地配置。
+
+## 安全边界
+
+ReMe 默认定位为本地服务:
+
+- 默认绑定 `127.0.0.1`;
+- HTTP CORS 配置允许任意 origin;
+- Job 可进行文件写入、移动和删除;
+- 当前服务层不提供通用用户认证。
+
+不要直接把默认服务暴露到公网。需要远程访问时,在受控网络或带身份认证、TLS、访问控制和请求大小限制的反向代理后部署,并通过 `service.jobs` 只开放必要 Job。
+
+## OpenAPI
+
+HTTP 服务使用 FastAPI。启用 HTTP 服务时,可以通过 `/docs`、`/redoc` 和 `/openapi.json` 查看当前配置实际注册的端点;Studio 的 SPA fallback 不会覆盖这些保留路径。
diff --git a/github-pages/README.md b/github-pages/README.md
index 2be3e6a4..c4b09810 100644
--- a/github-pages/README.md
+++ b/github-pages/README.md
@@ -1,8 +1,8 @@
-# ReMe GitHub Pages
+# ReMe documentation site
-This directory contains the standalone Vite documentation site published at . The
-GitHub Pages fallback is . It does not depend on the ReMe Studio application in
-`reme_studio/`.
+This package builds the VitePress site published at . The canonical documentation lives in
+`docs/`; selected product, integration, plugin, and benchmark READMEs are mirrored into a disposable source tree during
+the build. Do not edit `.generated/` or `dist/`.
## Requirements
@@ -11,79 +11,41 @@ GitHub Pages fallback is . It does not de
## Local development
-From the repository root:
-
```bash
cd github-pages
-npm install
+npm ci
npm run dev
```
-Open the URL printed by Vite, normally . The development server watches the frontend source.
-When a repository Markdown file changes, restart the development command to regenerate the documentation content.
+The development server prints its local URL. Restart it after changing a mirrored README or `reme/config/default.yaml`
+so the generated source tree and Job reference are refreshed. Changes under `docs/` are also refreshed on restart.
-For subsequent installs or CI-compatible dependency installation, use:
-
-```bash
-npm ci
-```
-
-## Preview the production build
-
-Build and start the preview server:
+## Validation
```bash
+npm test
npm run build
npm run preview
```
-Open the URL printed by Vite, normally . Production assets use relative paths so the same build
-works on both the custom domain and the GitHub Pages project path.
+The test suite verifies bilingual core pages, canonical-source mappings, generated Job coverage, and disposable output.
+The production build is written to `github-pages/dist/` for the existing GitHub Pages workflow.
-The generated `dist/` and `.generated/` directories are disposable build output and are excluded from Git.
+## Sources
-## Documentation sources
-
-The build script reads the canonical repository files directly. Do not edit generated copies under `.generated/` or
-`dist/`.
-
-- `README.md` and `README_ZH.md`: project introductions
-- `docs/en/` and `docs/zh/`: English and Chinese guides
-- `docs/figure/`: documentation images
-- `reme_studio/README.md` and `reme_studio/README_ZH.md`: ReMe Studio guide
-- `typescript/README.md` and `typescript/README_ZH.md`: TypeScript client, DeepSeek Harness, and OpenClaw integration guide
+- `docs/`: canonical guides, VitePress configuration, theme, and brand assets
+- `reme/config/default.yaml`: generated callable Job reference
+- `reme_studio/README*.md`: ReMe Studio
+- `typescript/README*.md`: TypeScript client and adapters
- `plugins/*/README*.md`: plugin guides
-- `benchmark/{beam,longmemeval,pibench,toolmemory}/README*.md`: benchmark guides and results
-- `AGENTS.md`: repository development guide
+- `benchmark/*/README*.md`: benchmark guides
+- `scripts/generate-content.mjs`: source mirroring and reference generation
-To add or reorganize a document in the site navigation, update
-[`scripts/generate-content.mjs`](./scripts/generate-content.mjs). Presentation and interaction code lives in `src/`.
-
-## Project structure
-
-```text
-github-pages/
-├── index.html
-├── package.json
-├── scripts/
-│ └── generate-content.mjs
-├── src/
-│ ├── main.js
-│ └── styles.css
-└── vite.config.js
-```
+When adding a canonical guide, add both `docs/zh/.md` and `docs/en/.md`, then include it in the appropriate
+sidebar in `docs/.vitepress/config.mts`. Add repository-owned READMEs to `externalDocuments` in the generator rather than
+duplicating their full content under `docs/`.
## Deployment
-The repository workflow `.github/workflows/deploy-docs.yml` builds this directory and publishes `dist/` to GitHub Pages.
-It runs after relevant documentation or site files change on `main`, and it can also be started manually from the
-GitHub Actions page.
-
-The repository's **Settings → Pages → Build and deployment → Source** must be set to **GitHub Actions**. Its custom
-domain must be set to `reme.agentscope.io`; `public/CNAME` preserves that domain in the published artifact.
-
-Useful links:
-
-- ReMe documentation:
-- GitHub Pages fallback:
-- ReMe repository:
+`.github/workflows/deploy-docs.yml` uses the reusable documentation build workflow and publishes `dist/` to GitHub
+Pages. `public/CNAME` preserves the `reme.agentscope.io` custom domain.
diff --git a/github-pages/index.html b/github-pages/index.html
deleted file mode 100644
index 3655d5ee..00000000
--- a/github-pages/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
- ReMe Documentation
-
-
-
-
-
-
diff --git a/github-pages/package-lock.json b/github-pages/package-lock.json
index 726cc77f..48930a39 100644
--- a/github-pages/package-lock.json
+++ b/github-pages/package-lock.json
@@ -7,21 +7,377 @@
"": {
"name": "reme-github-pages",
"version": "0.1.0",
- "dependencies": {
- "dompurify": "^3.2.6",
- "marked": "^16.2.1"
- },
"devDependencies": {
- "vite": "^7.1.1"
+ "vitepress": "1.6.4",
+ "yaml": "^2.8.1"
},
"engines": {
"node": ">=22.13.0"
}
},
+ "node_modules/@algolia/abtesting": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.23.0.tgz",
+ "integrity": "sha512-j45MBISstltys9QyQ4xf6quRiN1g7vMuwQL9VM4dx8YuRZvCQ173b9royZAx6iAbRX3IB1VnG1z//NuwyQ8jpQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/autocomplete-core": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz",
+ "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-plugin-algolia-insights": "1.17.7",
+ "@algolia/autocomplete-shared": "1.17.7"
+ }
+ },
+ "node_modules/@algolia/autocomplete-plugin-algolia-insights": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz",
+ "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "search-insights": ">= 1 < 3"
+ }
+ },
+ "node_modules/@algolia/autocomplete-preset-algolia": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz",
+ "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/autocomplete-shared": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz",
+ "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/client-abtesting": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.57.0.tgz",
+ "integrity": "sha512-JVFFujiZUCguk5tz3LZr4fTQxqpIrj4/Jw3SI7kMljSqtfLxYn/s/TWH0J2s4iNfsDpxPhgFGMotCpmDI4kZ8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-analytics": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.57.0.tgz",
+ "integrity": "sha512-6KqECK4ED3JJQEoDrQWnGPQzElA828xAD4qK5ceawNNyP/LcSvzAoLHjFkoTPksZ/kxj6VUtCRH+IHZesLltng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-common": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.57.0.tgz",
+ "integrity": "sha512-uqpGF3oXYsoCbQq5d7BzNrNTfIfuvJyGP1CKvSW27T9boUg7KOwyxsAw1AX0a3jSW2HrYEJ/NN+Z4MiGivbpeQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-insights": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.57.0.tgz",
+ "integrity": "sha512-u5NboJVJXDEFplvNnqqX4CxkXPYysjJRj47hOSh9329H8kG5gFLKJBIiS5utMQ+GZm8xQl3Te7NInDk6elEADQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-personalization": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.57.0.tgz",
+ "integrity": "sha512-uzc0b2LmHAK9/QID4xeo35OG84AkZl4YewkCqawqAOGLjT2eZpM/OZx45ESygMHG30Ws+ZTSdluPtMJcUnrbWQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-query-suggestions": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.57.0.tgz",
+ "integrity": "sha512-dIAhnM6ue/ssa5PjgNfu4g8A4yTojl9ZOUzZU3wIaIKRerL2R/3Emuf9n/D6ICXXP167KC6XCeC7nliSw7cuSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-search": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.57.0.tgz",
+ "integrity": "sha512-2TTPTTKSJmCptvhCm4Xf3bBYMqZni+Pgc2hVdqc4l9wsBpSJNVTVIKpnd10OubUgkGcmppVDj1XQqYaf6EnPSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/ingestion": {
+ "version": "1.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.57.0.tgz",
+ "integrity": "sha512-W4JseHKt+pzOxlFV+T3MWEG0h4Z2Se5zjoXUD0ewlw8aOWMG/yjRdopUdLQsXULepB/My2tDuZjkwk2sMfsUrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/monitoring": {
+ "version": "1.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.57.0.tgz",
+ "integrity": "sha512-BrxJVE0/eLinEPICCD7BKN/2xnt0nkjge70u8zzE2ISP3fuB3tjLgcwpanUycvlHBFLI4gK0l5ol54p6IYuR/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/recommend": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.57.0.tgz",
+ "integrity": "sha512-Gc29jkeiLKlVfHvyrIgyUHHE+aYTdXEeLfK42rjr5/1TTVsYwUJz0XkvoIBIqfMjcDg6gXeHb1jTUZ0H+SYIlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-browser-xhr": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.57.0.tgz",
+ "integrity": "sha512-PIPnPN7MP3fp2VAi01BVXhCWmD366ZB2Hkq5TlYKtThd4KxUtMmaaNDpFgVCTXtSIqWVZLJntOHRvxg/sIPd8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-fetch": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.57.0.tgz",
+ "integrity": "sha512-AX3RlOudXMdTwtwUqdAf5hAVLvXfOZZH1FZh6ALDdrhVLT0TtAIe48N6nYcWcTnwoTxK/wDIQqZ19IMjK8zJAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-node-http": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.57.0.tgz",
+ "integrity": "sha512-cWZc1dKb7wy9/wPpwMtL1y89gK2G7y2A47Coa7zwf1ydtIeJm4+S+XxoQ2b/ZRiQnrC1YHavLjYUPDCdnT7Khg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.8"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@docsearch/css": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz",
+ "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@docsearch/js": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz",
+ "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/react": "3.8.2",
+ "preact": "^10.0.0"
+ }
+ },
+ "node_modules/@docsearch/react": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz",
+ "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-core": "1.17.7",
+ "@algolia/autocomplete-preset-algolia": "1.17.7",
+ "@docsearch/css": "3.8.2",
+ "algoliasearch": "^5.14.2"
+ },
+ "peerDependencies": {
+ "@types/react": ">= 16.8.0 < 19.0.0",
+ "react": ">= 16.8.0 < 19.0.0",
+ "react-dom": ">= 16.8.0 < 19.0.0",
+ "search-insights": ">= 1 < 3"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "search-insights": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
- "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
"cpu": [
"ppc64"
],
@@ -32,13 +388,13 @@
"aix"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
- "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
@@ -49,13 +405,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
- "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
@@ -66,13 +422,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
- "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
@@ -83,13 +439,13 @@
"android"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
- "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
@@ -100,13 +456,13 @@
"darwin"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
- "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
@@ -117,13 +473,13 @@
"darwin"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
- "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
@@ -134,13 +490,13 @@
"freebsd"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
- "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
@@ -151,13 +507,13 @@
"freebsd"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
- "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
@@ -168,13 +524,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
- "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
@@ -185,13 +541,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
- "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
@@ -202,13 +558,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
- "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
@@ -219,13 +575,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
- "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
@@ -236,13 +592,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
- "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
@@ -253,13 +609,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
- "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
@@ -270,13 +626,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
- "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
@@ -287,13 +643,13 @@
"linux"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
- "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
@@ -304,30 +660,13 @@
"linux"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
- "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
- "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
@@ -338,30 +677,13 @@
"netbsd"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
- "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
- "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
@@ -372,30 +694,13 @@
"openbsd"
],
"engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
- "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
- "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
@@ -406,13 +711,13 @@
"sunos"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
- "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
@@ -423,13 +728,13 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
- "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
@@ -440,13 +745,13 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
- "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
@@ -457,9 +762,33 @@
"win32"
],
"engines": {
- "node": ">=18"
+ "node": ">=12"
}
},
+ "node_modules/@iconify-json/simple-icons": {
+ "version": "1.2.94",
+ "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.94.tgz",
+ "integrity": "sha512-l8UWzVxKaqZd9ABsE/M/9p6NyGkQnmCnOoZyhQmjlXCtY5PuL2rcWxOFk2l9pk7ux3ERMPkTLE4jl6kQpTkwxA==",
+ "dev": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@napi-rs/lzma-linux-x64-gnu": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz",
@@ -827,6 +1156,93 @@
"win32"
]
},
+ "node_modules/@shikijs/core": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz",
+ "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.4"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz",
+ "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^3.1.0"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz",
+ "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz",
+ "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz",
+ "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/transformers": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz",
+ "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz",
+ "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -834,26 +1250,483 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "node_modules/@types/hast": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz",
+ "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==",
+ "dev": true,
"license": "MIT",
- "optional": true
+ "dependencies": {
+ "@types/unist": "*"
+ }
},
- "node_modules/dompurify": {
- "version": "3.4.13",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz",
- "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==",
- "license": "(MPL-2.0 OR Apache-2.0)",
- "optionalDependencies": {
- "@types/trusted-types": "^2.0.7"
+ "node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "14.2.0",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.2.0.tgz",
+ "integrity": "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz",
+ "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz",
+ "integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.8",
+ "@vue/shared": "3.5.42",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz",
+ "integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.42",
+ "@vue/shared": "3.5.42"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz",
+ "integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.8",
+ "@vue/compiler-core": "3.5.42",
+ "@vue/compiler-dom": "3.5.42",
+ "@vue/compiler-ssr": "3.5.42",
+ "@vue/shared": "3.5.42",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.19",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz",
+ "integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.42",
+ "@vue/shared": "3.5.42"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "7.7.10",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz",
+ "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-kit": "^7.7.10"
+ }
+ },
+ "node_modules/@vue/devtools-kit": {
+ "version": "7.7.10",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz",
+ "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-shared": "^7.7.10",
+ "birpc": "^2.3.0",
+ "hookable": "^5.5.3",
+ "mitt": "^3.0.1",
+ "perfect-debounce": "^1.0.0",
+ "speakingurl": "^14.0.1",
+ "superjson": "^2.2.2"
+ }
+ },
+ "node_modules/@vue/devtools-shared": {
+ "version": "7.7.10",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz",
+ "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rfdc": "^1.4.1"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.42.tgz",
+ "integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.42"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.42.tgz",
+ "integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.42",
+ "@vue/shared": "3.5.42"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz",
+ "integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.42",
+ "@vue/runtime-core": "3.5.42",
+ "@vue/shared": "3.5.42",
+ "csstype": "^3.2.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.42.tgz",
+ "integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.42",
+ "@vue/runtime-dom": "3.5.42",
+ "@vue/shared": "3.5.42"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz",
+ "integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vueuse/core": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz",
+ "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/integrations": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz",
+ "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vueuse/core": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "async-validator": "^4",
+ "axios": "^1",
+ "change-case": "^5",
+ "drauu": "^0.4",
+ "focus-trap": "^7",
+ "fuse.js": "^7",
+ "idb-keyval": "^6",
+ "jwt-decode": "^4",
+ "nprogress": "^0.2",
+ "qrcode": "^1.5",
+ "sortablejs": "^1",
+ "universal-cookie": "^7"
+ },
+ "peerDependenciesMeta": {
+ "async-validator": {
+ "optional": true
+ },
+ "axios": {
+ "optional": true
+ },
+ "change-case": {
+ "optional": true
+ },
+ "drauu": {
+ "optional": true
+ },
+ "focus-trap": {
+ "optional": true
+ },
+ "fuse.js": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "jwt-decode": {
+ "optional": true
+ },
+ "nprogress": {
+ "optional": true
+ },
+ "qrcode": {
+ "optional": true
+ },
+ "sortablejs": {
+ "optional": true
+ },
+ "universal-cookie": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz",
+ "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz",
+ "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/algoliasearch": {
+ "version": "5.57.0",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.57.0.tgz",
+ "integrity": "sha512-HpND7MBGctOAkd1GoQoDZCGoCpqNTS5NG1LuhElFet3RdLJkwnyTYZXZhXwtpAQPrI36fqQ3eT6KQrdKDTKu3A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/abtesting": "1.23.0",
+ "@algolia/client-abtesting": "5.57.0",
+ "@algolia/client-analytics": "5.57.0",
+ "@algolia/client-common": "5.57.0",
+ "@algolia/client-insights": "5.57.0",
+ "@algolia/client-personalization": "5.57.0",
+ "@algolia/client-query-suggestions": "5.57.0",
+ "@algolia/client-search": "5.57.0",
+ "@algolia/ingestion": "1.57.0",
+ "@algolia/monitoring": "1.57.0",
+ "@algolia/recommend": "5.57.0",
+ "@algolia/requester-browser-xhr": "5.57.0",
+ "@algolia/requester-fetch": "5.57.0",
+ "@algolia/requester-node-http": "5.57.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/birpc": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz",
+ "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/copy-anything": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.1.0.tgz",
+ "integrity": "sha512-ufbM3smX/Jbnpk5wcQjzd1MgBpzmqfNETUAyZNrGwU9foRlyHoGzMMBBCRzEhQLBjZfFDE1W2ufPXX2vdWkV8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/emoji-regex-xs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
+ "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/esbuild": {
- "version": "0.28.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
- "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -861,53 +1734,49 @@
"esbuild": "bin/esbuild"
},
"engines": {
- "node": ">=18"
+ "node": ">=12"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.28.2",
- "@esbuild/android-arm": "0.28.2",
- "@esbuild/android-arm64": "0.28.2",
- "@esbuild/android-x64": "0.28.2",
- "@esbuild/darwin-arm64": "0.28.2",
- "@esbuild/darwin-x64": "0.28.2",
- "@esbuild/freebsd-arm64": "0.28.2",
- "@esbuild/freebsd-x64": "0.28.2",
- "@esbuild/linux-arm": "0.28.2",
- "@esbuild/linux-arm64": "0.28.2",
- "@esbuild/linux-ia32": "0.28.2",
- "@esbuild/linux-loong64": "0.28.2",
- "@esbuild/linux-mips64el": "0.28.2",
- "@esbuild/linux-ppc64": "0.28.2",
- "@esbuild/linux-riscv64": "0.28.2",
- "@esbuild/linux-s390x": "0.28.2",
- "@esbuild/linux-x64": "0.28.2",
- "@esbuild/netbsd-arm64": "0.28.2",
- "@esbuild/netbsd-x64": "0.28.2",
- "@esbuild/openbsd-arm64": "0.28.2",
- "@esbuild/openbsd-x64": "0.28.2",
- "@esbuild/openharmony-arm64": "0.28.2",
- "@esbuild/sunos-x64": "0.28.2",
- "@esbuild/win32-arm64": "0.28.2",
- "@esbuild/win32-ia32": "0.28.2",
- "@esbuild/win32-x64": "0.28.2"
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
}
},
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/focus-trap": {
+ "version": "7.8.0",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz",
+ "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
+ "dependencies": {
+ "tabbable": "^6.4.0"
}
},
"node_modules/fsevents": {
@@ -925,18 +1794,209 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/marked": {
- "version": "16.4.2",
- "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
- "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "dev": true,
"license": "MIT",
- "bin": {
- "marked": "bin/marked.js"
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
},
- "engines": {
- "node": ">= 20"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/mark.js": {
+ "version": "8.11.1",
+ "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
+ "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+ "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/minisearch": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz",
+ "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nanoid": {
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
@@ -956,6 +2016,25 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/oniguruma-to-es": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz",
+ "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex-xs": "^1.0.0",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
+ "node_modules/perfect-debounce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -963,19 +2042,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/picomatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
- "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
"node_modules/postcss": {
"version": "8.5.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
@@ -1005,6 +2071,70 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/preact": {
+ "version": "10.29.8",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.8.tgz",
+ "integrity": "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ },
+ "peerDependencies": {
+ "preact-render-to-string": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "preact-render-to-string": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/property-information": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz",
+ "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz",
+ "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/rollup": {
"version": "4.62.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz",
@@ -1051,6 +2181,31 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/search-insights": {
+ "version": "2.17.3",
+ "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
+ "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/shiki": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz",
+ "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/langs": "2.5.0",
+ "@shikijs/themes": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -1061,42 +2216,192 @@
"node": ">=0.10.0"
}
},
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/speakingurl": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/superjson": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
+ "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz",
+ "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+ "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+ "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+ "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
"node_modules/vite": {
- "version": "7.3.6",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz",
- "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==",
+ "version": "5.4.21",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "esbuild": "^0.27.0 || ^0.28.0",
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3",
- "postcss": "^8.5.6",
- "rollup": "^4.43.0",
- "tinyglobby": "^0.2.15"
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
- "node": "^20.19.0 || >=22.12.0"
+ "node": "^18.0.0 || >=20.0.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
@@ -1105,25 +2410,19 @@
"fsevents": "~2.3.3"
},
"peerDependencies": {
- "@types/node": "^20.19.0 || >=22.12.0",
- "jiti": ">=1.21.0",
- "less": "^4.0.0",
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
"lightningcss": "^1.21.0",
- "sass": "^1.70.0",
- "sass-embedded": "^1.70.0",
- "stylus": ">=0.54.8",
- "sugarss": "^5.0.0",
- "terser": "^5.16.0",
- "tsx": "^4.8.1",
- "yaml": "^2.4.2"
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
- "jiti": {
- "optional": true
- },
"less": {
"optional": true
},
@@ -1144,14 +2443,99 @@
},
"terser": {
"optional": true
- },
- "tsx": {
+ }
+ }
+ },
+ "node_modules/vitepress": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz",
+ "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/css": "3.8.2",
+ "@docsearch/js": "3.8.2",
+ "@iconify-json/simple-icons": "^1.2.21",
+ "@shikijs/core": "^2.1.0",
+ "@shikijs/transformers": "^2.1.0",
+ "@shikijs/types": "^2.1.0",
+ "@types/markdown-it": "^14.1.2",
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@vue/devtools-api": "^7.7.0",
+ "@vue/shared": "^3.5.13",
+ "@vueuse/core": "^12.4.0",
+ "@vueuse/integrations": "^12.4.0",
+ "focus-trap": "^7.6.4",
+ "mark.js": "8.11.1",
+ "minisearch": "^7.1.1",
+ "shiki": "^2.1.0",
+ "vite": "^5.4.14",
+ "vue": "^3.5.13"
+ },
+ "bin": {
+ "vitepress": "bin/vitepress.js"
+ },
+ "peerDependencies": {
+ "markdown-it-mathjax3": "^4",
+ "postcss": "^8"
+ },
+ "peerDependenciesMeta": {
+ "markdown-it-mathjax3": {
"optional": true
},
- "yaml": {
+ "postcss": {
"optional": true
}
}
+ },
+ "node_modules/vue": {
+ "version": "3.5.42",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.42.tgz",
+ "integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.42",
+ "@vue/compiler-sfc": "3.5.42",
+ "@vue/runtime-dom": "3.5.42",
+ "@vue/server-renderer": "3.5.42",
+ "@vue/shared": "3.5.42"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
}
}
}
diff --git a/github-pages/package.json b/github-pages/package.json
index 4ace932f..a9a0eb6d 100644
--- a/github-pages/package.json
+++ b/github-pages/package.json
@@ -7,16 +7,14 @@
"node": ">=22.13.0"
},
"scripts": {
- "dev": "node scripts/generate-content.mjs && vite",
- "build": "node scripts/generate-content.mjs && vite build",
- "preview": "vite preview",
- "test": "node scripts/generate-content.mjs && node --test tests/*.test.mjs"
- },
- "dependencies": {
- "dompurify": "^3.2.6",
- "marked": "^16.2.1"
+ "content": "node scripts/generate-content.mjs",
+ "dev": "npm run content && vitepress dev .generated/site",
+ "build": "npm run content && vitepress build .generated/site --outDir dist && node scripts/verify-build.mjs",
+ "preview": "vitepress preview .generated/site --outDir dist",
+ "test": "npm run content && node --test tests/*.test.mjs"
},
"devDependencies": {
- "vite": "^7.1.1"
+ "vitepress": "1.6.4",
+ "yaml": "^2.8.1"
}
}
diff --git a/github-pages/scripts/generate-content.mjs b/github-pages/scripts/generate-content.mjs
index 05054730..1a01f1f5 100644
--- a/github-pages/scripts/generate-content.mjs
+++ b/github-pages/scripts/generate-content.mjs
@@ -1,249 +1,191 @@
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
+import { parse as parseYaml } from "yaml";
const siteDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const repoDir = path.resolve(siteDir, "..");
-const outputDir = path.join(siteDir, ".generated", "content");
+const outputDir = path.join(siteDir, ".generated", "site");
-const navigationGroupOrder = [
- "overview",
- "start",
- "integration",
- "fundamentals",
- "automation",
- "concepts",
- "workspace",
- "plugins",
- "benchmarks",
- "development",
+const externalDocuments = [
+ ["en/integrations/claude-code.md", "integrations/claude_code/README.md"],
+ ["en/integrations/hermes.md", "integrations/hermes_agent/README.md"],
+ ["zh/integrations/typescript.md", "typescript/README_ZH.md"],
+ ["en/integrations/typescript.md", "typescript/README.md"],
+ ["zh/workspace/studio.md", "reme_studio/README_ZH.md"],
+ ["en/workspace/studio.md", "reme_studio/README.md"],
+ ["zh/plugins/daily-paper.md", "plugins/daily_paper/README_ZH.md"],
+ ["en/plugins/daily-paper.md", "plugins/daily_paper/README.md"],
+ ["zh/plugins/auto-fin.md", "plugins/auto-fin/README_ZH.md"],
+ ["en/plugins/auto-fin.md", "plugins/auto-fin/README.md"],
+ ["zh/plugins/lme.md", "plugins/lme/README_ZH.md"],
+ ["en/plugins/lme.md", "plugins/lme/README.md"],
+ ["zh/plugins/beam.md", "plugins/beam/README_ZH.md"],
+ ["en/plugins/beam.md", "plugins/beam/README.md"],
+ ["zh/benchmarks/beam.md", "benchmark/beam/README_ZH.md"],
+ ["en/benchmarks/beam.md", "benchmark/beam/README.md"],
+ ["zh/benchmarks/longmemeval.md", "benchmark/longmemeval/README_ZH.md"],
+ ["en/benchmarks/longmemeval.md", "benchmark/longmemeval/README.md"],
+ ["zh/benchmarks/pibench.md", "benchmark/pibench/README_ZH.md"],
+ ["en/benchmarks/pibench.md", "benchmark/pibench/README.md"],
+ ["zh/benchmarks/toolmemory.md", "benchmark/toolmemory/README_ZH.md"],
+ ["en/benchmarks/toolmemory.md", "benchmark/toolmemory/README.md"],
];
-const topicOrder = [
- "quick_start",
- "plugin_management",
- "memory_as_file",
- "memory_search",
- "auto_memory",
- "auto_resource",
- "auto_link",
- "auto_dream",
- "proactive",
- "reme_scene",
- "framework",
- "reme-blog",
- "contributing",
-];
-
-const groups = {
- quick_start: "start",
- plugin_management: "start",
- memory_as_file: "fundamentals",
- memory_search: "fundamentals",
- auto_memory: "automation",
- auto_resource: "automation",
- auto_link: "automation",
- auto_dream: "automation",
- proactive: "automation",
- reme_scene: "concepts",
- framework: "concepts",
- "reme-blog": "concepts",
- contributing: "development",
+const groupNames = {
+ zh: {
+ system: "系统与诊断",
+ memory: "记忆演化",
+ retrieval: "检索与图谱",
+ daily: "Daily Note",
+ files: "文件操作",
+ },
+ en: {
+ system: "System and diagnostics",
+ memory: "Memory evolution",
+ retrieval: "Retrieval and graph",
+ daily: "Daily notes",
+ files: "File operations",
+ },
};
-const localizedTitles = {
- quick_start: { zh: "快速开始", en: "Quick Start" },
- plugin_management: { zh: "插件管理", en: "Plugin Management" },
- memory_as_file: { zh: "文件即记忆", en: "Memory as File" },
- memory_search: { zh: "记忆检索", en: "Memory Search" },
- auto_memory: { zh: "自动记忆", en: "Auto Memory" },
- auto_resource: { zh: "自动资料整理", en: "Auto Resource" },
- auto_link: { zh: "自动关联", en: "Auto Link" },
- auto_dream: { zh: "自动沉淀", en: "Auto Dream" },
- proactive: { zh: "主动发现", en: "Proactive" },
- reme_scene: { zh: "ReMe 应用场景", en: "ReMe Application Scenarios" },
- framework: { zh: "ReMe 代码框架", en: "ReMe Framework" },
- "reme-blog": { zh: "ReMe 博客", en: "ReMe Blog" },
- contributing: { zh: "开源与贡献", en: "Open Source and Contributing" },
+const jobGroups = {
+ version: "system",
+ app_config: "system",
+ chat: "system",
+ health_check: "system",
+ status: "system",
+ help: "system",
+ auto_dream: "memory",
+ auto_memory: "memory",
+ auto_memory_cc: "memory",
+ auto_resource: "memory",
+ proactive: "memory",
+ traverse: "retrieval",
+ graph_snapshot: "retrieval",
+ reindex: "retrieval",
+ search: "retrieval",
+ node_search: "retrieval",
+ daily_list: "daily",
+ daily_reindex: "daily",
+ daily_write: "daily",
+ frontmatter_delete: "files",
+ frontmatter_read: "files",
+ frontmatter_update: "files",
+ stat: "files",
+ list: "files",
+ move: "files",
+ delete: "files",
+ read: "files",
+ load: "files",
+ read_image: "files",
+ write: "files",
+ save: "files",
+ edit: "files",
};
-const productDocuments = [
- {
- slug: "typescript",
- source: "typescript",
- titles: { zh: "TypeScript Agent 集成", en: "TypeScript Agent Integrations" },
- descriptions: {
- zh: "配置统一 HTTP client,以及 DeepSeek Harness 和 OpenClaw 原生适配器。",
- en: "Configure the shared HTTP client and native DeepSeek Harness and OpenClaw adapters.",
- },
- group: "integration",
- },
- {
- slug: "studio",
- source: "reme_studio",
- titles: { zh: "ReMe 工作台", en: "ReMe Studio" },
- descriptions: {
- zh: "浏览、编辑和搜索本地记忆,并探索记忆图谱。",
- en: "Browse, edit, search, and explore local memory from the web workspace.",
- },
- group: "workspace",
- },
- {
- slug: "daily-paper",
- source: "plugins/daily_paper",
- titles: { zh: "每日论文插件", en: "Daily Paper Plugin" },
- descriptions: {
- zh: "发现论文、解析 PDF,并生成阅读笔记与每日简报。",
- en: "Discover papers, analyze PDFs, and produce reading notes and a daily brief.",
- },
- group: "plugins",
- },
- {
- slug: "auto-fin",
- source: "plugins/auto-fin",
- titles: { zh: "Auto Fin 插件", en: "Auto Fin Plugin" },
- descriptions: {
- zh: "结合最新财联社新闻与本地历史记忆生成研究报告。",
- en: "Research recent CLS news with historical context from local memory.",
- },
- group: "plugins",
- },
- {
- slug: "beam",
- source: "benchmark/beam",
- titles: { zh: "BEAM", en: "BEAM" },
- descriptions: {
- zh: "评测大规模记忆检索能力。",
- en: "Evaluate memory retrieval at scale.",
- },
- group: "benchmarks",
- },
- {
- slug: "longmemeval",
- source: "benchmark/longmemeval",
- titles: { zh: "LongMemEval", en: "LongMemEval" },
- descriptions: {
- zh: "评测跨会话长期记忆问答能力。",
- en: "Evaluate long-term, cross-session memory question answering.",
- },
- group: "benchmarks",
- },
- {
- slug: "pibench",
- source: "benchmark/pibench",
- titles: { zh: "π-Bench", en: "π-Bench" },
- descriptions: {
- zh: "评测带持久记忆的个人智能体。",
- en: "Evaluate personal agents with persistent memory.",
- },
- group: "benchmarks",
- },
- {
- slug: "toolmemory",
- source: "benchmark/toolmemory",
- titles: { zh: "Tool Memory / ExpG", en: "Tool Memory / ExpG" },
- descriptions: {
- zh: "通过经验驱动的自适应指导增强 Agent 工具使用。",
- en: "Improve agent tool use through experience-driven adaptive guidance.",
- },
- group: "benchmarks",
- },
-];
-
-const sharedDocuments = [
- {
- id: "agents-guide",
- path: "AGENTS.md",
- sourcePath: "AGENTS.md",
- titles: {
- zh: "Agent 开发指南",
- en: "Agent Development Guide",
- },
- description: "Repository contracts, lifecycle rules, safety boundaries, and validation.",
- group: "development",
- language: "shared",
- },
-];
-
-async function markdownTitle(filePath) {
- const source = await readFile(filePath, "utf8");
- return source.match(/^#\s+(.+)$/m)?.[1]?.replace(/[`*_]/g, "") || path.basename(filePath, ".md");
+function typeLabel(schema = {}) {
+ if (schema.oneOf) return schema.oneOf.map(typeLabel).join(" or ");
+ if (schema.type === "array") return `${typeLabel(schema.items || {})}[]`;
+ return schema.type || "any";
}
-async function buildManifest() {
- const documents = [
- {
- id: "readme-zh",
- path: "README_ZH.md",
- sourcePath: "README_ZH.md",
- title: "ReMe 项目介绍",
- description: "核心理念、快速开始、使用场景与社区入口。",
- group: "overview",
- language: "zh",
- },
- {
- id: "readme-en",
- path: "README.md",
- sourcePath: "README.md",
- title: "Introducing ReMe",
- description: "Core ideas, quick start, use cases, and community resources.",
- group: "overview",
- language: "en",
- },
- ];
+function markdownCell(value) {
+ if (value === undefined) return "—";
+ const rendered = typeof value === "string" ? value : JSON.stringify(value);
+ return rendered
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll("|", "\\|")
+ .replaceAll("\n", " ");
+}
- for (const language of ["zh", "en"]) {
- for (const topic of topicOrder) {
- const sourcePath = `docs/${language}/${topic}.md`;
- documents.push({
- id: `${language}-${topic}`,
- path: sourcePath,
- sourcePath,
- title: localizedTitles[topic]?.[language] || (await markdownTitle(path.join(repoDir, sourcePath))),
- description: "",
- group: groups[topic],
- language,
- });
- }
+function buildJobReference(config, language) {
+ const isZh = language === "zh";
+ const jobs = Object.entries(config.jobs || {}).filter(([, job]) => !["background", "cron"].includes(job.backend));
+ const sections = new Map();
- for (const product of productDocuments) {
- const filename = language === "zh" ? "README_ZH.md" : "README.md";
- documents.push({
- id: `${product.slug}-${language}`,
- path: `${product.source}/${filename}`,
- sourcePath: `${product.source}/${filename}`,
- title: product.titles[language],
- description: product.descriptions[language],
- group: product.group,
- language,
- });
- }
+ for (const [name, job] of jobs) {
+ const group = jobGroups[name] || "system";
+ if (!sections.has(group)) sections.set(group, []);
+ sections.get(group).push([name, job]);
}
- return [...documents, ...sharedDocuments].sort(
- (left, right) => navigationGroupOrder.indexOf(left.group) - navigationGroupOrder.indexOf(right.group),
- );
+ const lines = [
+ "---",
+ `title: ${isZh ? "Job API 参考" : "Job API Reference"}`,
+ `description: ${isZh ? "从默认配置自动生成的可调用 Job、参数和服务边界。" : "Callable jobs, parameters, and service boundaries generated from the default configuration."}`,
+ "---",
+ "",
+ `# ${isZh ? "Job API 参考" : "Job API Reference"}`,
+ "",
+ isZh
+ ? "本页从 `reme/config/default.yaml` 自动生成。它描述默认应用中的可调用 Job;插件和自定义配置可以增加、删除或覆盖 Job。运行 `reme help` 可查看当前服务的实际能力。"
+ : "This page is generated from `reme/config/default.yaml`. It describes callable jobs in the default application; plugins and custom configurations may add, remove, or override jobs. Run `reme help` to inspect the active service.",
+ "",
+ isZh
+ ? "> 后台 Job 和 Cron Job 不通过服务暴露,因此不列入调用参考。"
+ : "> Background and cron jobs are not service-exposed and are omitted from the callable reference.",
+ "",
+ ];
+
+ for (const [group, entries] of sections) {
+ lines.push(`## ${groupNames[language][group]}`, "");
+ for (const [name, job] of entries) {
+ const properties = job.parameters?.properties || {};
+ const required = new Set(job.parameters?.required || []);
+ lines.push(`### \`${name}\``, "", markdownCell(job.description || ""), "");
+ lines.push("```bash", `reme ${name}${Object.keys(properties).length ? " ..." : ""}`, "```", "");
+ if (!Object.keys(properties).length) {
+ lines.push(isZh ? "无参数。" : "No parameters.", "");
+ continue;
+ }
+ lines.push(
+ isZh
+ ? "| 参数 | 类型 | 必填 | 默认值 | 说明 |"
+ : "| Parameter | Type | Required | Default | Description |",
+ "|---|---|---:|---|---|",
+ );
+ for (const [parameter, schema] of Object.entries(properties)) {
+ lines.push(
+ `| \`${parameter}\` | \`${markdownCell(typeLabel(schema))}\` | ${required.has(parameter) ? (isZh ? "是" : "yes") : (isZh ? "否" : "no")} | ${markdownCell(schema.default)} | ${markdownCell(schema.description || "—")} |`,
+ );
+ }
+ lines.push("");
+ }
+ }
+ return `${lines.join("\n")}\n`;
}
await rm(path.join(siteDir, ".generated"), { recursive: true, force: true });
await mkdir(outputDir, { recursive: true });
-await cp(path.join(siteDir, "public", "favicon.svg"), path.join(siteDir, ".generated", "favicon.svg"));
-await cp(path.join(siteDir, "public", "CNAME"), path.join(siteDir, ".generated", "CNAME"));
-
-for (const file of ["README.md", "README_ZH.md", "AGENTS.md"]) {
- await cp(path.join(repoDir, file), path.join(outputDir, file));
-}
-await cp(path.join(repoDir, "docs"), path.join(outputDir, "docs"), {
+await cp(path.join(repoDir, "docs"), outputDir, {
recursive: true,
- filter: (source) => path.basename(source) !== ".DS_Store",
+ filter: (source) => ![".DS_Store", "plans"].includes(path.basename(source)),
});
-for (const product of productDocuments) {
- await mkdir(path.join(outputDir, product.source), { recursive: true });
- for (const filename of ["README.md", "README_ZH.md"]) {
- await cp(path.join(repoDir, product.source, filename), path.join(outputDir, product.source, filename));
- }
+await cp(path.join(siteDir, "public", "CNAME"), path.join(outputDir, "public", "CNAME"));
+
+const sourceMap = {};
+for (const [destination, source] of externalDocuments) {
+ const destinationPath = path.join(outputDir, destination);
+ await mkdir(path.dirname(destinationPath), { recursive: true });
+ await cp(path.join(repoDir, source), destinationPath);
+ sourceMap[destination] = source;
}
-await writeFile(
- path.join(outputDir, "manifest.json"),
- `${JSON.stringify({ documents: await buildManifest() }, null, 2)}\n`,
-);
+
+for (const language of ["zh", "en"]) {
+ await cp(
+ path.join(repoDir, "benchmark/toolmemory/gitcha.png"),
+ path.join(outputDir, language, "benchmarks", "gitcha.png"),
+ );
+}
+
+const defaultConfig = parseYaml(await readFile(path.join(repoDir, "reme/config/default.yaml"), "utf8"));
+for (const language of ["zh", "en"]) {
+ const destination = path.join(outputDir, language, "reference", "jobs.md");
+ await mkdir(path.dirname(destination), { recursive: true });
+ await writeFile(destination, buildJobReference(defaultConfig, language));
+ sourceMap[`${language}/reference/jobs.md`] = "reme/config/default.yaml";
+}
+
+await writeFile(path.join(outputDir, ".source-map.json"), `${JSON.stringify(sourceMap, null, 2)}\n`);
diff --git a/github-pages/scripts/verify-build.mjs b/github-pages/scripts/verify-build.mjs
new file mode 100644
index 00000000..cdf6df72
--- /dev/null
+++ b/github-pages/scripts/verify-build.mjs
@@ -0,0 +1,91 @@
+import assert from "node:assert/strict";
+import { access, readFile, readdir } from "node:fs/promises";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+const siteDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
+const outputDir = path.join(siteDir, "dist");
+
+async function collectFiles(directory, prefix = "") {
+ const files = [];
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
+ const relativePath = path.posix.join(prefix, entry.name);
+ if (entry.isDirectory()) files.push(...await collectFiles(path.join(directory, entry.name), relativePath));
+ else files.push(relativePath);
+ }
+ return files;
+}
+
+function pageUrl(relativePath) {
+ if (relativePath === "index.html") return "/";
+ if (relativePath.endsWith("/index.html")) return `/${relativePath.slice(0, -"index.html".length)}`;
+ return `/${relativePath.slice(0, -".html".length)}`;
+}
+
+function routeExists(pathname, files) {
+ const relativePath = decodeURIComponent(pathname).replace(/^\/+/, "");
+ if (!relativePath) return files.has("index.html");
+ if (relativePath.endsWith("/")) return files.has(`${relativePath}index.html`);
+ return files.has(relativePath) || files.has(`${relativePath}.html`) || files.has(`${relativePath}/index.html`);
+}
+
+const requiredFiles = [
+ "index.html",
+ "404.html",
+ "CNAME",
+ "favicon.svg",
+ "hashmap.json",
+ "sitemap.xml",
+ "llms.txt",
+ "llms-full.txt",
+ "zh/index.html",
+ "en/index.html",
+ "zh/configuration.html",
+ "en/configuration.html",
+ "zh/services.html",
+ "en/services.html",
+ "zh/reference/jobs.html",
+ "en/reference/jobs.html",
+ "zh/configuration/llms.txt",
+ "en/configuration/llms.txt",
+];
+
+for (const relativePath of requiredFiles) await access(path.join(outputDir, relativePath));
+
+assert.equal((await readFile(path.join(outputDir, "CNAME"), "utf8")).trim(), "reme.agentscope.io");
+
+const homepage = await readFile(path.join(outputDir, "index.html"), "utf8");
+assert.ok(homepage.includes('href="/en/"'), "root language switch must link to /en/");
+assert.ok(!homepage.includes('href="/en/ex"'), "root language switch must not produce /en/ex");
+assert.ok(homepage.includes('"studio-en":"/en/workspace/studio"'), "legacy redirects must be embedded");
+
+const sitemap = await readFile(path.join(outputDir, "sitemap.xml"), "utf8");
+assert.ok(sitemap.includes(""), "sitemap must include canonical-source update times");
+assert.ok(!sitemap.includes("https://reme.agentscope.io/"), "root redirect must not be indexed");
+assert.ok(!sitemap.includes('hreflang="zh-CN" href="https://reme.agentscope.io/"'), "root must not duplicate zh-CN");
+
+const ChineseConfiguration = await readFile(path.join(outputDir, "zh/configuration.html"), "utf8");
+assert.match(ChineseConfiguration, /搜索文档/);
+assert.match(ChineseConfiguration, /复制 Markdown/);
+assert.match(ChineseConfiguration, /在 GitHub 查看源文件/);
+
+const jobReference = await readFile(path.join(outputDir, "en/reference/jobs.html"), "utf8");
+assert.match(jobReference, /Job API Reference/);
+assert.match(jobReference, /auto_memory/);
+
+const outputFiles = new Set(await collectFiles(outputDir));
+const missingLinks = [];
+for (const relativePath of [...outputFiles].filter((file) => file.endsWith(".html"))) {
+ const html = await readFile(path.join(outputDir, relativePath), "utf8");
+ const currentUrl = new URL(pageUrl(relativePath), "https://reme-docs.local");
+ for (const match of html.matchAll(/]*\bhref="([^"]+)"/g)) {
+ const href = match[1].replaceAll("&", "&");
+ if (href.startsWith("#")) continue;
+ const target = new URL(href, currentUrl);
+ if (target.origin !== currentUrl.origin) continue;
+ if (!routeExists(target.pathname, outputFiles)) missingLinks.push(`${relativePath}: ${href}`);
+ }
+}
+assert.deepEqual(missingLinks, [], `missing internal links:\n${missingLinks.join("\n")}`);
+
+console.log(`Verified ${requiredFiles.length} documentation build artifacts.`);
diff --git a/github-pages/src/main.js b/github-pages/src/main.js
deleted file mode 100644
index 9397ce41..00000000
--- a/github-pages/src/main.js
+++ /dev/null
@@ -1,458 +0,0 @@
-import DOMPurify from "dompurify";
-import { marked } from "marked";
-import { stripMarkdownFrontmatter } from "./markdown.js";
-import "./styles.css";
-
-const baseUrl = import.meta.env.BASE_URL;
-const repositoryUrl = "https://github.com/agentscope-ai/ReMe";
-
-const copy = {
- zh: {
- docs: "文档",
- home: "首页",
- search: "搜索文档…",
- noResults: "没有找到匹配的文档",
- menu: "打开导航",
- toc: "本页目录",
- edit: "在 GitHub 查看源文件",
- quickStart: "快速开始",
- groups: {
- overview: "项目介绍",
- start: "开始使用",
- fundamentals: "核心原理",
- automation: "自动化能力",
- concepts: "架构与场景",
- integration: "Agent 集成",
- workspace: "工作区",
- plugins: "插件",
- benchmarks: "评测",
- development: "开发者规范",
- },
- },
- en: {
- docs: "Documentation",
- home: "Home",
- search: "Search documentation…",
- noResults: "No matching documents",
- menu: "Open navigation",
- toc: "On this page",
- edit: "View source on GitHub",
- quickStart: "Quick start",
- groups: {
- overview: "Introduction",
- start: "Get started",
- fundamentals: "Fundamentals",
- automation: "Automation",
- concepts: "Architecture & scenarios",
- integration: "Agent integration",
- workspace: "Workspace",
- plugins: "Plugins",
- benchmarks: "Benchmarks",
- development: "Development",
- },
- },
-};
-
-const state = {
- language: localStorage.getItem("reme-docs-language") || "zh",
- documents: [],
- activeDocument: null,
- query: "",
-};
-
-const homeCopy = {
- zh: {
- eyebrow: "LOCAL-FIRST · FILE-NATIVE",
- title: "让 Agent 真正记住,\n也让记忆始终属于你。",
- description: "ReMe 将对话和资料沉淀为可读、可编辑、可检索、相互链接的 Markdown,并提供从工作区管理到主动研究的一整套工具。",
- start: "快速开始",
- project: "了解 ReMe",
- explore: "按目标探索",
- exploreDescription: "选择你现在想完成的事情。每个入口都直接连接到对应的完整文档。",
- cards: [
- { id: "studio-zh", icon: "◫", label: "管理记忆", title: "ReMe 工作台", description: "在本地 Web 工作区中浏览、编辑、搜索记忆,并探索 wikilink 图谱。", tone: "mint" },
- { id: "daily-paper-zh", icon: "◌", label: "发现与分析", title: "每日论文插件", description: "从论文榜单筛选值得阅读的工作,解析 PDF,并生成笔记与五分钟简报。", tone: "blue" },
- { id: "auto-fin-zh", icon: "↗", label: "主题研究", title: "Auto Fin 插件", description: "连接最新财联社新闻和本地历史记忆,生成可追溯的研究报告。", tone: "amber" },
- ],
- benchmark: "验证记忆能力",
- benchmarkDescription: "从检索规模、跨会话问答、个人智能体到工具经验,查看 ReMe 的四套评测与复现实验。",
- benchmarkAction: "从 BEAM 开始",
- },
- en: {
- eyebrow: "LOCAL-FIRST · FILE-NATIVE",
- title: "Memory that works for agents.\nFiles that remain yours.",
- description: "ReMe turns conversations and resources into readable, editable, searchable, interconnected Markdown—with tools spanning workspace management and proactive research.",
- start: "Quick start",
- project: "Meet ReMe",
- explore: "Explore by goal",
- exploreDescription: "Start with what you want to accomplish. Every entry opens the complete guide.",
- cards: [
- { id: "studio-en", icon: "◫", label: "Manage memory", title: "ReMe Studio", description: "Browse, edit, and search memory in a local web workspace, then explore its wikilink graph.", tone: "mint" },
- { id: "daily-paper-en", icon: "◌", label: "Discover & analyze", title: "Daily Paper Plugin", description: "Select useful papers from rankings, analyze PDFs, and create notes plus a five-minute brief.", tone: "blue" },
- { id: "auto-fin-en", icon: "↗", label: "Research topics", title: "Auto Fin Plugin", description: "Connect recent CLS news with historical local memory to produce traceable research reports.", tone: "amber" },
- ],
- benchmark: "Validate memory systems",
- benchmarkDescription: "Explore four reproducible evaluations covering retrieval scale, cross-session QA, personal agents, and tool-use experience.",
- benchmarkAction: "Start with BEAM",
- },
-};
-
-const app = document.querySelector("#app");
-
-app.innerHTML = `
-
-
-
-`;
-
-const sidebar = app.querySelector(".sidebar");
-const docsShell = app.querySelector(".docs-shell");
-const documentNav = app.querySelector(".document-nav");
-const article = app.querySelector(".article");
-const toc = app.querySelector(".toc");
-const searchInput = app.querySelector("input[type='search']");
-const menuButton = app.querySelector(".menu-button");
-const backdrop = app.querySelector(".sidebar-backdrop");
-
-function slugify(value) {
- return value
- .toLowerCase()
- .trim()
- .replace(/<[^>]+>/g, "")
- .replace(/[^\p{Letter}\p{Number}]+/gu, "-")
- .replace(/^-|-$/g, "");
-}
-
-function resolveDocumentPath(currentPath, target) {
- const cleanTarget = target.split("#")[0].split("?")[0];
- const currentParts = currentPath.split("/");
- currentParts.pop();
- for (const part of cleanTarget.split("/")) {
- if (!part || part === ".") continue;
- if (part === "..") currentParts.pop();
- else currentParts.push(part);
- }
- return currentParts.join("/");
-}
-
-function configureMarkdown(document) {
- const renderer = new marked.Renderer();
- const headingIds = new Map();
-
- renderer.heading = ({ tokens, depth }) => {
- const text = tokens.map((token) => token.text || token.raw || "").join("");
- const baseSlug = slugify(text) || "section";
- const count = headingIds.get(baseSlug) || 0;
- headingIds.set(baseSlug, count + 1);
- const id = count ? `${baseSlug}-${count + 1}` : baseSlug;
- return `${text}`;
- };
-
- renderer.image = ({ href, title, text }) => {
- const url = /^(https?:|data:)/.test(href)
- ? href
- : `${baseUrl}content/${resolveDocumentPath(document.path, href)}`;
- const titleAttribute = title ? ` title="${title}"` : "";
- return `
`;
- };
-
- renderer.link = ({ href, title, tokens }) => {
- const label = tokens.map((token) => token.text || token.raw || "").join("");
- const titleAttribute = title ? ` title="${title}"` : "";
- if (href.startsWith("#")) return `${label}`;
- if (!/^(https?:|mailto:)/.test(href)) {
- const resolved = resolveDocumentPath(document.path, href);
- const localDocument = state.documents.find((item) => item.path === resolved);
- if (localDocument) return `${label}`;
- return `${label}`;
- }
- return `${label}`;
- };
-
- marked.use({ renderer, gfm: true, breaks: false });
-}
-
-function availableDocuments() {
- return state.documents.filter(
- (document) => document.language === state.language || document.language === "shared",
- );
-}
-
-function documentTitle(document) {
- return document.titles?.[state.language] || document.title;
-}
-
-function renderChrome() {
- const labels = copy[state.language];
- app.querySelector("[data-copy='docs']").textContent = labels.docs;
- const quickStartLink = app.querySelector("[data-copy='quickStart']");
- quickStartLink.textContent = `${labels.quickStart} →`;
- quickStartLink.href = `?doc=${state.language}-quick_start`;
- quickStartLink.dataset.doc = `${state.language}-quick_start`;
- searchInput.placeholder = labels.search;
- menuButton.textContent = labels.menu;
- document.documentElement.lang = state.language === "zh" ? "zh-CN" : "en";
- app.querySelectorAll("[data-language]").forEach((button) => {
- button.classList.toggle("active", button.dataset.language === state.language);
- });
-}
-
-function renderNavigation() {
- const labels = copy[state.language];
- const query = state.query.trim().toLocaleLowerCase();
- const filtered = availableDocuments().filter((document) =>
- `${documentTitle(document)} ${document.title || ""} ${document.description}`.toLocaleLowerCase().includes(query),
- );
- const groups = [...new Set(filtered.map((document) => document.group))];
-
- if (!filtered.length) {
- documentNav.innerHTML = `
- ${labels.home}
- ${labels.noResults}
- `;
- return;
- }
-
- documentNav.innerHTML = `
- ${labels.home}
- ` + groups
- .map(
- (group) => `
-
- ${labels.groups[group]}
- ${filtered
- .filter((document) => document.group === group)
- .map(
- (document) => `
-
- ${documentTitle(document)}
- `,
- )
- .join("")}
- `,
- )
- .join("");
-}
-
-function renderHome(pushHistory = true) {
- const labels = homeCopy[state.language];
- state.activeDocument = null;
- docsShell.classList.add("home-view");
- article.dataset.group = "home";
- renderNavigation();
- article.innerHTML = `
-
- ${labels.eyebrow}
- ${labels.title.replace("\n", "
")}
- ${labels.description}
-
-
-
- 01 / PRODUCT & PLUGINS
- ${labels.explore}
- ${labels.exploreDescription}
-
-
-
- `;
- toc.innerHTML = "";
- closeMenu();
- if (pushHistory) history.pushState({ home: true }, "", baseUrl);
- window.scrollTo({ top: 0, behavior: "instant" });
-}
-
-function renderToc() {
- const headings = [...article.querySelectorAll("h2, h3")];
- if (!headings.length) {
- toc.innerHTML = "";
- return;
- }
- toc.innerHTML = `
- ${copy[state.language].toc}
- ${headings
- .map(
- (heading) => `${heading.childNodes[0]?.textContent || heading.textContent}`,
- )
- .join("")}
- `;
-}
-
-function rewriteRenderedUrls(document) {
- article.querySelectorAll("img[src]").forEach((image) => {
- const source = image.getAttribute("src");
- if (source && !/^(https?:|data:|\/)/.test(source)) {
- image.src = `${baseUrl}content/${resolveDocumentPath(document.path, source)}`;
- }
- });
-
- article.querySelectorAll("a[href]").forEach((link) => {
- const href = link.getAttribute("href");
- if (!href || /^(https?:|mailto:|#|\/)/.test(href) || link.dataset.doc) return;
- const resolved = resolveDocumentPath(document.path, href);
- const localDocument = state.documents.find((item) => item.path === resolved);
- if (localDocument) {
- link.href = `?doc=${localDocument.id}`;
- link.dataset.doc = localDocument.id;
- link.removeAttribute("target");
- return;
- }
- link.href = `${repositoryUrl}/blob/main/${resolved}`;
- link.target = "_blank";
- link.rel = "noreferrer";
- });
-}
-
-async function openDocument(id, pushHistory = true) {
- const fallbackId = state.language === "zh" ? "readme-zh" : "readme-en";
- const document = state.documents.find((item) => item.id === id) || state.documents.find((item) => item.id === fallbackId);
- if (document.language !== "shared" && document.language !== state.language) {
- state.language = document.language;
- localStorage.setItem("reme-docs-language", state.language);
- renderChrome();
- }
- state.activeDocument = document;
- docsShell.classList.remove("home-view");
- article.dataset.group = document.group;
- renderNavigation();
- article.innerHTML = ``;
-
- const response = await fetch(`${baseUrl}content/${document.path}`);
- if (!response.ok) throw new Error(`Unable to load ${document.path}`);
- configureMarkdown(document);
- const markdown = stripMarkdownFrontmatter(await response.text());
- const body = DOMPurify.sanitize(await marked.parse(markdown), {
- ADD_ATTR: ["target"],
- });
- article.innerHTML = `
-
- ${copy[state.language].groups[document.group]}
- ·
- ${document.sourcePath}
-
- ${body}
-
- `;
- rewriteRenderedUrls(document);
- renderToc();
- closeMenu();
- if (pushHistory) history.pushState({ doc: document.id }, "", `?doc=${document.id}`);
- window.scrollTo({ top: 0, behavior: "instant" });
-}
-
-function closeMenu() {
- sidebar.classList.remove("open");
- backdrop.classList.remove("visible");
- menuButton.setAttribute("aria-expanded", "false");
-}
-
-function toggleMenu() {
- const open = !sidebar.classList.contains("open");
- sidebar.classList.toggle("open", open);
- backdrop.classList.toggle("visible", open);
- menuButton.setAttribute("aria-expanded", String(open));
-}
-
-app.addEventListener("click", (event) => {
- const homeLink = event.target.closest("[data-home]");
- if (homeLink) {
- event.preventDefault();
- renderHome();
- return;
- }
- const documentLink = event.target.closest("[data-doc]");
- if (documentLink) {
- event.preventDefault();
- openDocument(documentLink.dataset.doc);
- }
- if (event.target.closest("[data-action='menu']")) toggleMenu();
- const languageButton = event.target.closest("[data-language]");
- if (languageButton && languageButton.dataset.language !== state.language) {
- state.language = languageButton.dataset.language;
- localStorage.setItem("reme-docs-language", state.language);
- state.query = "";
- searchInput.value = "";
- renderChrome();
- renderHome();
- }
-});
-
-searchInput.addEventListener("input", () => {
- state.query = searchInput.value;
- renderNavigation();
-});
-
-document.addEventListener("keydown", (event) => {
- if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
- event.preventDefault();
- searchInput.focus();
- }
- if (event.key === "Escape") closeMenu();
-});
-
-backdrop.addEventListener("click", closeMenu);
-window.addEventListener("popstate", (event) => {
- const id = event.state?.doc || new URLSearchParams(location.search).get("doc");
- if (id) openDocument(id, false);
- else renderHome(false);
-});
-
-const manifest = await fetch(`${baseUrl}content/manifest.json`).then((response) => response.json());
-state.documents = manifest.documents;
-renderChrome();
-const initialDocument = new URLSearchParams(location.search).get("doc");
-if (initialDocument) await openDocument(initialDocument, false);
-else renderHome(false);
diff --git a/github-pages/src/markdown.js b/github-pages/src/markdown.js
deleted file mode 100644
index ef81a773..00000000
--- a/github-pages/src/markdown.js
+++ /dev/null
@@ -1,6 +0,0 @@
-const FRONTMATTER_PATTERN = /^\uFEFF?---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;
-
-/** Remove a leading YAML frontmatter block before rendering Markdown. */
-export function stripMarkdownFrontmatter(markdown) {
- return markdown.replace(FRONTMATTER_PATTERN, "");
-}
diff --git a/github-pages/src/styles.css b/github-pages/src/styles.css
deleted file mode 100644
index 7b3ee4ad..00000000
--- a/github-pages/src/styles.css
+++ /dev/null
@@ -1,200 +0,0 @@
-:root {
- color: #17221d;
- background: #f4f7f5;
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- --ink: #17221d;
- --muted: #65716a;
- --line: #dce5e0;
- --paper: #ffffff;
- --green: #087f6a;
- --blue: #3156d9;
- --green-soft: #e5f5ef;
- --code: #f3f5f2;
-}
-
-* { box-sizing: border-box; }
-html { scroll-behavior: smooth; scroll-padding-top: 92px; }
-body {
- margin: 0;
- min-width: 320px;
- background:
- radial-gradient(circle at 8% 9%, rgba(27, 193, 164, 0.06), transparent 26rem),
- #f4f7f5;
-}
-button, input { font: inherit; }
-a { color: inherit; }
-
-.topbar {
- position: fixed;
- inset: 0 0 auto 0;
- z-index: 30;
- height: 66px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 0 28px;
- border-bottom: 1px solid rgba(213, 225, 219, 0.85);
- background: rgba(250, 252, 251, 0.88);
- backdrop-filter: blur(18px) saturate(140%);
-}
-
-.brand { display: flex; align-items: center; gap: 11px; color: var(--ink); text-decoration: none; font-weight: 760; }
-.brand-mark {
- display: grid;
- place-items: center;
- width: 34px;
- height: 34px;
- border-radius: 11px;
- color: white;
- background: linear-gradient(145deg, #19c9b0, #3156d9 82%);
- box-shadow: 0 7px 18px rgba(24, 123, 114, 0.2);
- font-family: Georgia, serif;
- font-size: 21px;
-}
-.brand-divider { width: 1px; height: 20px; background: var(--line); margin-left: 2px; }
-.brand-section { color: var(--muted); font-weight: 520; }
-.top-actions { display: flex; align-items: center; gap: 18px; }
-.github-link, .quick-start-link { color: #37443d; text-decoration: none; font-size: 13px; font-weight: 650; }
-.github-link:hover, .quick-start-link:hover { color: var(--green); }
-.quick-start-link { padding: 8px 12px; border: 1px solid #d7e5df; border-radius: 9px; background: rgba(255, 255, 255, 0.72); }
-.language-switch { display: flex; padding: 3px; border: 1px solid var(--line); border-radius: 9px; background: #f5f7f4; }
-.language-switch button { padding: 5px 9px; border: 0; border-radius: 6px; color: var(--muted); background: transparent; cursor: pointer; font-size: 12px; font-weight: 700; }
-.language-switch button.active { color: var(--ink); background: white; box-shadow: 0 1px 3px rgba(20, 40, 30, 0.1); }
-.menu-button { display: none; border: 1px solid var(--line); border-radius: 8px; background: white; padding: 7px 10px; cursor: pointer; }
-
-.docs-shell { display: grid; grid-template-columns: 276px minmax(0, 1fr) 224px; max-width: 1540px; min-height: 100vh; margin: 0 auto; padding-top: 66px; }
-.docs-shell.home-view { grid-template-columns: 276px minmax(0, 1fr); }
-.docs-shell.home-view .toc-panel { display: none; }
-.sidebar { position: sticky; top: 66px; height: calc(100vh - 66px); padding: 25px 20px 18px; overflow-y: auto; border-right: 1px solid var(--line); background: rgba(247, 250, 248, 0.78); }
-.search-box { display: flex; align-items: center; gap: 8px; height: 41px; padding: 0 11px; border: 1px solid #d8e3dd; border-radius: 11px; color: #7a857e; background: rgba(255, 255, 255, 0.84); box-shadow: 0 5px 18px rgba(29, 65, 48, 0.035); }
-.search-box:focus-within { border-color: #78aa8e; box-shadow: 0 0 0 3px rgba(22, 120, 76, 0.1); }
-.search-box input { width: 100%; border: 0; outline: 0; color: var(--ink); background: transparent; font-size: 13px; }
-.search-box kbd { padding: 2px 5px; border: 1px solid var(--line); border-radius: 4px; background: #f7f8f6; font-size: 10px; }
-.document-nav { padding: 12px 0 52px; }
-.home-link { position: relative; display: block; margin-top: 9px; padding: 9px 10px 9px 13px; border-radius: 8px; color: #536058; text-decoration: none; font-size: 13px; }
-.home-link:hover { color: var(--ink); background: #f0f3ef; }
-.home-link.active { color: #086b5a; background: linear-gradient(90deg, #dff3ec, #eaf6f2); font-weight: 700; }
-.nav-group { margin-top: 21px; }
-.nav-group h2 { margin: 0 10px 7px; color: #8a948e; font-size: 10px; font-weight: 800; letter-spacing: 0.11em; text-transform: uppercase; }
-.nav-group a { position: relative; display: block; padding: 7px 10px 7px 13px; border-radius: 8px; color: #536058; text-decoration: none; font-size: 13px; line-height: 1.4; }
-.nav-group a:hover { color: var(--ink); background: #f0f3ef; }
-.nav-group a.active { color: #086b5a; background: linear-gradient(90deg, #dff3ec, #eaf6f2); font-weight: 700; }
-.nav-group a.active::before { position: absolute; top: 9px; bottom: 9px; left: 0; width: 3px; border-radius: 3px; background: linear-gradient(#17b79d, #3470d8); content: ""; }
-.empty-state { padding: 24px 10px; color: var(--muted); font-size: 13px; }
-.sidebar-footer { position: sticky; bottom: -18px; display: flex; align-items: center; gap: 8px; margin: 0 -20px; padding: 14px 22px 18px; border-top: 1px solid var(--line); color: #7c8880; background: #f7faf8; font: 600 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.04em; text-transform: uppercase; }
-.status-dot { width: 6px; height: 6px; border-radius: 50%; background: #29a869; box-shadow: 0 0 0 3px #dff3e8; }
-
-.article-wrap { min-width: 0; padding: 58px clamp(32px, 5.8vw, 86px) 100px; background: rgba(255, 255, 255, 0.94); }
-.article { width: 100%; max-width: 820px; margin: 0 auto; }
-.article[data-group="home"] { max-width: 980px; }
-.home-hero { padding: 34px 0 76px; }
-.home-eyebrow, .section-kicker { margin: 0 0 17px; color: #12806d; font: 750 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.13em; }
-.home-hero h1 { margin: 0; color: #102019; font-size: clamp(46px, 6.3vw, 76px); line-height: 1.15; letter-spacing: -0.055em; }
-.home-lead { margin: 27px 0 0; color: #526159; font-size: 18px; line-height: 1.72; }
-.home-actions { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 31px; }
-.home-actions a { padding: 11px 17px; border-radius: 10px; text-decoration: none; font-size: 14px; font-weight: 720; }
-.primary-action { color: white; background: #087f6a; box-shadow: 0 8px 22px rgba(8, 127, 106, 0.2); }
-.secondary-action { border: 1px solid #d5e2dc; color: #34443c; background: white; }
-.home-explore { padding-top: 58px; border-top: 1px solid var(--line); }
-.home-explore h2, .benchmark-callout h2 { margin: 0; color: #15251d; font-size: 30px; letter-spacing: -0.025em; }
-.section-lead { max-width: 620px; margin: 10px 0 25px; color: var(--muted); line-height: 1.65; }
-.feature-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
-.feature-card { position: relative; display: flex; min-height: 260px; flex-direction: column; padding: 23px; overflow: hidden; border: 1px solid #dce8e2; border-radius: 16px; color: var(--ink); background: linear-gradient(155deg, #fff, #f4faf7); text-decoration: none; transition: transform 160ms ease, box-shadow 160ms ease; }
-.feature-card:hover { transform: translateY(-3px); box-shadow: 0 16px 34px rgba(29, 68, 49, 0.1); }
-.feature-card.blue { background: linear-gradient(155deg, #fff, #f1f5ff); }
-.feature-card.amber { background: linear-gradient(155deg, #fff, #fbf7ec); }
-.feature-icon { display: grid; place-items: center; width: 42px; height: 42px; margin-bottom: 32px; border-radius: 12px; color: #08705e; background: #dbf2ea; font-size: 22px; }
-.blue .feature-icon { color: #3156b8; background: #e5ebff; }
-.amber .feature-icon { color: #9b6818; background: #f8eac8; }
-.feature-label { margin-bottom: 7px; color: #718078; font: 700 10px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
-.feature-card strong { font-size: 20px; }
-.feature-description { margin-top: 10px; color: #66736c; font-size: 13px; line-height: 1.6; }
-.feature-arrow { position: absolute; right: 22px; bottom: 18px; color: #6a7870; font-size: 19px; }
-.benchmark-callout { display: flex; align-items: end; justify-content: space-between; gap: 35px; margin-top: 62px; padding: 36px; border-radius: 17px; color: white; background: linear-gradient(125deg, #142a22, #1c473b); }
-.benchmark-callout .section-kicker { color: #74d4bb; }
-.benchmark-callout h2 { color: white; }
-.benchmark-callout p:not(.section-kicker) { max-width: 610px; margin: 10px 0 0; color: #c3d4cd; line-height: 1.65; }
-.benchmark-callout > a { flex: none; padding: 10px 14px; border: 1px solid rgba(255,255,255,.25); border-radius: 9px; color: white; text-decoration: none; font-size: 13px; font-weight: 700; }
-.article-meta { display: flex; gap: 8px; margin-bottom: 22px; color: #7d8d84; font: 600 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; }
-.article-meta span:first-child { padding: 3px 8px; border-radius: 999px; color: #08705e; background: #e6f5ef; }
-.markdown-body { color: #27332d; font-size: 16px; line-height: 1.78; }
-.markdown-body > :first-child { margin-top: 0; }
-.markdown-body h1 { margin: 0 0 30px; color: #112019; font-size: clamp(36px, 5vw, 54px); line-height: 1.06; letter-spacing: -0.04em; }
-.markdown-body h2 { margin: 58px 0 18px; padding-top: 4px; color: #14241c; font-size: 27px; line-height: 1.25; letter-spacing: -0.02em; }
-.markdown-body h3 { margin: 35px 0 12px; color: #1f3027; font-size: 20px; line-height: 1.35; }
-.markdown-body p, .markdown-body ul, .markdown-body ol { margin: 14px 0; }
-.markdown-body li { margin: 5px 0; }
-.markdown-body a { color: var(--green); text-decoration-color: #9cc8ae; text-underline-offset: 3px; }
-.markdown-body a:hover { text-decoration-color: var(--green); }
-.markdown-body img { display: block; max-width: 100%; height: auto; margin: 30px auto; border-radius: 14px; }
-/* README badges are linked images. Keep them in a compact row instead of applying the figure layout above. */
-.article[data-group="overview"] .markdown-body > p:has(> a > img[src*="img.shields.io"]) {
- display: flex;
- flex-wrap: wrap;
- justify-content: center;
- gap: 7px;
- max-width: 690px;
- margin: 20px auto;
-}
-.article[data-group="overview"] .markdown-body > p > a > img[src*="img.shields.io"] {
- display: inline-block;
- width: auto;
- max-height: 24px;
- margin: 0;
- border-radius: 4px;
- vertical-align: middle;
-}
-.markdown-body p[align="center"] { text-align: center; }
-.article[data-group="overview"] .markdown-body > p:first-child img { max-width: min(470px, 72%); margin-top: 8px; filter: drop-shadow(0 18px 25px rgba(44, 85, 164, 0.1)); }
-.markdown-body code { padding: 2px 5px; border-radius: 5px; background: var(--code); color: #315844; font: 0.88em/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
-.markdown-body pre { margin: 24px 0; padding: 19px 21px; overflow-x: auto; border: 1px solid #dce5e0; border-radius: 12px; background: linear-gradient(145deg, #f5f8f6, #f8faf9); box-shadow: inset 3px 0 0 #7bd0b6; }
-.markdown-body pre code { padding: 0; color: #263b30; background: none; font-size: 13px; }
-.markdown-body blockquote { margin: 24px 0; padding: 4px 20px; border-left: 3px solid #68aa85; color: #53635a; background: #f5faf7; }
-.markdown-body table { display: block; width: 100%; margin: 24px 0; overflow-x: auto; border-collapse: collapse; font-size: 14px; }
-.markdown-body th, .markdown-body td { padding: 10px 13px; border: 1px solid var(--line); text-align: left; }
-.markdown-body th { background: #f4f6f3; }
-.markdown-body hr { margin: 44px 0; border: 0; border-top: 1px solid var(--line); }
-.article-footer { margin-top: 70px; padding-top: 20px; border-top: 1px solid var(--line); }
-.article-footer a { color: var(--muted); text-decoration: none; font-size: 13px; }
-.article-footer a:hover { color: var(--green); }
-.loading-line { width: 55%; height: 12px; margin-top: 40px; border-radius: 9px; background: linear-gradient(90deg, #edf0ec, #f8faf7, #edf0ec); background-size: 200% 100%; animation: loading 1.2s infinite; }
-@keyframes loading { to { background-position: -200% 0; } }
-
-.toc-panel { position: sticky; top: 66px; height: calc(100vh - 66px); padding: 58px 24px; overflow-y: auto; border-left: 1px solid #e9efeb; background: rgba(252, 253, 252, 0.92); }
-.toc h2 { margin: 0 0 12px; color: #8a948e; font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; }
-.toc a { display: block; padding: 5px 0; color: #7a857e; text-decoration: none; font-size: 12px; line-height: 1.45; }
-.toc a:hover { color: var(--green); }
-.toc .toc-h3 { padding-left: 12px; }
-.sidebar-backdrop { display: none; }
-
-@media (max-width: 1120px) {
- .docs-shell { grid-template-columns: 250px minmax(0, 1fr); }
- .toc-panel { display: none; }
-}
-
-@media (max-width: 760px) {
- .topbar { height: 60px; padding: 0 16px; }
- .brand-section, .brand-divider, .github-link { display: none; }
- .quick-start-link { font-size: 12px; }
- .menu-button { display: block; max-width: 112px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
- .top-actions { gap: 9px; }
- .docs-shell { display: block; padding-top: 60px; }
- .sidebar { position: fixed; z-index: 25; top: 60px; bottom: 0; left: 0; width: min(310px, 86vw); height: auto; transform: translateX(-105%); transition: transform 180ms ease; box-shadow: 16px 0 35px rgba(20, 40, 30, 0.12); }
- .sidebar.open { transform: translateX(0); }
- .sidebar-backdrop { position: fixed; z-index: 20; inset: 60px 0 0; width: 100%; border: 0; background: rgba(18, 30, 23, 0.35); }
- .sidebar-backdrop.visible { display: block; }
- .article-wrap { padding: 38px 20px 72px; }
- .article-meta { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
- .markdown-body { font-size: 15px; }
- .markdown-body h1 { font-size: 34px; }
- .markdown-body h2 { margin-top: 46px; font-size: 24px; }
- .article[data-group="overview"] .markdown-body > p:first-child img { max-width: 84%; }
- .home-hero { padding: 20px 0 54px; }
- .home-hero h1 { font-size: 43px; }
- .home-lead { font-size: 16px; }
- .feature-grid { grid-template-columns: 1fr; }
- .feature-card { min-height: 225px; }
- .benchmark-callout { align-items: flex-start; flex-direction: column; padding: 28px 24px; }
-}
diff --git a/github-pages/tests/content-manifest.test.mjs b/github-pages/tests/content-manifest.test.mjs
deleted file mode 100644
index bc1a8a0b..00000000
--- a/github-pages/tests/content-manifest.test.mjs
+++ /dev/null
@@ -1,23 +0,0 @@
-import assert from "node:assert/strict";
-import { readFile } from "node:fs/promises";
-import test from "node:test";
-
-const manifestUrl = new URL("../.generated/content/manifest.json", import.meta.url);
-
-test("omits retired Agent documents and places Agent integration after getting started", async () => {
- const manifest = JSON.parse(await readFile(manifestUrl, "utf8"));
- const documents = manifest.documents;
- const groups = [...new Set(documents.map((document) => document.group))];
-
- assert.equal(documents.some((document) => document.id === "reme-memory-skill"), false);
- assert.equal(documents.some((document) => document.sourcePath.endsWith("agent_integration_plan.md")), false);
- assert.deepEqual(
- documents
- .filter((document) => document.group === "plugins")
- .map((document) => document.title || document.titles?.en),
- ["每日论文插件", "Auto Fin 插件", "Daily Paper Plugin", "Auto Fin Plugin"],
- );
- assert.equal(documents.some((document) => document.group === "cookbooks"), false);
- assert.ok(groups.indexOf("integration") > groups.indexOf("start"));
- assert.ok(groups.indexOf("integration") < groups.indexOf("fundamentals"));
-});
diff --git a/github-pages/tests/generated-content.test.mjs b/github-pages/tests/generated-content.test.mjs
new file mode 100644
index 00000000..cf699a5d
--- /dev/null
+++ b/github-pages/tests/generated-content.test.mjs
@@ -0,0 +1,90 @@
+import assert from "node:assert/strict";
+import { access, readFile } from "node:fs/promises";
+import path from "node:path";
+import test from "node:test";
+import { fileURLToPath } from "node:url";
+import { parse as parseYaml } from "yaml";
+import { legacyRoutes } from "../../docs/.vitepress/legacy-routes.mjs";
+
+const siteDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
+const repoDir = path.resolve(siteDir, "..");
+const generatedDir = path.join(siteDir, ".generated", "site");
+
+test("generates every required bilingual guide", async () => {
+ const names = [
+ "configuration.md",
+ "services.md",
+ "operations.md",
+ "integrations.md",
+ "plugin_development.md",
+ "faq.md",
+ "reference/cli.md",
+ "reference/jobs.md",
+ ];
+ for (const language of ["zh", "en"]) {
+ for (const name of names) await access(path.join(generatedDir, language, name));
+ }
+ await access(path.join(generatedDir, "zh/integrations/claude-code.md"));
+ await access(path.join(generatedDir, "en/integrations/claude-code.md"));
+ await access(path.join(generatedDir, "zh/integrations/hermes.md"));
+ await access(path.join(generatedDir, "en/integrations/hermes.md"));
+});
+
+test("maps mirrored pages back to their canonical repository sources", async () => {
+ const sourceMap = JSON.parse(await readFile(path.join(generatedDir, ".source-map.json"), "utf8"));
+ assert.equal(sourceMap["zh/integrations/typescript.md"], "typescript/README_ZH.md");
+ assert.equal(sourceMap["en/integrations/claude-code.md"], "integrations/claude_code/README.md");
+ assert.equal(sourceMap["en/integrations/hermes.md"], "integrations/hermes_agent/README.md");
+ assert.equal(sourceMap["en/workspace/studio.md"], "reme_studio/README.md");
+ assert.equal(sourceMap["zh/plugins/lme.md"], "plugins/lme/README_ZH.md");
+ assert.equal(sourceMap["en/reference/jobs.md"], "reme/config/default.yaml");
+});
+
+test("generates the callable Job reference from default.yaml", async () => {
+ const config = parseYaml(await readFile(path.join(repoDir, "reme/config/default.yaml"), "utf8"));
+ const callableJobs = Object.entries(config.jobs)
+ .filter(([, job]) => !["background", "cron"].includes(job.backend))
+ .map(([name]) => name);
+
+ for (const language of ["zh", "en"]) {
+ const reference = await readFile(path.join(generatedDir, language, "reference", "jobs.md"), "utf8");
+ for (const job of callableJobs) assert.ok(reference.includes(`### ${"`"}${job}${"`"}`), job);
+ }
+});
+
+test("keeps generated content disposable and excludes internal plans", async () => {
+ await assert.rejects(access(path.join(generatedDir, "plans")));
+ await access(path.join(generatedDir, ".vitepress", "config.mts"));
+ await access(path.join(generatedDir, "public", "favicon.svg"));
+ assert.equal(
+ (await readFile(path.join(generatedDir, "public", "CNAME"), "utf8")).trim(),
+ "reme.agentscope.io",
+ );
+});
+
+test("maps every legacy query-string document ID to a generated page", async () => {
+ assert.equal(Object.keys(legacyRoutes).length, 45);
+ assert.equal(legacyRoutes["studio-en"], "/en/workspace/studio");
+ assert.equal(legacyRoutes["en-quick_start"], "/en/quick_start");
+ assert.equal(legacyRoutes["agents-guide"], "https://github.com/agentscope-ai/ReMe/blob/main/AGENTS.md");
+
+ for (const [id, route] of Object.entries(legacyRoutes)) {
+ if (route.startsWith("https://")) continue;
+ assert.match(route, /^\/(?:zh|en)\//, id);
+ const relative = route.endsWith("/") ? `${route.slice(1)}index.md` : `${route.slice(1)}.md`;
+ await access(path.join(generatedDir, relative));
+ }
+});
+
+test("tracks every generated input in documentation CI and deployment", async () => {
+ const requiredPaths = [
+ "reme/config/default.yaml",
+ "integrations/claude_code/README.md",
+ "integrations/hermes_agent/README.md",
+ "benchmark/toolmemory/gitcha.png",
+ ];
+ for (const workflow of ["ci-docs.yml", "deploy-docs.yml"]) {
+ const source = await readFile(path.join(repoDir, ".github/workflows", workflow), "utf8");
+ for (const requiredPath of requiredPaths) assert.ok(source.includes(requiredPath), `${workflow}: ${requiredPath}`);
+ }
+});
diff --git a/github-pages/tests/markdown.test.mjs b/github-pages/tests/markdown.test.mjs
deleted file mode 100644
index 129b6190..00000000
--- a/github-pages/tests/markdown.test.mjs
+++ /dev/null
@@ -1,15 +0,0 @@
-import assert from "node:assert/strict";
-import test from "node:test";
-import { stripMarkdownFrontmatter } from "../src/markdown.js";
-
-test("strips leading YAML frontmatter before rendering", () => {
- assert.equal(
- stripMarkdownFrontmatter("---\nname: reme_memory\ndescription: Memory skill\n---\n\n# ReMe Memory\n"),
- "\n# ReMe Memory\n",
- );
-});
-
-test("preserves Markdown without frontmatter", () => {
- const markdown = "# ReMe Memory\n\nContent\n";
- assert.equal(stripMarkdownFrontmatter(markdown), markdown);
-});
diff --git a/github-pages/vite.config.js b/github-pages/vite.config.js
deleted file mode 100644
index 1445f872..00000000
--- a/github-pages/vite.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { defineConfig } from "vite";
-
-export default defineConfig({
- base: "./",
- publicDir: ".generated",
- build: {
- outDir: "dist",
- emptyOutDir: true,
- },
-});